diff --git a/DESIGN.md b/DESIGN.md index 7a649fd4..83b47702 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -84,13 +84,11 @@ import { | `Switch` | Form | `switch` | — | Stable | | `Textarea` | Form | `textarea` | — | Stable | | `Calendar` | Form | `calendar` | — | Stable | -| `InputOtp` | Form | `input-otp` | — | Stable | | `Slider` | Form | `slider` | — | Stable | | `CodeEditor` | Form | — | Monaco editor, theme-aware | Stable | | `Dialog` | Overlay | `dialog` | — | Stable | | `AlertDialog` | Overlay | `alert-dialog` | — | Stable | | `Sheet` | Overlay | `sheet` | — | Stable | -| `Drawer` | Overlay | `drawer` | — | Stable | | `Tooltip` | Overlay | `tooltip` | — | Stable | | `HoverCard` | Overlay | `hover-card` | — | Stable | | `Command` | Overlay | `command` | Command palette / search | Stable | diff --git a/MIGRATION.md b/MIGRATION.md index 0d1418bb..6aa83990 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -117,10 +117,8 @@ These shadcn components are new additions with no prior equivalent: | `ComboBox` | Searchable select | | `Command` | Command palette (cmdk) | | `ContextMenu` | Right-click menus | -| `Drawer` | Bottom sheet drawer | | `HoverCard` | Hover info cards | | `InputGroup` | Input with addons | -| `InputOTP` | OTP code input | | `Item` | Generic list item | | `KBD` | Keyboard shortcut display | | `NavigationMenu` | Navigation menus | @@ -208,7 +206,6 @@ The following exports no longer exist: - `embla-carousel-react` — Carousel - `react-day-picker` + `date-fns` — Calendar - `react-resizable-panels` — Resizable layouts -- `vaul` — Drawer component ### Removed diff --git a/README.md b/README.md index 0e996a95..06d6add1 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Dark mode is supported via the `.dark` class on a parent element. See [THEMING.m shadcn/ui components built on Radix UI with Tailwind CSS and CVA variants: -Accordion, Alert, AlertDialog, AspectRatio, Avatar, Badge, Breadcrumb, Button, ButtonGroup, Calendar, Card, Carousel, Checkbox, CodeEditor, Collapsible, ComboBox, Command, ContextMenu, Dialog, Drawer, DropdownMenu, Field, HoverCard, Input, InputGroup, InputOTP, Item, KBD, Label, MenuBar, NavigationMenu, RadioGroup, ResizablePanel, ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Sonner, Spinner, Switch, Table, Tabs, Textarea, TetraScience Icon, Toggle, ToggleGroup, Tooltip +Accordion, Alert, AlertDialog, AspectRatio, Avatar, Badge, Breadcrumb, Button, ButtonGroup, Calendar, Card, Carousel, Checkbox, CodeEditor, Collapsible, ComboBox, Command, ContextMenu, Dialog, DropdownMenu, Field, HoverCard, Input, InputGroup, Item, KBD, Label, MenuBar, NavigationMenu, RadioGroup, ResizablePanel, ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Sonner, Spinner, Switch, Table, Tabs, Textarea, TetraScience Icon, Toggle, ToggleGroup, Tooltip ### Composed Components (`composed/`) diff --git a/commitlint.config.js b/commitlint.config.js index b29b5ae8..1a171610 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,3 +1,9 @@ export default { extends: ["@commitlint/config-conventional"], + rules: { + // Allow JIRA-key-prefixed subjects (e.g. "feat: SW-1234 Add validation"), + // which the default subject-case rule rejects as start-case. Matches the + // commit convention documented in AGENTS.md. + "subject-case": [0], + }, }; diff --git a/package.json b/package.json index a1ef175d..3a4de9b0 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,6 @@ "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", - "input-otp": "^1.4.2", "lucide-react": "^0.577.0", "monaco-editor": "^0.52.2", "motion": "^12.38.0", @@ -145,8 +144,7 @@ "streamdown": "^2.5.0", "tailwind-merge": "^3.5.0", "tokenlens": "^1.3.1", - "use-stick-to-bottom": "^1.1.3", - "vaul": "^1.1.2" + "use-stick-to-bottom": "^1.1.3" }, "peerDependencies": { "@aws-sdk/client-athena": "^3.0.0", diff --git a/registry.json b/registry.json index db41838d..bc411f12 100644 --- a/registry.json +++ b/registry.json @@ -127,12 +127,6 @@ "registryDependencies": ["button"], "files": [{ "path": "src/components/ui/dialog.tsx", "type": "registry:ui" }] }, - { - "name": "drawer", - "type": "registry:ui", - "dependencies": ["vaul"], - "files": [{ "path": "src/components/ui/drawer.tsx", "type": "registry:ui" }] - }, { "name": "dropdown-menu", "type": "registry:ui", @@ -163,12 +157,6 @@ "registryDependencies": ["button", "input", "textarea"], "files": [{ "path": "src/components/ui/input-group.tsx", "type": "registry:ui" }] }, - { - "name": "input-otp", - "type": "registry:ui", - "dependencies": ["input-otp", "lucide-react"], - "files": [{ "path": "src/components/ui/input-otp.tsx", "type": "registry:ui" }] - }, { "name": "item", "type": "registry:ui", diff --git a/src/components/ui/drawer.stories.tsx b/src/components/ui/drawer.stories.tsx deleted file mode 100644 index 890bbcdb..00000000 --- a/src/components/ui/drawer.stories.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { expect, within } from "storybook/test" - -import { Button } from "./button" -import { - Drawer, - DrawerContent, - DrawerDescription, - DrawerFooter, - DrawerHeader, - DrawerTitle, -} from "./drawer" - -import type { Meta, StoryObj } from "@storybook/react-vite" - -const meta: Meta = { - title: "Components/Drawer", - component: Drawer, - parameters: { - layout: "centered", - docs: { story: { inline: false, iframeHeight: 400 } }, - }, - tags: ["autodocs"], - argTypes: { - direction: { - control: { type: "select" }, - options: ["bottom", "right", "left", "top"], - }, - }, - args: { - direction: "bottom", - }, -} - -export default meta - -type Story = StoryObj - -function renderDrawer(args: Story["args"]) { - return ( -
- - - - Filter results - - Narrow the dataset by source, status, and reporting range before exporting. - - -
-
Source: All pipelines
-
Status: Active and paused
-
Range: Last 30 days
-
- - - - -
-
-
- ) -} - -export const Bottom: Story = { - render: renderDrawer, - parameters: { - zephyr: { testCaseId: "SW-T1233" }, - }, - play: async ({ canvasElement, step }) => { - const body = within(canvasElement.ownerDocument.body) - - await step("Drawer portaled content renders", async () => { - expect(body.getByText("Filter results")).toBeInTheDocument() - expect( - body.getByText( - "Narrow the dataset by source, status, and reporting range before exporting.", - ), - ).toBeInTheDocument() - }) - - await step("Footer actions render", async () => { - expect(body.getByRole("button", { name: "Apply filters" })).toBeInTheDocument() - expect(body.getByRole("button", { name: "Reset" })).toBeInTheDocument() - }) - }, -} - -export const Right: Story = { - args: { - direction: "right", - }, - render: renderDrawer, - parameters: { - zephyr: { testCaseId: "SW-T1234" }, - }, - play: async ({ canvasElement, step }) => { - const body = within(canvasElement.ownerDocument.body) - - await step("Drawer portaled content renders", async () => { - expect(body.getByText("Filter results")).toBeInTheDocument() - expect( - body.getByText( - "Narrow the dataset by source, status, and reporting range before exporting.", - ), - ).toBeInTheDocument() - }) - - await step("Footer actions render", async () => { - expect(body.getByRole("button", { name: "Apply filters" })).toBeInTheDocument() - expect(body.getByRole("button", { name: "Reset" })).toBeInTheDocument() - }) - }, -} - -export const Left: Story = { - args: { - direction: "left", - }, - render: renderDrawer, - parameters: { - zephyr: { testCaseId: "SW-T1235" }, - }, - play: async ({ canvasElement, step }) => { - const body = within(canvasElement.ownerDocument.body) - - await step("Drawer portaled content renders", async () => { - expect(body.getByText("Filter results")).toBeInTheDocument() - expect( - body.getByText( - "Narrow the dataset by source, status, and reporting range before exporting.", - ), - ).toBeInTheDocument() - }) - - await step("Footer actions render", async () => { - expect(body.getByRole("button", { name: "Apply filters" })).toBeInTheDocument() - expect(body.getByRole("button", { name: "Reset" })).toBeInTheDocument() - }) - }, -} - -export const Top: Story = { - args: { - direction: "top", - }, - render: renderDrawer, - parameters: { - zephyr: { testCaseId: "SW-T1236" }, - }, - play: async ({ canvasElement, step }) => { - const body = within(canvasElement.ownerDocument.body) - - await step("Drawer portaled content renders", async () => { - expect(body.getByText("Filter results")).toBeInTheDocument() - expect( - body.getByText( - "Narrow the dataset by source, status, and reporting range before exporting.", - ), - ).toBeInTheDocument() - }) - - await step("Footer actions render", async () => { - expect(body.getByRole("button", { name: "Apply filters" })).toBeInTheDocument() - expect(body.getByRole("button", { name: "Reset" })).toBeInTheDocument() - }) - }, -} \ No newline at end of file diff --git a/src/components/ui/drawer.tsx b/src/components/ui/drawer.tsx deleted file mode 100644 index ea930ee9..00000000 --- a/src/components/ui/drawer.tsx +++ /dev/null @@ -1,131 +0,0 @@ -"use client" - -import * as React from "react" -import { Drawer as DrawerPrimitive } from "vaul" - -import { cn } from "@/lib/utils" - -function Drawer({ - ...props -}: React.ComponentProps) { - return -} - -function DrawerTrigger({ - ...props -}: React.ComponentProps) { - return -} - -function DrawerPortal({ - ...props -}: React.ComponentProps) { - return -} - -function DrawerClose({ - ...props -}: React.ComponentProps) { - return -} - -function DrawerOverlay({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function DrawerContent({ - className, - children, - ...props -}: React.ComponentProps) { - return ( - - - -
- {children} - - - ) -} - -function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function DrawerTitle({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function DrawerDescription({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { - Drawer, - DrawerPortal, - DrawerOverlay, - DrawerTrigger, - DrawerClose, - DrawerContent, - DrawerHeader, - DrawerFooter, - DrawerTitle, - DrawerDescription, -} diff --git a/src/components/ui/input-otp.stories.tsx b/src/components/ui/input-otp.stories.tsx deleted file mode 100644 index 89cf64c3..00000000 --- a/src/components/ui/input-otp.stories.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { expect, within } from "storybook/test" - -import { - InputOTP, - InputOTPGroup, - InputOTPSeparator, - InputOTPSlot, -} from "./input-otp" - -import type { Meta, StoryObj } from "@storybook/react-vite" - - -const meta: Meta = { - title: "Components/Input OTP", - component: InputOTP, - parameters: { - layout: "centered", - }, - tags: ["autodocs"], - args: { - maxLength: 6, - value: "123456", - }, -} - -export default meta - -type Story = StoryObj - -function renderOtp(args: Story["args"], withSeparator = false) { - return ( - - - - - - - {withSeparator && } - - - - - - - ) -} - -export const Default: Story = { - render: renderOtp, - parameters: { - zephyr: { testCaseId: "SW-T1255" }, - }, - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement) - - await step("OTP slots display entered digits", async () => { - expect(canvas.getByText("1")).toBeInTheDocument() - expect(canvas.getByText("2")).toBeInTheDocument() - expect(canvas.getByText("3")).toBeInTheDocument() - expect(canvas.getByText("4")).toBeInTheDocument() - expect(canvas.getByText("5")).toBeInTheDocument() - expect(canvas.getByText("6")).toBeInTheDocument() - }) - }, -} - -export const WithSeparator: Story = { - render: (args) => renderOtp(args, true), - parameters: { - zephyr: { testCaseId: "SW-T1256" }, - }, - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement) - - await step("OTP slots display entered digits", async () => { - expect(canvas.getByText("1")).toBeInTheDocument() - expect(canvas.getByText("6")).toBeInTheDocument() - }) - - await step("Separator between OTP groups is present", async () => { - expect(canvas.getByRole("separator")).toBeInTheDocument() - }) - }, -} \ No newline at end of file diff --git a/src/components/ui/input-otp.tsx b/src/components/ui/input-otp.tsx deleted file mode 100644 index 73a1b81c..00000000 --- a/src/components/ui/input-otp.tsx +++ /dev/null @@ -1,88 +0,0 @@ -"use client" - -import { OTPInput, OTPInputContext } from "input-otp" -import { MinusIcon } from "lucide-react" -import * as React from "react" - -import { cn } from "@/lib/utils" - - -function InputOTP({ - className, - containerClassName, - ...props -}: React.ComponentProps & { - containerClassName?: string -}) { - return ( - - ) -} - -function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function InputOTPSlot({ - index, - className, - ...props -}: React.ComponentProps<"div"> & { - index: number -}) { - const inputOTPContext = React.useContext(OTPInputContext) - const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {} - - return ( -
- {char} - {hasFakeCaret && ( -
-
-
- )} -
- ) -} - -function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) { - return ( -
- -
- ) -} - -export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } diff --git a/src/index.ts b/src/index.ts index 67bc8f1d..eabd72ef 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,13 +53,11 @@ export * from "@/components/ui/command"; export * from "@/components/ui/context-menu"; export * from "@/components/ui/data-table"; export * from "@/components/ui/dialog"; -export * from "@/components/ui/drawer"; export * from "@/components/ui/dropdown-menu"; export * from "@/components/ui/field"; export * from "@/components/ui/hover-card"; export * from "@/components/ui/input"; export * from "@/components/ui/input-group"; -export * from "@/components/ui/input-otp"; export * from "@/components/ui/item"; export * from "@/components/ui/kbd"; export * from "@/components/ui/label"; diff --git a/yarn.lock b/yarn.lock index 1cab197f..1c718a7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4946,7 +4946,7 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-dialog@npm:1.1.15, @radix-ui/react-dialog@npm:^1.1.1, @radix-ui/react-dialog@npm:^1.1.6": +"@radix-ui/react-dialog@npm:1.1.15, @radix-ui/react-dialog@npm:^1.1.6": version: 1.1.15 resolution: "@radix-ui/react-dialog@npm:1.1.15" dependencies: @@ -7960,7 +7960,6 @@ __metadata: fast-xml-parser: "npm:^5.3.4" globals: "npm:^15.9.0" husky: "npm:^9.1.7" - input-otp: "npm:^1.4.2" jsdom: "npm:^28.1.0" lint-staged: "npm:^15.2.0" lucide-react: "npm:^0.577.0" @@ -7997,7 +7996,6 @@ __metadata: typescript: "npm:^5.5.3" typescript-eslint: "npm:^8.0.1" use-stick-to-bottom: "npm:^1.1.3" - vaul: "npm:^1.1.2" vite: "npm:^7.3.1" vite-plugin-dts: "npm:^4.5.4" vitest: "npm:^3" @@ -15758,16 +15756,6 @@ __metadata: languageName: node linkType: hard -"input-otp@npm:^1.4.2": - version: 1.4.2 - resolution: "input-otp@npm:1.4.2" - peerDependencies: - react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/d3a3216a75ed832993f3f2852edd7a85c5bae30ea6d251182119120488bbf9fed7cfdd91819bcee6daff57b3cfcbca94fd16d6a7c92cee4d806c0d4fa6ff1128 - languageName: node - linkType: hard - "internal-slot@npm:^1.1.0": version: 1.1.0 resolution: "internal-slot@npm:1.1.0" @@ -24435,18 +24423,6 @@ __metadata: languageName: node linkType: hard -"vaul@npm:^1.1.2": - version: 1.1.2 - resolution: "vaul@npm:1.1.2" - dependencies: - "@radix-ui/react-dialog": "npm:^1.1.1" - peerDependencies: - react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/a6da539eb5576c0004a6b17e3673ea1db2c34e80355860131183abf53279ce025bbd016d542c345d1cc8464ad12f9dc9860949c751055d8a84961e8472a53707 - languageName: node - linkType: hard - "vfile-location@npm:^5.0.0": version: 5.0.3 resolution: "vfile-location@npm:5.0.3"