@kinetixui/ui 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/index.js +30 -21
  2. package/package.json +12 -4
  3. package/src/components/button.tsx +19 -12
  4. package/src/components/context-menu.tsx +1 -1
  5. package/src/components/dropdown-menu.tsx +1 -1
  6. package/src/components/input-group.tsx +2 -1
  7. package/src/components/list.tsx +3 -1
  8. package/src/components/menubar.tsx +2 -2
  9. package/src/components/navigation-bar.tsx +1 -1
  10. package/src/components/select.tsx +1 -1
  11. package/src/components/toggle.tsx +1 -1
  12. package/src/components-behavior.test.tsx +74 -0
  13. package/src/components-smoke.test.tsx +47 -0
  14. package/src/stories/Accordion.stories.tsx +49 -0
  15. package/src/stories/Alert.stories.tsx +38 -0
  16. package/src/stories/AlertDialog.stories.tsx +35 -0
  17. package/src/stories/AspectRatio.stories.tsx +32 -0
  18. package/src/stories/AudioPlayer.stories.tsx +26 -0
  19. package/src/stories/Avatar.stories.tsx +23 -0
  20. package/src/stories/AvatarGroup.stories.tsx +37 -0
  21. package/src/stories/Badge.stories.tsx +35 -0
  22. package/src/stories/Breadcrumb.stories.tsx +36 -0
  23. package/src/stories/Calendar.stories.tsx +25 -0
  24. package/src/stories/Card.stories.tsx +33 -0
  25. package/src/stories/Carousel.stories.tsx +33 -0
  26. package/src/stories/Chart.stories.tsx +44 -0
  27. package/src/stories/Checkbox.stories.tsx +29 -0
  28. package/src/stories/CircularProgress.stories.tsx +42 -0
  29. package/src/stories/CodeBlock.stories.tsx +25 -0
  30. package/src/stories/Collapsible.stories.tsx +50 -0
  31. package/src/stories/Combobox.stories.tsx +32 -0
  32. package/src/stories/Command.stories.tsx +32 -0
  33. package/src/stories/ContextMenu.stories.tsx +31 -0
  34. package/src/stories/DataTable.stories.tsx +31 -0
  35. package/src/stories/DatePicker.stories.tsx +30 -0
  36. package/src/stories/Dialog.stories.tsx +38 -0
  37. package/src/stories/Drawer.stories.tsx +39 -0
  38. package/src/stories/DropdownMenu.stories.tsx +32 -0
  39. package/src/stories/Fab.stories.tsx +47 -0
  40. package/src/stories/Field.stories.tsx +35 -0
  41. package/src/stories/FileUpload.stories.tsx +36 -0
  42. package/src/stories/Footer.stories.tsx +39 -0
  43. package/src/stories/Form.stories.tsx +28 -0
  44. package/src/stories/HoverCard.stories.tsx +41 -0
  45. package/src/stories/Image.stories.tsx +35 -0
  46. package/src/stories/Inform.stories.tsx +39 -0
  47. package/src/stories/InputGroup.stories.tsx +36 -0
  48. package/src/stories/InputOTP.stories.tsx +27 -0
  49. package/src/stories/Label.stories.tsx +24 -0
  50. package/src/stories/List.stories.tsx +26 -0
  51. package/src/stories/Menubar.stories.tsx +38 -0
  52. package/src/stories/Metric.stories.tsx +32 -0
  53. package/src/stories/Modal.stories.tsx +31 -0
  54. package/src/stories/NavigationBar.stories.tsx +32 -0
  55. package/src/stories/NavigationMenu.stories.tsx +34 -0
  56. package/src/stories/NumberInput.stories.tsx +29 -0
  57. package/src/stories/Pagination.stories.tsx +30 -0
  58. package/src/stories/PasswordInput.stories.tsx +23 -0
  59. package/src/stories/Popover.stories.tsx +47 -0
  60. package/src/stories/Progress.stories.tsx +31 -0
  61. package/src/stories/Quote.stories.tsx +32 -0
  62. package/src/stories/RadioGroup.stories.tsx +45 -0
  63. package/src/stories/Rating.stories.tsx +35 -0
  64. package/src/stories/Resizable.stories.tsx +29 -0
  65. package/src/stories/ScrollArea.stories.tsx +25 -0
  66. package/src/stories/Select.stories.tsx +46 -0
  67. package/src/stories/Separator.stories.tsx +41 -0
  68. package/src/stories/Sheet.stories.tsx +31 -0
  69. package/src/stories/Sidebar.stories.tsx +25 -0
  70. package/src/stories/Skeleton.stories.tsx +27 -0
  71. package/src/stories/Slider.stories.tsx +24 -0
  72. package/src/stories/Sonner.stories.tsx +26 -0
  73. package/src/stories/Spinner.stories.tsx +33 -0
  74. package/src/stories/Stepper.stories.tsx +35 -0
  75. package/src/stories/Switch.stories.tsx +29 -0
  76. package/src/stories/TabBar.stories.tsx +35 -0
  77. package/src/stories/Table.stories.tsx +42 -0
  78. package/src/stories/TableOfContents.stories.tsx +31 -0
  79. package/src/stories/Tabs.stories.tsx +50 -0
  80. package/src/stories/Tag.stories.tsx +42 -0
  81. package/src/stories/Toggle.stories.tsx +34 -0
  82. package/src/stories/ToggleGroup.stories.tsx +37 -0
  83. package/src/stories/Tooltip.stories.tsx +42 -0
