Skip to content

Commit 8b82dda

Browse files
Merge pull request #745 from gadget-inc/mill/shadcnTable
Initial readonly pass of Shadcn AutoTable
2 parents af5d7d8 + 8ecb04a commit 8b82dda

39 files changed

+1135
-176
lines changed
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import { PolarisWrapper } from "../../../../cypress/support/auto.js";
33
import { PolarisAutoTableEncryptedStringCell } from "../../../../src/auto/polaris/tableCells/PolarisAutoTableEncryptedStringCell.js";
4+
import { defaultPlaceholderHiddenText } from "../../../../src/auto/shared/defaults.js";
45

56
const sampleEncryptedValue = "nice encrypted value here";
67

@@ -9,17 +10,17 @@ describe("PolarisAutoTableEncryptedStringCell", () => {
910
cy.mountWithWrapper(<PolarisAutoTableEncryptedStringCell value={sampleEncryptedValue} />, PolarisWrapper);
1011

1112
// Initially hidden
12-
cy.contains("•".repeat(sampleEncryptedValue.length)).should("exist");
13+
cy.contains(defaultPlaceholderHiddenText).should("exist");
1314
cy.contains(sampleEncryptedValue).should("not.exist");
1415

1516
// Show
1617
cy.get(`div[role="EncryptedStringCellShowHideButton"]`).click();
17-
cy.contains("•".repeat(sampleEncryptedValue.length)).should("not.exist");
18+
cy.contains(defaultPlaceholderHiddenText).should("not.exist");
1819
cy.contains(sampleEncryptedValue).should("exist");
1920

2021
// Hide again
2122
cy.get(`div[role="EncryptedStringCellShowHideButton"]`).click();
22-
cy.contains("•".repeat(sampleEncryptedValue.length)).should("exist");
23+
cy.contains(defaultPlaceholderHiddenText).should("exist");
2324
cy.contains(sampleEncryptedValue).should("not.exist");
2425
});
2526
});

packages/react/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@
121121
"postcss": "^8.4.49",
122122
"react": "^18.2.0",
123123
"react-dom": "^18.2.0",
124+
"@radix-ui/react-avatar": "^1.1.2",
125+
"@radix-ui/react-tooltip": "^1.1.7",
126+
"@tanstack/react-table": "^8.20.6",
124127
"setup-polly-jest": "^0.11.0",
125128
"storybook": "^8.1.6",
126129
"tailwind-merge": "^2.6.0",

packages/react/spec/auto/polaris/PolarisAutoForm.stories.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { PolarisAutoInput } from "../../../src/auto/polaris/inputs/PolarisAutoIn
77
import { PolarisAutoSubmit } from "../../../src/auto/polaris/submit/PolarisAutoSubmit.tsx";
88
import { FormProvider, useForm } from "../../../src/useActionForm.ts";
99
import { testApi as api } from "../../apis.ts";
10-
import { StorybookErrorBoundary } from "../StorybookErrorBoundary.tsx";
10+
import { StorybookErrorBoundary } from "../storybook/StorybookErrorBoundary.tsx";
1111

1212
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
1313
export default {

packages/react/spec/auto/shadcn-defaults/ShadcnAutoForm.stories.jsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React, { useState } from "react";
22
import { Provider } from "../../../src/GadgetProvider.tsx";
3+
import { makeAutocomponents } from "../../../src/auto/shadcn/index.ts";
34
import { FormProvider, useForm } from "../../../src/useActionForm.ts";
45
import { testApi as api } from "../../apis.ts";
5-
import { StorybookErrorBoundary } from "../StorybookErrorBoundary.tsx";
6-
import { makeAutocomponents } from "../../../src/auto/shadcn/index.ts";
7-
import { elements } from "./index";
6+
import { StorybookErrorBoundary } from "../storybook/StorybookErrorBoundary.tsx";
7+
import { elements } from "./index.tsx";
88

99
import { makeShadcnAutoInput } from "../../../src/auto/shadcn/inputs/ShadcnAutoInput.tsx";
1010
import { makeShadcnAutoSubmit } from "../../../src/auto/shadcn/submit/ShadcnAutoSubmit.tsx";
@@ -25,7 +25,7 @@ export default {
2525
<div style={{ width: "600px", backgroundColor: "white" }}>
2626
<Provider api={api}>
2727
<FormProvider {...useForm()}>
28-
<StorybookErrorBoundary >
28+
<StorybookErrorBoundary>
2929
<elements.Card className="p-6 w-full bg-white shadow-lg rounded-lg">
3030
<Story />
3131
</elements.Card>
@@ -46,8 +46,6 @@ export default {
4646
// More on argTypes: https://storybook.js.org/docs/api/argtypes
4747
};
4848

49-
50-
5149
export const Primary = {
5250
args: {
5351
action: api.widget.create,
@@ -118,7 +116,6 @@ export const IncludedWithDefaultValues = {
118116
},
119117
};
120118

121-
122119
const ConditionalAppearingAutoInput = () => {
123120
const [showMoreInputs, setShowMoreInputs] = useState(false);
124121
return (
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* From https://ui.shadcn.com/docs/components/avatar
3+
*/
4+
5+
"use client";
6+
7+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
8+
import * as React from "react";
9+
10+
import { cn } from "../utils.js";
11+
12+
const Avatar = React.forwardRef<React.ElementRef<typeof AvatarPrimitive.Root>, React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>>(
13+
({ className, ...props }, ref) => (
14+
<AvatarPrimitive.Root ref={ref} className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden", className)} {...props} />
15+
)
16+
);
17+
Avatar.displayName = AvatarPrimitive.Root.displayName;
18+
19+
const AvatarImage = React.forwardRef<
20+
React.ElementRef<typeof AvatarPrimitive.Image>,
21+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
22+
>(({ className, ...props }, ref) => (
23+
<AvatarPrimitive.Image ref={ref} className={cn("aspect-square h-full w-full", className)} {...props} />
24+
));
25+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
26+
27+
const AvatarFallback = React.forwardRef<
28+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
29+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
30+
>(({ className, ...props }, ref) => (
31+
<AvatarPrimitive.Fallback
32+
ref={ref}
33+
className={cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className)}
34+
{...props}
35+
/>
36+
));
37+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
38+
39+
export { Avatar, AvatarFallback, AvatarImage };
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* File contents from https://ui.shadcn.com/docs/components/table
3+
*/
4+
import * as React from "react";
5+
import { cn } from "../utils.js";
6+
7+
const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(({ className, ...props }, ref) => (
8+
<div className="relative w-full overflow-auto">
9+
<table ref={ref} className={cn("w-full caption-bottom text-sm", className)} {...props} />
10+
</div>
11+
));
12+
Table.displayName = "Table";
13+
14+
const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
15+
({ className, ...props }, ref) => <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
16+
);
17+
TableHeader.displayName = "TableHeader";
18+
19+
const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
20+
({ className, ...props }, ref) => <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} />
21+
);
22+
TableBody.displayName = "TableBody";
23+
24+
const TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
25+
({ className, ...props }, ref) => (
26+
<tfoot ref={ref} className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)} {...props} />
27+
)
28+
);
29+
TableFooter.displayName = "TableFooter";
30+
31+
const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(({ className, ...props }, ref) => (
32+
<tr ref={ref} className={cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className)} {...props} />
33+
));
34+
TableRow.displayName = "TableRow";
35+
36+
const TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(({ className, ...props }, ref) => (
37+
<th
38+
ref={ref}
39+
className={cn(
40+
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
41+
className
42+
)}
43+
{...props}
44+
/>
45+
));
46+
TableHead.displayName = "TableHead";
47+
48+
const TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(({ className, ...props }, ref) => (
49+
<td
50+
ref={ref}
51+
className={cn("p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className)}
52+
{...props}
53+
/>
54+
));
55+
TableCell.displayName = "TableCell";
56+
57+
const TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(
58+
({ className, ...props }, ref) => <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} />
59+
);
60+
TableCaption.displayName = "TableCaption";
61+
62+
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* File contents from https://ui.shadcn.com/docs/components/tooltip
3+
*/
4+
5+
"use client";
6+
7+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
8+
import * as React from "react";
9+
import { cn } from "../utils.js";
10+
11+
const TooltipProvider = TooltipPrimitive.Provider;
12+
13+
const Tooltip = TooltipPrimitive.Root;
14+
15+
const TooltipTrigger = TooltipPrimitive.Trigger;
16+
17+
const TooltipContent = React.forwardRef<
18+
React.ElementRef<typeof TooltipPrimitive.Content>,
19+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
20+
>(({ className, sideOffset = 4, ...props }, ref) => (
21+
<TooltipPrimitive.Portal>
22+
<TooltipPrimitive.Content
23+
ref={ref}
24+
sideOffset={sideOffset}
25+
className={cn(
26+
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
27+
className
28+
)}
29+
{...props}
30+
/>
31+
</TooltipPrimitive.Portal>
32+
));
33+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
34+
35+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };

packages/react/spec/auto/shadcn-defaults/index.tsx

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ShadcnElements } from "../../../src/auto/shadcn/elements.js";
22
import { Alert, AlertDescription, AlertTitle } from "./components/Alert.js";
3+
import { Avatar, AvatarFallback, AvatarImage } from "./components/Avatar.js";
34
import { Badge } from "./components/Badge.js";
45
import { Button } from "./components/Button.js";
56
import { Calendar } from "./components/Calendar.js";
@@ -12,46 +13,77 @@ import { Label } from "./components/Label.js";
1213
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "./components/Popover.js";
1314
import { ScrollArea, ScrollBar } from "./components/ScrollArea.js";
1415
import { Skeleton } from "./components/Skeleton.js";
16+
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./components/Table.js";
1517
import { Textarea } from "./components/TextArea.js";
1618
import { Toaster } from "./components/Toaster.js";
19+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/Tooltip.js";
1720
import { toast } from "./hooks/useToast.js";
1821
import { cn } from "./utils.js";
19-
export type MergeClassNames = (defaultClassNames: string | string[], userClassName?: string) => string;
2022

21-
export const elements: ShadcnElements & { mergeClassNames: MergeClassNames } = {
23+
export const elements: ShadcnElements = {
2224
Alert,
2325
AlertDescription,
2426
AlertTitle,
27+
2528
Badge,
29+
2630
Button,
31+
2732
Calendar,
33+
2834
Card,
2935
CardContent,
3036
CardDescription,
3137
CardFooter,
3238
CardHeader,
3339
CardTitle,
40+
3441
Checkbox,
42+
3543
Command,
3644
CommandEmpty,
3745
CommandGroup,
3846
CommandInput,
3947
CommandItem,
4048
CommandList,
4149
CommandSeparator,
50+
4251
Popover,
4352
PopoverAnchor,
4453
PopoverContent,
4554
PopoverTrigger,
4655
ScrollArea,
4756
ScrollBar,
57+
4858
Input,
59+
4960
Label,
5061
Textarea,
62+
5163
Form,
64+
5265
Skeleton,
66+
67+
Table,
68+
TableBody,
69+
TableCaption,
70+
TableCell,
71+
TableFooter,
72+
TableHead,
73+
TableHeader,
74+
TableRow,
75+
76+
TooltipProvider,
77+
Tooltip,
78+
TooltipTrigger,
79+
TooltipContent,
80+
81+
Avatar,
82+
AvatarImage,
83+
AvatarFallback,
84+
5385
toast,
54-
mergeClassNames: cn,
86+
cn,
5587
};
5688

5789
export { Toaster };

packages/react/spec/auto/shadcn-defaults/inputs/ShadcnAutoEnumInput.stories.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import React, { useState } from "react";
1+
import React from "react";
22
import { Provider } from "../../../../src/GadgetProvider.tsx";
3-
import { FormProvider, useForm } from "../../../../src/useActionForm.ts";
4-
import { testApi as api } from "../../../apis.ts";
5-
import { StorybookErrorBoundary } from "../../StorybookErrorBoundary.tsx";
63
import { makeAutocomponents } from "../../../../src/auto/shadcn/index.ts";
7-
import { elements } from "../index";
84
import { makeShadcnAutoEnumInput } from "../../../../src/auto/shadcn/inputs/ShadcnAutoEnumInput.tsx";
5+
import { FormProvider, useForm } from "../../../../src/useActionForm.ts";
6+
import { testApi as api } from "../../../apis.ts";
7+
import { StorybookErrorBoundary } from "../../storybook/StorybookErrorBoundary.tsx";
8+
import { elements } from "../index.tsx";
99

1010
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
1111

@@ -31,7 +31,7 @@ export default {
3131
<div style={{ width: "600px", backgroundColor: "white" }}>
3232
<Provider api={api}>
3333
<FormProvider {...useForm()}>
34-
<StorybookErrorBoundary >
34+
<StorybookErrorBoundary>
3535
<elements.Card className="p-6 w-full bg-white shadow-lg rounded-lg">
3636
<Story />
3737
</elements.Card>

0 commit comments

Comments
 (0)