11import { ChevronRightIcon } from "@heroicons/react/24/solid" ;
22import { Link } from "@remix-run/react" ;
3- import React , { ReactNode , forwardRef , useState } from "react" ;
3+ import React , { ReactNode , forwardRef , useState , useContext , createContext } from "react" ;
44import { cn } from "~/utils/cn" ;
55import { Popover , PopoverContent , PopoverVerticalEllipseTrigger } from "./Popover" ;
66import { InfoIconTooltip } from "./Tooltip" ;
77
8+ const variants = {
9+ bright : {
10+ header : "bg-background-bright" ,
11+ cell : "group-hover/table-row:bg-charcoal-750 group-has-[[tabindex='0']:focus]/table-row:bg-charcoal-750" ,
12+ stickyCell : "bg-background-bright group-hover/table-row:bg-charcoal-750" ,
13+ menuButton :
14+ "bg-background-bright group-hover/table-row:bg-charcoal-750 group-hover/table-row:ring-charcoal-600/70 group-has-[[tabindex='0']:focus]/table-row:bg-charcoal-750" ,
15+ menuButtonDivider : "group-hover/table-row:border-charcoal-600/70" ,
16+ rowSelected : "bg-charcoal-750 group-hover/table-row:bg-charcoal-750" ,
17+ } ,
18+ dimmed : {
19+ header : "bg-background-dimmed" ,
20+ cell : "group-hover/table-row:bg-charcoal-800 group-has-[[tabindex='0']:focus]/table-row:bg-background-bright" ,
21+ stickyCell : "group-hover/table-row:bg-charcoal-800" ,
22+ menuButton :
23+ "bg-background-dimmed group-hover/table-row:bg-charcoal-800 group-hover/table-row:ring-grid-bright group-has-[[tabindex='0']:focus]/table-row:bg-background-bright" ,
24+ menuButtonDivider : "group-hover/table-row:border-grid-dimmed" ,
25+ rowSelected : "bg-charcoal-750 group-hover/table-row:bg-charcoal-750" ,
26+ } ,
27+ } as const ;
28+
29+ export type TableVariant = keyof typeof variants ;
30+
831type TableProps = {
932 containerClassName ?: string ;
1033 className ?: string ;
1134 children : ReactNode ;
1235 fullWidth ?: boolean ;
1336} ;
1437
15- export const Table = forwardRef < HTMLTableElement , TableProps > (
16- ( { className, containerClassName, children, fullWidth } , ref ) => {
38+ // Add TableContext
39+ const TableContext = createContext < { variant : TableVariant } > ( { variant : "dimmed" } ) ;
40+
41+ export const Table = forwardRef < HTMLTableElement , TableProps & { variant ?: TableVariant } > (
42+ ( { className, containerClassName, children, fullWidth, variant = "dimmed" } , ref ) => {
1743 return (
18- < div
19- className = { cn (
20- "overflow-x-auto whitespace-nowrap border-t border-grid-bright scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" ,
21- containerClassName ,
22- fullWidth && "w-full"
23- ) }
24- >
25- < table ref = { ref } className = { cn ( "w-full" , className ) } >
26- { children }
27- </ table >
28- </ div >
44+ < TableContext . Provider value = { { variant } } >
45+ < div
46+ className = { cn (
47+ "overflow-x-auto whitespace-nowrap border-t scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" ,
48+ containerClassName ,
49+ fullWidth && "w-full"
50+ ) }
51+ >
52+ < table ref = { ref } className = { cn ( "w-full" , className ) } >
53+ { children }
54+ </ table >
55+ </ div >
56+ </ TableContext . Provider >
2957 ) ;
3058 }
3159) ;
3260
3361type TableHeaderProps = {
3462 className ?: string ;
3563 children : ReactNode ;
64+ variant ?: TableVariant ;
3665} ;
3766
38- export const TableHeader = forwardRef < HTMLTableSectionElement , TableHeaderProps > (
67+ export const TableHeader = forwardRef < HTMLTableSectionElement , Omit < TableHeaderProps , "variant" > > (
3968 ( { className, children } , ref ) => {
69+ const { variant } = useContext ( TableContext ) ;
4070 return (
4171 < thead
4272 ref = { ref }
4373 className = { cn (
44- "sticky top-0 z-10 bg-background-dimmed after:absolute after:bottom-0 after:left-0 after:right-0 after:h-px after:bg-grid-bright" ,
74+ "sticky top-0 z-10 after:absolute after:bottom-0 after:left-0 after:right-0 after:h-px after:bg-grid-bright" ,
75+ variants [ variant ] . header ,
4576 className
4677 ) }
4778 >
@@ -71,18 +102,19 @@ type TableRowProps = {
71102 children : ReactNode ;
72103 disabled ?: boolean ;
73104 isSelected ?: boolean ;
105+ variant ?: TableVariant ;
74106} ;
75107
76- export const TableRow = forwardRef < HTMLTableRowElement , TableRowProps > (
108+ export const TableRow = forwardRef < HTMLTableRowElement , Omit < TableRowProps , "variant" > > (
77109 ( { className, disabled, isSelected, children } , ref ) => {
110+ const { variant } = useContext ( TableContext ) ;
78111 return (
79112 < tr
80113 ref = { ref }
81114 className = { cn (
82115 "group/table-row relative w-full cursor-pointer outline-none after:absolute after:bottom-0 after:left-3 after:right-0 after:h-px after:bg-grid-dimmed" ,
83- "has-[[tabindex='0']:focus]:bg-background-bright" ,
116+ isSelected && variants [ variant ] . rowSelected ,
84117 disabled && "opacity-50" ,
85- isSelected && isSelectedStyle ,
86118 className
87119 ) }
88120 >
@@ -95,7 +127,7 @@ export const TableRow = forwardRef<HTMLTableRowElement, TableRowProps>(
95127type TableCellBasicProps = {
96128 className ?: string ;
97129 alignment ?: "left" | "center" | "right" ;
98- children : ReactNode ;
130+ children ? : ReactNode ;
99131 colSpan ?: number ;
100132} ;
101133
@@ -149,29 +181,14 @@ type TableCellProps = TableCellBasicProps & {
149181 hasAction ?: boolean ;
150182 isSticky ?: boolean ;
151183 actionClassName ?: string ;
152- rowHoverStyle ?: keyof typeof rowHoverStyles ;
184+ rowHoverStyle ?: string ;
153185 isSelected ?: boolean ;
154186 isTabbableCell ?: boolean ;
187+ variant ?: TableVariant ;
188+ children ?: ReactNode ;
155189} ;
156190
157- const rowHoverStyles = {
158- default :
159- "group-hover/table-row:bg-charcoal-800 group-focus-visible/table-row:bg-background-bright group-hover/table-row:before:absolute group-hover/table-row:before:bg-charcoal-750 group-hover/table-row:before:top-[-1px] group-hover/table-row:before:left-0 group-hover/table-row:before:h-px group-hover/table-row:before:w-3 group-hover/table-row:after:absolute group-hover/table-row:after:bg-charcoal-750 group-hover/table-row:after:bottom-0 group-hover/table-row:after:left-0 group-hover/table-row:after:h-px group-hover/table-row:after:w-3" ,
160- dimmed :
161- "group-hover/table-row:bg-charcoal-850 group-hover/table-row:before:absolute group-hover/table-row:before:bg-charcoal-800 group-hover/table-row:before:top-[-1px] group-hover/table-row:before:left-0 group-hover/table-row:before:h-px group-hover/table-row:before:w-3 group-hover/table-row:after:absolute group-hover/table-row:after:bg-charcoal-800 group-hover/table-row:after:bottom-0 group-hover/table-row:after:left-0 group-hover/table-row:after:h-px group-hover/table-row:after:w-3" ,
162- bright :
163- "group-hover/table-row:bg-charcoal-750 group-hover/table-row:before:absolute group-hover/table-row:before:bg-charcoal-700 group-hover/table-row:before:top-[-1px] group-hover/table-row:before:left-0 group-hover/table-row:before:h-px group-hover/table-row:before:w-3 group-hover/table-row:after:absolute group-hover/table-row:after:bg-charcoal-700 group-hover/table-row:after:bottom-0 group-hover/table-row:after:left-0 group-hover/table-row:after:h-px group-hover/table-row:after:w-3" ,
164- } ;
165-
166- const stickyStyles =
167- "sticky right-0 bg-background-dimmed group-hover/table-row:bg-charcoal-750 [&:has(.group-hover\\/table-row\\:block)]:w-auto group-has-[[tabindex='0']:focus]/table-row:bg-background-bright" ;
168-
169- const tabFocusRowDividerStyles =
170- "has-[[tabindex='0']:focus]:after:absolute has-[[tabindex='0']:focus]:after:bottom-0 has-[[tabindex='0']:focus]:after:left-0 has-[[tabindex='0']:focus]:after:right-0 has-[[tabindex='0']:focus]:after:h-px has-[[tabindex='0']:focus]:after:bg-grid-dimmed has-[[tabindex='0']:focus]:before:absolute has-[[tabindex='0']:focus]:before:left-0 has-[[tabindex='0']:focus]:before:-top-px has-[[tabindex='0']:focus]:before:h-px has-[[tabindex='0']:focus]:before:w-3 has-[[tabindex='0']:focus]:before:bg-grid-dimmed" ;
171-
172- const isSelectedStyle = "bg-charcoal-750 group-hover:bg-charcoal-750" ;
173-
174- export const TableCell = forwardRef < HTMLTableCellElement , TableCellProps > (
191+ export const TableCell = forwardRef < HTMLTableCellElement , Omit < TableCellProps , "variant" > > (
175192 (
176193 {
177194 className,
@@ -183,7 +200,6 @@ export const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(
183200 onClick,
184201 hasAction = false ,
185202 isSticky = false ,
186- rowHoverStyle = "default" ,
187203 isSelected,
188204 isTabbableCell = false ,
189205 } ,
@@ -207,18 +223,22 @@ export const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(
207223 ? "justify-center text-center"
208224 : "justify-end text-right"
209225 ) ;
226+ const { variant } = useContext ( TableContext ) ;
210227
211228 return (
212229 < td
213230 ref = { ref }
214231 className = { cn (
215- "text-xs text-charcoal-400" ,
232+ "text-xs text-charcoal-400 has-[[tabindex='0']:focus]:before:absolute has-[[tabindex='0']:focus]:before:-top-px has-[[tabindex='0']:focus]:before:left-0 has-[[tabindex='0']:focus]:before:h-px has-[[tabindex='0']:focus]:before:w-3 has-[[tabindex='0']:focus]:before:bg-grid-dimmed has-[[tabindex='0']:focus]:after:absolute has-[[tabindex='0']:focus]:after:bottom-0 has-[[tabindex='0']:focus]:after:left-0 has-[[tabindex='0']:focus]:after:right-0 has-[[tabindex='0']:focus]:after:h-px has-[[tabindex='0']:focus]:after:bg-grid-dimmed" ,
233+ variants [ variant ] . cell ,
216234 to || onClick || hasAction ? "cursor-pointer" : "cursor-default px-3 py-3 align-middle" ,
217235 ! to && ! onClick && alignmentClassName ,
218- isSticky && stickyStyles ,
219- isSelected && isSelectedStyle ,
220- ! isSelected && rowHoverStyles [ rowHoverStyle ] ,
221- tabFocusRowDividerStyles ,
236+ isSticky &&
237+ "[&:has(.group-hover/table-row:block)]:w-auto sticky right-0 bg-background-dimmed" ,
238+ isSticky && variants [ variant ] . stickyCell ,
239+ isSelected && variants [ variant ] . rowSelected ,
240+ ! isSelected &&
241+ "group-hover/table-row:before:absolute group-hover/table-row:before:left-0 group-hover/table-row:before:top-[-1px] group-hover/table-row:before:h-px group-hover/table-row:before:w-3 group-hover/table-row:before:bg-charcoal-750 group-hover/table-row:after:absolute group-hover/table-row:after:bottom-0 group-hover/table-row:after:left-0 group-hover/table-row:after:h-px group-hover/table-row:after:w-3 group-hover/table-row:after:bg-charcoal-750 group-focus-visible/table-row:bg-background-bright" ,
222242 className
223243 ) }
224244 colSpan = { colSpan }
@@ -274,7 +294,7 @@ export const TableCellChevron = forwardRef<
274294
275295export const TableCellMenu = forwardRef <
276296 HTMLTableCellElement ,
277- {
297+ Omit < TableCellProps , "variant" > & {
278298 className ?: string ;
279299 isSticky ?: boolean ;
280300 onClick ?: ( event : React . MouseEvent < HTMLButtonElement , MouseEvent > ) => void ;
@@ -283,6 +303,7 @@ export const TableCellMenu = forwardRef<
283303 popoverContent ?: ReactNode ;
284304 children ?: ReactNode ;
285305 isSelected ?: boolean ;
306+ variant ?: TableVariant ;
286307 }
287308> (
288309 (
@@ -299,6 +320,7 @@ export const TableCellMenu = forwardRef<
299320 ref
300321 ) => {
301322 const [ isOpen , setIsOpen ] = useState ( false ) ;
323+ const { variant } = useContext ( TableContext ) ;
302324
303325 return (
304326 < TableCell
@@ -313,12 +335,18 @@ export const TableCellMenu = forwardRef<
313335 < div className = "relative h-full p-1" >
314336 < div
315337 className = { cn (
316- "absolute right-0 top-1/2 mr-1 flex -translate-y-1/2 items-center justify-end gap-0.5 rounded-[0.25rem] bg-background-dimmed p-0.5 group-hover/table-row:bg-background-bright group-hover/table-row:ring-1 group-hover/table-row:ring-grid-bright group-has-[[tabindex='0']:focus]/table-row:bg-background-bright"
338+ "absolute right-0 top-1/2 mr-1 flex -translate-y-1/2 items-center justify-end gap-0.5 rounded-[0.25rem] p-0.5 group-hover/table-row:ring-1" ,
339+ variants [ variant ] . menuButton
317340 ) }
318341 >
319342 { /* Hidden buttons that show on hover */ }
320343 { hiddenButtons && (
321- < div className = "hidden pr-0.5 group-hover/table-row:block group-hover/table-row:border-r group-hover/table-row:border-grid-dimmed" >
344+ < div
345+ className = { cn (
346+ "hidden pr-0.5 group-hover/table-row:block group-hover/table-row:border-r" ,
347+ variants [ variant ] . menuButtonDivider
348+ ) }
349+ >
322350 { hiddenButtons }
323351 </ div >
324352 ) }
0 commit comments