@@ -0,0 +1,39 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Button, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <Drawer>
9
+ <DrawerTrigger asChild>
10
+ <Button variant="Outline">Open Drawer</Button>
11
+ </DrawerTrigger>
12
+ <DrawerContent>
13
+ <div className="mx-auto w-full max-w-sm">
14
+ <DrawerHeader>
15
+ <DrawerTitle>Move goal</DrawerTitle>
16
+ <DrawerDescription>Set your daily activity goal.</DrawerDescription>
17
+ </DrawerHeader>
18
+ <DrawerFooter>
19
+ <Button>Submit</Button>
20
+ <DrawerClose asChild>
21
+ <Button variant="Outline">Cancel</Button>
22
+ </DrawerClose>
23
+ </DrawerFooter>
24
+ </div>
25
+ </DrawerContent>
26
+ </Drawer>
27
+ );
28
+
29
+ const meta = {
30
+ title: "Overlays/Drawer",
31
+ parameters: {
32
+ layout: "centered",
33
+ docs: { source: { code: `<Drawer>\n <DrawerTrigger asChild><Button variant="Outline">Open Drawer</Button></DrawerTrigger>\n <DrawerContent>…</DrawerContent>\n</Drawer>`, language: "tsx" } },
34
+ },
35
+ } satisfies Meta;
36
+
37
+ export default meta;
38
+
39
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,32 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <DropdownMenu>
9
+ <DropdownMenuTrigger asChild>
10
+ <Button variant="Outline">Open</Button>
11
+ </DropdownMenuTrigger>
12
+ <DropdownMenuContent className="w-44">
13
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
14
+ <DropdownMenuSeparator />
15
+ <DropdownMenuItem>Profile</DropdownMenuItem>
16
+ <DropdownMenuItem>Billing</DropdownMenuItem>
17
+ <DropdownMenuItem>Team</DropdownMenuItem>
18
+ </DropdownMenuContent>
19
+ </DropdownMenu>
20
+ );
21
+
22
+ const meta = {
23
+ title: "Overlays/DropdownMenu",
24
+ parameters: {
25
+ layout: "centered",
26
+ docs: { source: { code: `<DropdownMenu>\n <DropdownMenuTrigger asChild><Button variant="Outline">Open</Button></DropdownMenuTrigger>\n <DropdownMenuContent>…</DropdownMenuContent>\n</DropdownMenu>`, language: "tsx" } },
27
+ },
28
+ } satisfies Meta;
29
+
30
+ export default meta;
31
+
32
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,47 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx · controls: scripts/gen-stories.mjs CONTROLS */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Fab } from "@kinetixui/ui";
6
+ import { Plus } from "lucide-react";
7
+
8
+ const Demo = () => (
9
+ <div className="flex items-center gap-4">
10
+ <Fab aria-label="Add">
11
+ <Plus />
12
+ </Fab>
13
+ <Fab extended>
14
+ <Plus />
15
+ New item
16
+ </Fab>
17
+ <Fab variant="Secondary" size="sm" aria-label="Add">
18
+ <Plus />
19
+ </Fab>
20
+ </div>
21
+ );
22
+
23
+ const meta = {
24
+ title: "Controls & Actions/Fab",
25
+ component: Fab,
26
+ args: { variant: "Primary", size: "default", extended: false },
27
+ argTypes: {
28
+ variant: { control: "inline-radio", options: ["Primary", "Secondary"] },
29
+ size: { control: "inline-radio", options: ["default", "sm"] },
30
+ extended: { control: "boolean" },
31
+ },
32
+ parameters: {
33
+ layout: "centered",
34
+ docs: { source: { code: `<Fab aria-label="Add">\n <Plus />\n</Fab>\n\n<Fab extended>\n <Plus />\n New item\n</Fab>`, language: "tsx" } },
35
+ },
36
+ } satisfies Meta;
37
+
38
+ export default meta;
39
+
40
+ export const Playground: StoryObj<typeof meta> = { render: (args) => (
41
+ <Fab {...args} aria-label="Add">
42
+ <Plus />
43
+ {args.extended ? "New item" : null}
44
+ </Fab>
45
+ ) };
46
+
47
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,35 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Field, FieldControl, FieldDescription, FieldLabel, FieldMessage, Input } from "@kinetixui/ui";
6
+
7
+ const Demo = () => {
8
+ const [v, setV] = React.useState("");
9
+ const invalid = v.length > 0 && !v.includes("@");
10
+ return (
11
+ <div className="w-full max-w-sm">
12
+ <Field invalid={invalid}>
13
+ <FieldLabel>Email</FieldLabel>
14
+ <FieldControl>
15
+ <Input value={v} onChange={(e) => setV(e.target.value)} placeholder="you@example.com" />
16
+ </FieldControl>
17
+ <FieldDescription>We&rsquo;ll only use it to send receipts.</FieldDescription>
18
+ {invalid && <FieldMessage intent="error">Enter a valid email address.</FieldMessage>}
19
+ {!invalid && v.includes("@") && <FieldMessage intent="success">Looks good.</FieldMessage>}
20
+ </Field>
21
+ </div>
22
+ );
23
+ };
24
+
25
+ const meta = {
26
+ title: "Form Inputs/Field",
27
+ parameters: {
28
+ layout: "centered",
29
+ docs: { source: { code: `<Field invalid={!!error}>\n <FieldLabel>Email</FieldLabel>\n <FieldControl><Input type="email" {...register("email")} /></FieldControl>\n <FieldDescription>We'll only use it to send receipts.</FieldDescription>\n {error && <FieldMessage intent="error">{error.message}</FieldMessage>}\n</Field>`, language: "tsx" } },
30
+ },
31
+ } satisfies Meta;
32
+
33
+ export default meta;
34
+
35
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,36 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { FileUpload } from "@kinetixui/ui";
6
+
7
+ const Demo = () => {
8
+ const [files, setFiles] = React.useState([
9
+ { id: "1", name: "passport-scan.pdf", size: 245_000, status: "uploaded" as const },
10
+ { id: "2", name: "photo.png", size: 1_200_000, status: "error" as const, error: "File exceeds 1 MB limit" },
11
+ ]);
12
+ return (
13
+ <FileUpload
14
+ className="w-full max-w-sm"
15
+ multiple
16
+ helperText="PDF, PNG up to 5 MB"
17
+ files={files}
18
+ onFilesSelected={(picked) =>
19
+ setFiles((f) => [...f, ...picked.map((p, i) => ({ id: `new-${i}-${p.name}`, name: p.name, size: p.size, status: "uploaded" as const }))])
20
+ }
21
+ onRemove={(id) => setFiles((f) => f.filter((x) => x.id !== id))}
22
+ />
23
+ );
24
+ };
25
+
26
+ const meta = {
27
+ title: "Form Inputs/FileUpload",
28
+ parameters: {
29
+ layout: "centered",
30
+ docs: { source: { code: `<FileUpload\n multiple\n files={files}\n onFilesSelected={(picked) => upload(picked)}\n onRemove={(id) => removeFile(id)}\n/>`, language: "tsx" } },
31
+ },
32
+ } satisfies Meta;
33
+
34
+ export default meta;
35
+
36
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,39 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Footer, FooterBottom, FooterColumn, FooterLink } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <Footer className="w-full max-w-lg rounded-md">
9
+ <div className="grid grid-cols-2 gap-6">
10
+ <FooterColumn title="Product">
11
+ <FooterLink href="#">Overview</FooterLink>
12
+ <FooterLink href="#">Pricing</FooterLink>
13
+ </FooterColumn>
14
+ <FooterColumn title="Company">
15
+ <FooterLink href="#">About</FooterLink>
16
+ <FooterLink href="#">Careers</FooterLink>
17
+ </FooterColumn>
18
+ </div>
19
+ <FooterBottom>
20
+ <span>© 2026 Acme Inc.</span>
21
+ <div className="flex gap-3">
22
+ <FooterLink href="#">Privacy</FooterLink>
23
+ <FooterLink href="#">Terms</FooterLink>
24
+ </div>
25
+ </FooterBottom>
26
+ </Footer>
27
+ );
28
+
29
+ const meta = {
30
+ title: "Data Display/Footer",
31
+ parameters: {
32
+ layout: "padded",
33
+ docs: { source: { code: `<Footer>\n <div className="grid grid-cols-2 gap-6">\n <FooterColumn title="Product">\n <FooterLink href="/pricing">Pricing</FooterLink>\n </FooterColumn>\n </div>\n <FooterBottom>© 2026 Acme Inc.</FooterBottom>\n</Footer>`, language: "tsx" } },
34
+ },
35
+ } satisfies Meta;
36
+
37
+ export default meta;
38
+
39
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,28 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Button, Input } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <form className="w-full max-w-sm space-y-4" onSubmit={(e) => e.preventDefault()}>
9
+ <div className="grid gap-2">
10
+ <label htmlFor="fd-user" className="text-sm font-medium">Username</label>
11
+ <Input id="fd-user" placeholder="kinetixui" />
12
+ <p className="text-sm text-muted-foreground">This is your public display name.</p>
13
+ </div>
14
+ <Button type="submit">Submit</Button>
15
+ </form>
16
+ );
17
+
18
+ const meta = {
19
+ title: "Form Inputs/Form",
20
+ parameters: {
21
+ layout: "centered",
22
+ docs: { source: { code: `const form = useForm<z.infer<typeof schema>>({ resolver: zodResolver(schema) })\n\n<Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <FormField control={form.control} name="username" render={({ field }) => (\n <FormItem>\n <FormLabel>Username</FormLabel>\n <FormControl><Input {...field} /></FormControl>\n <FormMessage />\n </FormItem>\n )} />\n <Button type="submit">Submit</Button>\n </form>\n</Form>`, language: "tsx" } },
23
+ },
24
+ } satisfies Meta;
25
+
26
+ export default meta;
27
+
28
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,41 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx · controls: scripts/gen-stories.mjs CONTROLS */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Button, HoverCard, HoverCardContent, HoverCardTrigger } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <HoverCard>
9
+ <HoverCardTrigger asChild>
10
+ <Button variant="Link">@kinetixui</Button>
11
+ </HoverCardTrigger>
12
+ <HoverCardContent>One token architecture, in motion across every platform.</HoverCardContent>
13
+ </HoverCard>
14
+ );
15
+
16
+ const meta = {
17
+ title: "Overlays/HoverCard",
18
+ component: HoverCard,
19
+ args: { openDelay: 200, closeDelay: 200 },
20
+ argTypes: {
21
+ openDelay: { control: { type: "number", step: 100 } },
22
+ closeDelay: { control: { type: "number", step: 100 } },
23
+ },
24
+ parameters: {
25
+ layout: "centered",
26
+ docs: { source: { code: `<HoverCard>\n <HoverCardTrigger>@kinetixui</HoverCardTrigger>\n <HoverCardContent>…</HoverCardContent>\n</HoverCard>`, language: "tsx" } },
27
+ },
28
+ } satisfies Meta;
29
+
30
+ export default meta;
31
+
32
+ export const Playground: StoryObj<typeof meta> = { render: (args) => (
33
+ <HoverCard {...args}>
34
+ <HoverCardTrigger asChild>
35
+ <Button variant="Link">@kinetixui</Button>
36
+ </HoverCardTrigger>
37
+ <HoverCardContent>One token architecture, in motion across every platform.</HoverCardContent>
38
+ </HoverCard>
39
+ ) };
40
+
41
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,35 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx · controls: scripts/gen-stories.mjs CONTROLS */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Image } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <div className="grid w-full max-w-md grid-cols-3 gap-3">
9
+ <Image ratio="1:1" src="https://picsum.photos/seed/kx1/400" alt="" />
10
+ <Image ratio="4:3" src="https://picsum.photos/seed/kx2/400/300" alt="" />
11
+ <Image ratio="3:4" src="https://picsum.photos/seed/kx3/300/400" alt="" />
12
+ </div>
13
+ );
14
+
15
+ const meta = {
16
+ title: "Foundations/Image",
17
+ component: Image,
18
+ args: { ratio: "4:3", rounded: true },
19
+ argTypes: {
20
+ ratio: { control: "inline-radio", options: ["1:1", "4:3", "3:4", "16:9"] },
21
+ rounded: { control: "boolean" },
22
+ },
23
+ parameters: {
24
+ layout: "centered",
25
+ docs: { source: { code: `<Image ratio="1:1" src="/photo.jpg" alt="" />\n<Image ratio="4:3" src="/photo.jpg" alt="" />\n<Image ratio="16:9" src="/photo.jpg" alt="" rounded={false} />`, language: "tsx" } },
26
+ },
27
+ } satisfies Meta;
28
+
29
+ export default meta;
30
+
31
+ export const Playground: StoryObj<typeof meta> = { render: (args) => (
32
+ <Image {...args} src="https://picsum.photos/seed/kx/400/300" alt="" className="w-56" />
33
+ ) };
34
+
35
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,39 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx · controls: scripts/gen-stories.mjs CONTROLS */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Inform } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <div className="flex w-full max-w-md flex-col gap-3">
9
+ <Inform variant="information" onDismiss={() => {}}>
10
+ A new software update is available.
11
+ </Inform>
12
+ <Inform variant="success">Your changes have been saved.</Inform>
13
+ <Inform variant="warning">Your subscription expires in 3 days.</Inform>
14
+ <Inform variant="error" action={{ label: "Retry" }}>
15
+ We couldn&rsquo;t process your payment.
16
+ </Inform>
17
+ </div>
18
+ );
19
+
20
+ const meta = {
21
+ title: "Feedback/Inform",
22
+ component: Inform,
23
+ args: { variant: "information" },
24
+ argTypes: {
25
+ variant: { control: "inline-radio", options: ["information", "warning", "success", "error"] },
26
+ },
27
+ parameters: {
28
+ layout: "centered",
29
+ docs: { source: { code: `<Inform variant="information" onDismiss={close}>\n A new software update is available.\n</Inform>\n\n<Inform variant="error" action={{ label: "Retry", onClick: retry }}>\n We couldn't process your payment.\n</Inform>`, language: "tsx" } },
30
+ },
31
+ } satisfies Meta;
32
+
33
+ export default meta;
34
+
35
+ export const Playground: StoryObj<typeof meta> = { render: (args) => (
36
+ <Inform {...args} className="max-w-md">A new software update is available.</Inform>
37
+ ) };
38
+
39
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,36 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText } from "@kinetixui/ui";
6
+ import { Search } from "lucide-react";
7
+
8
+ const Demo = () => (
9
+ <div className="flex w-full max-w-sm flex-col gap-3">
10
+ <InputGroup>
11
+ <InputGroupText>https://</InputGroupText>
12
+ <InputGroupInput placeholder="kinetixui.com" />
13
+ </InputGroup>
14
+ <InputGroup>
15
+ <InputGroupAddon align="start">$</InputGroupAddon>
16
+ <InputGroupInput placeholder="0.00" inputMode="decimal" />
17
+ <InputGroupText>USD</InputGroupText>
18
+ </InputGroup>
19
+ <InputGroup>
20
+ <InputGroupInput placeholder="Search components…" />
21
+ <InputGroupButton>Search</InputGroupButton>
22
+ </InputGroup>
23
+ </div>
24
+ );
25
+
26
+ const meta = {
27
+ title: "Form Inputs/InputGroup",
28
+ parameters: {
29
+ layout: "centered",
30
+ docs: { source: { code: `<InputGroup>\n <InputGroupText>https://</InputGroupText>\n <InputGroupInput placeholder="kinetixui.com" />\n</InputGroup>\n\n<InputGroup>\n <InputGroupAddon align="start">$</InputGroupAddon>\n <InputGroupInput placeholder="0.00" />\n <InputGroupText>USD</InputGroupText>\n</InputGroup>`, language: "tsx" } },
31
+ },
32
+ } satisfies Meta;
33
+
34
+ export default meta;
35
+
36
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,27 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { InputOTP, InputOTPGroup, InputOTPSlot } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <InputOTP maxLength={6}>
9
+ <InputOTPGroup>
10
+ {Array.from({ length: 6 }).map((_, i) => (
11
+ <InputOTPSlot key={i} index={i} />
12
+ ))}
13
+ </InputOTPGroup>
14
+ </InputOTP>
15
+ );
16
+
17
+ const meta = {
18
+ title: "Form Inputs/InputOTP",
19
+ parameters: {
20
+ layout: "centered",
21
+ docs: { source: { code: `<InputOTP maxLength={6}>\n <InputOTPGroup>\n <InputOTPSlot index={0} />\n ...\n <InputOTPSlot index={5} />\n </InputOTPGroup>\n</InputOTP>`, language: "tsx" } },
22
+ },
23
+ } satisfies Meta;
24
+
25
+ export default meta;
26
+
27
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,24 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Checkbox, Label } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <div className="flex items-center gap-2">
9
+ <Checkbox id="terms" />
10
+ <Label htmlFor="terms">Accept terms and conditions</Label>
11
+ </div>
12
+ );
13
+
14
+ const meta = {
15
+ title: "Foundations/Label",
16
+ parameters: {
17
+ layout: "centered",
18
+ docs: { source: { code: `<Label htmlFor="email">Your email address</Label>`, language: "tsx" } },
19
+ },
20
+ } satisfies Meta;
21
+
22
+ export default meta;
23
+
24
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,26 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Badge, List, ListItem, Switch } from "@kinetixui/ui";
6
+ import { Bell, Settings, User } from "lucide-react";
7
+
8
+ const Demo = () => (
9
+ <List className="w-full max-w-sm rounded-md border">
10
+ <ListItem leading={<User className="size-5 text-muted-foreground" />} title="Profile" description="Name, photo, and personal details" trailing={<Badge variant="outline">2</Badge>} onSelect={() => {}} />
11
+ <ListItem leading={<Bell className="size-5 text-muted-foreground" />} title="Notifications" description="Push, email and SMS preferences" trailing={<Switch />} />
12
+ <ListItem leading={<Settings className="size-5 text-muted-foreground" />} title="Settings" onSelect={() => {}} />
13
+ </List>
14
+ );
15
+
16
+ const meta = {
17
+ title: "Data Display/List",
18
+ parameters: {
19
+ layout: "centered",
20
+ docs: { source: { code: `<List>\n <ListItem\n leading={<User />}\n title="Profile"\n description="Name, photo, and personal details"\n onSelect={() => router.push("/profile")}\n />\n <ListItem leading={<Bell />} title="Notifications" trailing={<Switch />} />\n</List>`, language: "tsx" } },
21
+ },
22
+ } satisfies Meta;
23
+
24
+ export default meta;
25
+
26
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,38 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <Menubar>
9
+ <MenubarMenu>
10
+ <MenubarTrigger>File</MenubarTrigger>
11
+ <MenubarContent>
12
+ <MenubarItem>New Tab</MenubarItem>
13
+ <MenubarItem>New Window</MenubarItem>
14
+ <MenubarSeparator />
15
+ <MenubarItem>Share</MenubarItem>
16
+ </MenubarContent>
17
+ </MenubarMenu>
18
+ <MenubarMenu>
19
+ <MenubarTrigger>Edit</MenubarTrigger>
20
+ <MenubarContent>
21
+ <MenubarItem>Undo</MenubarItem>
22
+ <MenubarItem>Redo</MenubarItem>
23
+ </MenubarContent>
24
+ </MenubarMenu>
25
+ </Menubar>
26
+ );
27
+
28
+ const meta = {
29
+ title: "Navigation/Menubar",
30
+ parameters: {
31
+ layout: "padded",
32
+ docs: { source: { code: `<Menubar>\n <MenubarMenu>\n <MenubarTrigger>File</MenubarTrigger>\n <MenubarContent>\n <MenubarItem>New Tab</MenubarItem>\n </MenubarContent>\n </MenubarMenu>\n</Menubar>`, language: "tsx" } },
33
+ },
34
+ } satisfies Meta;
35
+
36
+ export default meta;
37
+
38
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,32 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx · controls: scripts/gen-stories.mjs CONTROLS */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Metric } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <div className="grid w-full max-w-lg grid-cols-2 gap-4">
9
+ <Metric label="Active users" value="2,420" trend="up" change="12%" />
10
+ <Metric label="Churn rate" value="1.2%" trend="down" change="0.3%" />
11
+ </div>
12
+ );
13
+
14
+ const meta = {
15
+ title: "Feedback/Metric",
16
+ component: Metric,
17
+ args: { label: "Active users", value: "2,420", trend: "up", change: "12%" },
18
+ argTypes: {
19
+ trend: { control: "inline-radio", options: ["up", "down", "neutral"] },
20
+ label: { control: "text" }, value: { control: "text" }, change: { control: "text" },
21
+ },
22
+ parameters: {
23
+ layout: "centered",
24
+ docs: { source: { code: `<Metric label="Active users" value="2,420" trend="up" change="12%" />`, language: "tsx" } },
25
+ },
26
+ } satisfies Meta;
27
+
28
+ export default meta;
29
+
30
+ export const Playground: StoryObj<typeof meta> = { render: (args) => <Metric {...args} /> };
31
+
32
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,31 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { Button, Dialog, Modal } from "@kinetixui/ui";
6
+
7
+ const Demo = () => (
8
+ <div className="flex flex-wrap gap-3">
9
+ {(["Info", "Confirmation", "Warning", "Destructive"] as const).map((type) => (
10
+ <Modal
11
+ key={type}
12
+ type={type}
13
+ title={`${type} dialog`}
14
+ description="Dialog description text — this modal is the design-source composition (header · divider · body · divider · footer)."
15
+ trigger={<Button variant="Outline">{type}</Button>}
16
+ />
17
+ ))}
18
+ </div>
19
+ );
20
+
21
+ const meta = {
22
+ title: "Overlays/Modal",
23
+ parameters: {
24
+ layout: "centered",
25
+ docs: { source: { code: `<Modal\n type="Confirmation"\n title="Are you sure?"\n description="This action cannot be undone."\n trigger={<Button variant="Outline">Delete</Button>}\n onAction={handleDelete}\n/>`, language: "tsx" } },
26
+ },
27
+ } satisfies Meta;
28
+
29
+ export default meta;
30
+
31
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
@@ -0,0 +1,32 @@
1
+ /* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
2
+ Source of truth: apps/web/src/registry/demos.tsx */
3
+ import * as React from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { NavigationBar } from "@kinetixui/ui";
6
+ import { Search } from "lucide-react";
7
+
8
+ const Demo = () => (
9
+ <NavigationBar
10
+ className="w-full max-w-md rounded-md"
11
+ title="Appointments"
12
+ infoText="3 upcoming"
13
+ onBack={() => {}}
14
+ actions={
15
+ <button type="button" aria-label="Search" className="flex size-9 items-center justify-center rounded-full hover:bg-accent">
16
+ <Search className="size-5" />
17
+ </button>
18
+ }
19
+ />
20
+ );
21
+
22
+ const meta = {
23
+ title: "Navigation/NavigationBar",
24
+ parameters: {
25
+ layout: "centered",
26
+ docs: { source: { code: `<NavigationBar\n title="Appointments"\n infoText="3 upcoming"\n onBack={() => router.back()}\n actions={<Button variant="Ghost" size="icon"><Search /></Button>}\n/>`, language: "tsx" } },
27
+ },
28
+ } satisfies Meta;
29
+
30
+ export default meta;
31
+
32
+ export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };