From 80db25b50c734e9658e7fdf76e70ea06d220466c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 5 Jul 2026 13:16:34 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat(ui):=20add=20base-ui=20primitives=20to?= =?UTF-8?q?=20close=20design=E2=86=94code=20gap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add nine shadcn base-nova style components backed by @base-ui/react, matching the existing ui/ conventions (data-slot, cn, JSDoc): table, checkbox, switch, radio-group, accordion, label, dialog, select, tooltip. These previously existed only in the Figma design system as "System Asset (no product code)"; the Figma Dev Handoff is now synced to Ready. Verified: tsc --noEmit and eslint clean; ui-added.test.tsx mounts and renders all nine in jsdom (checked/indicator, thumb, radio items, accordion panel, dialog portal, select/tooltip triggers). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RjGVapDZ3k7V7zKYk16P4C --- apps/desktop/src/components/ui/accordion.tsx | 76 +++++++++ apps/desktop/src/components/ui/checkbox.tsx | 39 +++++ apps/desktop/src/components/ui/dialog.tsx | 120 ++++++++++++++ apps/desktop/src/components/ui/label.tsx | 21 +++ .../desktop/src/components/ui/radio-group.tsx | 50 ++++++ apps/desktop/src/components/ui/select.tsx | 128 +++++++++++++++ apps/desktop/src/components/ui/switch.tsx | 34 ++++ apps/desktop/src/components/ui/table.tsx | 122 +++++++++++++++ apps/desktop/src/components/ui/tooltip.tsx | 53 +++++++ .../src/components/ui/ui-added.test.tsx | 148 ++++++++++++++++++ 10 files changed, 791 insertions(+) create mode 100644 apps/desktop/src/components/ui/accordion.tsx create mode 100644 apps/desktop/src/components/ui/checkbox.tsx create mode 100644 apps/desktop/src/components/ui/dialog.tsx create mode 100644 apps/desktop/src/components/ui/label.tsx create mode 100644 apps/desktop/src/components/ui/radio-group.tsx create mode 100644 apps/desktop/src/components/ui/select.tsx create mode 100644 apps/desktop/src/components/ui/switch.tsx create mode 100644 apps/desktop/src/components/ui/table.tsx create mode 100644 apps/desktop/src/components/ui/tooltip.tsx create mode 100644 apps/desktop/src/components/ui/ui-added.test.tsx diff --git a/apps/desktop/src/components/ui/accordion.tsx b/apps/desktop/src/components/ui/accordion.tsx new file mode 100644 index 00000000..752e33a0 --- /dev/null +++ b/apps/desktop/src/components/ui/accordion.tsx @@ -0,0 +1,76 @@ +"use client" + +import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +/** Render a vertically stacked set of collapsible sections. */ +function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) { + return ( + + ) +} + +/** Render one collapsible accordion item. */ +function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) { + return ( + + ) +} + +/** Render the clickable header that toggles an item open or closed. */ +function AccordionTrigger({ + className, + children, + ...props +}: AccordionPrimitive.Trigger.Props) { + return ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + + ) +} + +/** Render the collapsible content panel of an item. */ +function AccordionContent({ + className, + children, + ...props +}: AccordionPrimitive.Panel.Props) { + return ( + +
{children}
+
+ ) +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/apps/desktop/src/components/ui/checkbox.tsx b/apps/desktop/src/components/ui/checkbox.tsx new file mode 100644 index 00000000..f3b6cc89 --- /dev/null +++ b/apps/desktop/src/components/ui/checkbox.tsx @@ -0,0 +1,39 @@ +"use client" + +import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox" +import { Check, Minus } from "lucide-react" + +import { cn } from "@/lib/utils" + +/** Render an accessible checkbox with checked and indeterminate states. */ +function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) { + return ( + + + {props.indeterminate ? ( + + ) : ( + + )} + + + ) +} + +export { Checkbox } diff --git a/apps/desktop/src/components/ui/dialog.tsx b/apps/desktop/src/components/ui/dialog.tsx new file mode 100644 index 00000000..ec84c170 --- /dev/null +++ b/apps/desktop/src/components/ui/dialog.tsx @@ -0,0 +1,120 @@ +"use client" + +import * as React from "react" +import { Dialog as DialogPrimitive } from "@base-ui/react/dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +/** Render a modal dialog root. */ +function Dialog(props: DialogPrimitive.Root.Props) { + return +} + +/** Render the element that opens the dialog. */ +function DialogTrigger(props: DialogPrimitive.Trigger.Props) { + return +} + +/** Render an element that closes the dialog. */ +function DialogClose(props: DialogPrimitive.Close.Props) { + return +} + +/** Render the dialog backdrop, surface, and default close button. */ +function DialogContent({ + className, + children, + ...props +}: DialogPrimitive.Popup.Props) { + return ( + + + + {children} + + + Close + + + + ) +} + +/** Group the dialog title and description. */ +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +/** Group the dialog action buttons. */ +function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +/** Render the dialog title. */ +function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) { + return ( + + ) +} + +/** Render the dialog description. */ +function DialogDescription({ + className, + ...props +}: DialogPrimitive.Description.Props) { + return ( + + ) +} + +export { + Dialog, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/apps/desktop/src/components/ui/label.tsx b/apps/desktop/src/components/ui/label.tsx new file mode 100644 index 00000000..70a3cae7 --- /dev/null +++ b/apps/desktop/src/components/ui/label.tsx @@ -0,0 +1,21 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +/** Render a form label associated with a control. */ +function Label({ className, ...props }: React.ComponentProps<"label">) { + return ( +