Skip to content

Commit e7fd0c7

Browse files
committed
Creates table style variants so tables look good in the inspector panels
1 parent 3998961 commit e7fd0c7

File tree

3 files changed

+83
-50
lines changed

3 files changed

+83
-50
lines changed

apps/webapp/app/components/primitives/Table.tsx

Lines changed: 76 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,78 @@
11
import { ChevronRightIcon } from "@heroicons/react/24/solid";
22
import { Link } from "@remix-run/react";
3-
import React, { ReactNode, forwardRef, useState } from "react";
3+
import React, { ReactNode, forwardRef, useState, useContext, createContext } from "react";
44
import { cn } from "~/utils/cn";
55
import { Popover, PopoverContent, PopoverVerticalEllipseTrigger } from "./Popover";
66
import { 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+
831
type 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

3361
type 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>(
95127
type 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

275295
export 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
)}

apps/webapp/app/components/runs/v3/TaskRunsTable.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
TableHeader,
4040
TableHeaderCell,
4141
TableRow,
42+
TableVariant,
4243
} from "../../primitives/Table";
4344
import { CancelRunDialog } from "./CancelRunDialog";
4445
import { LiveTimer } from "./LiveTimer";
@@ -58,6 +59,7 @@ type RunsTableProps = {
5859
runs: RunListItem[];
5960
isLoading?: boolean;
6061
allowSelection?: boolean;
62+
variant?: TableVariant;
6163
};
6264

6365
export function TaskRunsTable({
@@ -67,6 +69,7 @@ export function TaskRunsTable({
6769
runs,
6870
isLoading = false,
6971
allowSelection = false,
72+
variant = "dimmed",
7073
}: RunsTableProps) {
7174
const user = useUser();
7275
const organization = useOrganization();
@@ -104,7 +107,7 @@ export function TaskRunsTable({
104107
);
105108

106109
return (
107-
<Table className="max-h-full overflow-y-auto">
110+
<Table variant={variant} className="max-h-full overflow-y-auto">
108111
<TableHeader>
109112
{allowSelection && (
110113
<TableHeaderCell className="pl-3 pr-0">

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.schedules.$scheduleParam/route.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ export default function Page() {
220220
TrailingIcon={ExitIcon}
221221
shortcut={{ key: "esc" }}
222222
shortcutPosition="before-trailing-icon"
223+
className="pl-1"
223224
/>
224225
</div>
225226
<div className="overflow-y-scroll scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600">
@@ -297,11 +298,12 @@ export default function Page() {
297298
}}
298299
runs={schedule.runs}
299300
isLoading={false}
301+
variant="bright"
300302
/>
301303
</div>
302304
<div className="flex flex-col gap-1">
303305
<Header3>Next 5 runs</Header3>
304-
<Table>
306+
<Table variant="bright">
305307
<TableHeader>
306308
{!isUtc && <TableHeaderCell>{schedule.timezone}</TableHeaderCell>}
307309
<TableHeaderCell>UTC</TableHeaderCell>

0 commit comments

Comments
 (0)