From f90a32e477bdf4e0616194c4e1fb4e47210ccfad Mon Sep 17 00:00:00 2001 From: Loki Date: Wed, 7 Oct 2026 14:47:53 +0800 Subject: [PATCH] feat: publish popover and command - popover: frosted layer-2 menu surface, p-1 and rounded-menu around control-radius content; aligns to the trigger's start - command: search field, list, empty state, group and items in text-body with rounded-control; no surface of its own, no shortcut, separator or command dialog (portal uses none of them) - the site shows a member combobox built from both Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 3 + README.md | 2 + app/_components/combobox-demo.tsx | 62 +++++++++++++++ app/page.tsx | 6 ++ bun.lock | 51 +++++++++++++ package.json | 1 + registry.json | 33 ++++++++ registry/winlab/ui/command.tsx | 121 ++++++++++++++++++++++++++++++ registry/winlab/ui/popover.tsx | 51 +++++++++++++ 9 files changed, 330 insertions(+) create mode 100644 app/_components/combobox-demo.tsx create mode 100644 registry/winlab/ui/command.tsx create mode 100644 registry/winlab/ui/popover.tsx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 485da55..39e7678 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,6 +66,9 @@ jobs: grep -q 'from "@/components/ui/button"' components/ui/dialog.tsx bunx shadcn@latest add http://localhost:8099/r/select.json http://localhost:8099/r/table.json -y -o ! grep -q 'text-sm' components/ui/select.tsx components/ui/table.tsx + bunx shadcn@latest add http://localhost:8099/r/popover.json http://localhost:8099/r/command.json -y -o + grep -q 'rounded-menu' components/ui/popover.tsx + grep -q 'cmdk' package.json bun run build - if: always() run: docker compose logs diff --git a/README.md b/README.md index c49c359..6bb9656 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ npx shadcn@latest add @winlab/button | `alert-dialog` | `registry:ui` | Confirmation with Cancel and an action | | `select` | `registry:ui` | Single-choice dropdown, same height as `input` | | `table` | `registry:ui` | Data table with muted headers; add `tabular-nums` and `text-right` to number columns | +| `popover` | `registry:ui` | Frosted menu surface anchored to a trigger; `w-(--anchor-width)` matches the trigger | +| `command` | `registry:ui` | Searchable list for a combobox inside a `popover` | | `badge` | `registry:ui` | Status label; variants `default`, `muted`, `outline`, `destructive`, `success`, `warning` | Text falls back in that order: `font-sans` is Inter, then Noto Sans JP, then Noto Sans TC. `font-mono` puts JetBrains Mono in front of the same CJK fonts. Use Inter's `tabular-nums` for amounts and table figures, not `font-mono`. diff --git a/app/_components/combobox-demo.tsx b/app/_components/combobox-demo.tsx new file mode 100644 index 0000000..7ae8c30 --- /dev/null +++ b/app/_components/combobox-demo.tsx @@ -0,0 +1,62 @@ +"use client" + +import * as React from "react" +import { ChevronDownIcon } from "lucide-react" + +import { Button } from "@/registry/winlab/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/registry/winlab/ui/command" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/registry/winlab/ui/popover" + +const members = ["Alice Chen", "Bob Lin", "Carol Wu", "Dave Huang", "Eve Tsai"] + +export function ComboboxDemo() { + const [open, setOpen] = React.useState(false) + const [value, setValue] = React.useState(null) + + return ( + + } + > + + {value ?? "Choose an attendee"} + + + + + + + + No member found. + + {members.map((member) => ( + { + setValue(member) + setOpen(false) + }} + > + {member} + + ))} + + + + + + ) +} diff --git a/app/page.tsx b/app/page.tsx index 0112a73..7507d9b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,5 +1,7 @@ import { PlusIcon } from "lucide-react" +import { ComboboxDemo } from "@/app/_components/combobox-demo" + import { AlertDialog, AlertDialogAction, @@ -144,6 +146,10 @@ export default function Page() { +
+ + +