♻️ refactor(web): consolidate design-system primitives and responsive data views

This commit is contained in:
t0ng7u
2026-07-11 05:13:16 +08:00
parent 262ab93123
commit 0918bdb49a
451 changed files with 7295 additions and 7693 deletions
+8 -51
View File
@@ -26,10 +26,6 @@ import { HugeiconsIcon } from '@hugeicons/react'
import * as React from 'react'
import { Button } from '@/components/ui/button'
import {
ComboboxInput as LegacyComboboxInput,
type ComboboxInputOption,
} from '@/components/ui/combobox-input'
import {
InputGroup,
InputGroupAddon,
@@ -38,46 +34,7 @@ import {
} from '@/components/ui/input-group'
import { cn } from '@/lib/utils'
type LegacyComboboxProps = {
options: ComboboxInputOption[]
value?: string
onValueChange?: (value: string | null) => void
placeholder?: string
searchPlaceholder?: string
emptyText?: string
allowCustomValue?: boolean
className?: string
id?: string
openOnFocus?: boolean
}
function Combobox(props: LegacyComboboxProps): React.ReactElement
function Combobox<Value, Multiple extends boolean | undefined = false>(
props: ComboboxPrimitive.Root.Props<Value, Multiple>
): React.ReactElement
function Combobox(
props:
| ComboboxPrimitive.Root.Props<unknown, boolean | undefined>
| LegacyComboboxProps
) {
if ('options' in props) {
return (
<LegacyComboboxInput
id={props.id}
options={props.options}
value={props.value ?? ''}
onValueChange={(value) => props.onValueChange?.(value)}
placeholder={props.searchPlaceholder ?? props.placeholder}
emptyText={props.emptyText}
className={props.className}
allowCustomValue={props.allowCustomValue}
openOnFocus={props.openOnFocus}
/>
)
}
return <ComboboxPrimitive.Root {...props} />
}
const Combobox = ComboboxPrimitive.Root
function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
return <ComboboxPrimitive.Value data-slot='combobox-value' {...props} />
@@ -183,7 +140,7 @@ function ComboboxContent({
data-slot='combobox-content'
data-chips={!!anchor}
className={cn(
'group/combobox-content bg-popover text-popover-foreground ring-foreground/10 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg shadow-md ring-1 duration-100 data-[chips=true]:min-w-(--anchor-width) *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:shadow-none',
'dark group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',
className
)}
{...props}
@@ -215,7 +172,7 @@ function ComboboxItem({
<ComboboxPrimitive.Item
data-slot='combobox-item'
className={cn(
"data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
@@ -253,7 +210,7 @@ function ComboboxLabel({
return (
<ComboboxPrimitive.GroupLabel
data-slot='combobox-label'
className={cn('text-muted-foreground px-2 py-1.5 text-xs', className)}
className={cn('px-2 py-1.5 text-xs text-muted-foreground', className)}
{...props}
/>
)
@@ -270,7 +227,7 @@ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
<ComboboxPrimitive.Empty
data-slot='combobox-empty'
className={cn(
'text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/combobox-content:flex',
'hidden w-full justify-center py-2 text-center text-sm text-muted-foreground group-data-empty/combobox-content:flex',
className
)}
{...props}
@@ -285,7 +242,7 @@ function ComboboxSeparator({
return (
<ComboboxPrimitive.Separator
data-slot='combobox-separator'
className={cn('bg-border -mx-1 my-1 h-px', className)}
className={cn('-mx-1 my-1 h-px bg-border', className)}
{...props}
/>
)
@@ -300,7 +257,7 @@ function ComboboxChips({
<ComboboxPrimitive.Chips
data-slot='combobox-chips'
className={cn(
'border-input focus-within:border-ring focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-destructive/20 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40 flex min-h-8 flex-wrap items-center gap-1 rounded-lg border bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:ring-3 has-aria-invalid:ring-3 has-data-[slot=combobox-chip]:px-1',
'flex min-h-8 flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40',
className
)}
{...props}
@@ -320,7 +277,7 @@ function ComboboxChip({
<ComboboxPrimitive.Chip
data-slot='combobox-chip'
className={cn(
'bg-muted text-foreground flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm px-1.5 text-xs font-medium whitespace-nowrap has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0',
'flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0',
className
)}
{...props}