{rows.map((row) => {
const key = getRowKey ? getRowKey(row) : row.id
return (
- {props.renderCard ? (
- props.renderCard(row)
- ) : (
-
- )}
+
)
})}
diff --git a/web/default/src/components/data-table/static/static-data-table-classnames.ts b/web/default/src/components/data-table/static/static-data-table-classnames.ts
index 4d35cc7747..9282ea7056 100644
--- a/web/default/src/components/data-table/static/static-data-table-classnames.ts
+++ b/web/default/src/components/data-table/static/static-data-table-classnames.ts
@@ -24,9 +24,10 @@ export const staticDataTableClassNames = {
compactHeaderRow: 'hover:bg-transparent',
mutedHeaderRow:
'[background-color:var(--table-header)] hover:[background-color:var(--table-header-hover)]',
- compactHeaderCell: 'text-muted-foreground py-2 text-xs font-medium',
+ compactHeaderCell:
+ 'text-muted-foreground py-2 text-[10px] font-medium tracking-wider uppercase',
compactHeaderCellRight:
- 'text-muted-foreground py-2 text-right text-xs font-medium',
+ 'text-muted-foreground py-2 text-right text-[10px] font-medium tracking-wider uppercase',
compactCell: 'py-2.5',
compactTopCell: 'py-2.5 align-top',
compactTopNumericCell: 'py-2.5 text-right align-top font-mono',
diff --git a/web/default/src/components/data-table/static/static-data-table.tsx b/web/default/src/components/data-table/static/static-data-table.tsx
index 2779bb6e2c..bde3f40609 100644
--- a/web/default/src/components/data-table/static/static-data-table.tsx
+++ b/web/default/src/components/data-table/static/static-data-table.tsx
@@ -25,7 +25,7 @@ import {
TableHead,
TableHeader,
TableRow,
-} from '@/components/design-system/table'
+} from '@/components/ui/table'
import { cn } from '@/lib/utils'
import { TruncatedCell } from '../core/truncated-cell'
diff --git a/web/default/src/components/data-table/static/static-row-actions.tsx b/web/default/src/components/data-table/static/static-row-actions.tsx
index eb845ed45d..581b66f549 100644
--- a/web/default/src/components/data-table/static/static-row-actions.tsx
+++ b/web/default/src/components/data-table/static/static-row-actions.tsx
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
*/
import { Pencil, Trash2 } from 'lucide-react'
-import { Button } from '@/components/design-system/button'
+import { Button } from '@/components/ui/button'
import {
DropdownMenuItem,
DropdownMenuShortcut,
diff --git a/web/default/src/components/data-table/toolbar/bulk-actions.tsx b/web/default/src/components/data-table/toolbar/bulk-actions.tsx
index 745199141f..a10fc190f9 100644
--- a/web/default/src/components/data-table/toolbar/bulk-actions.tsx
+++ b/web/default/src/components/data-table/toolbar/bulk-actions.tsx
@@ -21,8 +21,8 @@ import { X } from 'lucide-react'
import { useState, useEffect, useLayoutEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
-import { Button } from '@/components/design-system/button'
import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import {
Tooltip,
@@ -184,8 +184,9 @@ export function DataTableBulkActions
({
render={
diff --git a/web/default/src/components/data-table/toolbar/faceted-filter.tsx b/web/default/src/components/data-table/toolbar/faceted-filter.tsx
index a0327728c8..9dc31b0cc5 100644
--- a/web/default/src/components/data-table/toolbar/faceted-filter.tsx
+++ b/web/default/src/components/data-table/toolbar/faceted-filter.tsx
@@ -16,12 +16,13 @@ along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
-import type { Column } from '@tanstack/react-table'
-import { Check as CheckIcon, ChevronDown } from 'lucide-react'
-import type { ComponentType, ReactNode } from 'react'
+import { type Column } from '@tanstack/react-table'
+import { Check as CheckIcon, PlusCircle as PlusCircledIcon } from 'lucide-react'
+import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Button } from '@/components/design-system/button'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
import {
Command,
CommandEmpty,
@@ -30,12 +31,13 @@ import {
CommandItem,
CommandList,
CommandSeparator,
-} from '@/components/design-system/command'
+} from '@/components/ui/command'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover'
+import { Separator } from '@/components/ui/separator'
import { cn } from '@/lib/utils'
type DataTableFacetedFilterProps = {
@@ -44,15 +46,15 @@ type DataTableFacetedFilterProps = {
options: {
label: string
value: string
- icon?: ComponentType<{ className?: string }>
- iconNode?: ReactNode
+ icon?: React.ComponentType<{ className?: string }>
+ iconNode?: React.ReactNode
count?: number
}[]
/** Enable single select mode (only one option can be selected at a time) */
singleSelect?: boolean
}
-export function DataTableFacetedFilter({
+function DataTableFacetedFilterInner({
column,
title,
options,
@@ -62,21 +64,6 @@ export function DataTableFacetedFilter({
const facets = column?.getFacetedUniqueValues()
const filterValue = column?.getFilterValue() as string[] | undefined
const selectedValues = new Set(filterValue)
- const resolvedTitle = title ?? t('Filter')
- const selectedOptions = options.filter((option) =>
- selectedValues.has(option.value)
- )
-
- let selectedSummary: string | null = null
- if (selectedValues.size === 1 && selectedOptions.length === 1) {
- selectedSummary = t(selectedOptions[0].label)
- } else if (selectedValues.size === 2 && selectedOptions.length === 2) {
- selectedSummary = selectedOptions
- .map((option) => t(option.label))
- .join(', ')
- } else if (selectedValues.size > 0) {
- selectedSummary = `${selectedValues.size} ${t('selected')}`
- }
const handleOptionSelect = (optionValue: string) => {
const nextSelectedValues = getNextSelectedValues(
@@ -94,69 +81,57 @@ export function DataTableFacetedFilter({
+
}
>
-
- {resolvedTitle}
-
- {selectedSummary && (
+
+ {title}
+ {selectedValues?.size > 0 && (
<>
-
- :
-
-
- {selectedSummary}
-
+
+
+ {selectedValues.size}
+
+
+ {selectedValues.size > 2 ? (
+
+ {selectedValues.size} {t('selected')}
+
+ ) : (
+ options
+ .filter((option) => selectedValues.has(option.value))
+ .map((option) => (
+
+ {t(option.label)}
+
+ ))
+ )}
+
>
)}
-
-
+
-
+
{t('No results found.')}
{options.map((option) => {
const isSelected = selectedValues.has(option.value)
- let optionIcon: ReactNode = null
- if (option.iconNode) {
- optionIcon = (
-
- {option.iconNode}
-
- )
- } else if (option.icon) {
- optionIcon = (
-
- )
- }
-
- const optionCount =
- typeof option.count === 'number'
- ? option.count
- : facets?.get(option.value)
-
return (
handleOptionSelect(option.value)}
- aria-selected={isSelected}
>
({
: 'opacity-50 [&_svg]:invisible'
)}
>
-
+
- {optionIcon}
+ {option.iconNode ? (
+
+ {option.iconNode}
+
+ ) : option.icon ? (
+
+ ) : null}
{t(option.label)}
- {optionCount != null && (
-
- {optionCount}
+ {typeof option.count === 'number' ? (
+
+ {option.count}
- )}
+ ) : facets?.get(option.value) ? (
+
+ {facets.get(option.value)}
+
+ ) : null}
)
})}
@@ -207,6 +189,10 @@ export function DataTableFacetedFilter({
)
}
+export const DataTableFacetedFilter = React.memo(
+ DataTableFacetedFilterInner
+) as typeof DataTableFacetedFilterInner
+
function getNextSelectedValues(
selectedValues: Set,
optionValue: string,
@@ -223,5 +209,5 @@ function getNextSelectedValues(
nextSelectedValues.add(optionValue)
}
- return [...nextSelectedValues]
+ return Array.from(nextSelectedValues)
}
diff --git a/web/default/src/components/data-table/toolbar/filter-panel.tsx b/web/default/src/components/data-table/toolbar/filter-panel.tsx
deleted file mode 100644
index 05b2975457..0000000000
--- a/web/default/src/components/data-table/toolbar/filter-panel.tsx
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import type { Table } from '@tanstack/react-table'
-import { ChevronDown, Loader2 } from 'lucide-react'
-import { useState, type ComponentProps, type ReactNode } from 'react'
-import { useTranslation } from 'react-i18next'
-
-import { Button } from '@/components/design-system/button'
-import { Input } from '@/components/design-system/input'
-import { Badge } from '@/components/ui/badge'
-import {
- Drawer,
- DrawerContent,
- DrawerDescription,
- DrawerFooter,
- DrawerHeader,
- DrawerTitle,
- DrawerTrigger,
-} from '@/components/ui/drawer'
-import { useMediaQuery } from '@/hooks'
-import { cn } from '@/lib/utils'
-
-import { DataTableViewOptions } from './view-options'
-
-export interface DataTableFilterPanelProps {
- table: Table
- primaryFilters: ReactNode
- advancedFilters?: ReactNode
- mobilePinnedFilters?: ReactNode
- mobileFilters?: ReactNode
- mobileFilterCount?: number
- stats?: ReactNode
- actionStart?: ReactNode
- viewToggle?: ReactNode
- hideViewOptions?: boolean
- hasActiveFilters: boolean
- hasAdvancedActiveFilters?: boolean
- advancedFilterCount?: number
- searchLoading?: boolean
- onReset: () => void
- onSearch?: () => void
- inlineActions?: boolean
- className?: string
-}
-
-interface DataTableFilterFieldProps {
- children: ReactNode
- wide?: boolean
- className?: string
-}
-
-export function DataTableFilterField(props: DataTableFilterFieldProps) {
- return (
- button]:w-full [&>input]:w-full [&_[data-slot=select-trigger]]:w-full [&_[data-slot=select-trigger]]:text-sm [&_[data-slot=select-value]]:leading-5',
- props.wide && 'sm:col-span-2',
- props.className
- )}
- >
- {props.children}
-
- )
-}
-
-export function DataTableFilterInput(props: ComponentProps) {
- return (
-
- )
-}
-
-export function DataTableFilterPanel(
- props: DataTableFilterPanelProps
-) {
- const { t } = useTranslation()
- const [advancedOpen, setAdvancedOpen] = useState(false)
- const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false)
- const isMobile = useMediaQuery('(max-width: 640px)')
-
- const hasAdvancedFilters = props.advancedFilters != null
- const hasMobileFilters =
- props.mobileFilters != null || props.advancedFilters != null
- const activeAdvancedCount =
- props.advancedFilterCount ?? (props.hasAdvancedActiveFilters ? 1 : 0)
- const activeMobileFilterCount = props.mobileFilterCount ?? activeAdvancedCount
-
- const handleMobileReset = () => {
- props.onReset()
- setMobileFiltersOpen(false)
- }
-
- const handleMobileSubmit = () => {
- props.onSearch?.()
- setMobileFiltersOpen(false)
- }
-
- const advancedToggle = hasAdvancedFilters ? (
-
- ) : null
-
- const viewOptions = !props.hideViewOptions ? (
-
- ) : null
-
- const desktopActions = (
-
- {props.actionStart}
-
- {props.onSearch && (
-
- )}
- {props.viewToggle}
- {viewOptions}
-
- )
-
- if (isMobile && props.mobilePinnedFilters != null) {
- return (
-
-
-
{props.mobilePinnedFilters}
-
-
- {props.stats}
-
- {props.actionStart}
- {hasMobileFilters && (
- 0 &&
- 'text-primary hover:text-primary'
- )}
- >
- {t('Filter')}
- {activeMobileFilterCount > 0 && (
-
- {activeMobileFilterCount}
-
- )}
-
- }
- />
- )}
- {!hasMobileFilters && (
-
- )}
- {props.onSearch && (
-
- )}
- {props.viewToggle}
- {viewOptions}
-
-
-
-
- {hasMobileFilters && (
-
-
-
- {t('Filter')}
- {t('Filters')}
-
-
- {props.mobileFilters ?? (
- <>
- {props.primaryFilters}
- {props.advancedFilters}
- >
- )}
-
-
-
-
-
-
-
- )}
-
- )
- }
-
- return (
-
-
-
- {props.primaryFilters}
-
- {advancedToggle && (
-
- {advancedToggle}
-
- )}
- {props.inlineActions && desktopActions}
-
-
- {advancedOpen && props.advancedFilters && (
-
- {props.advancedFilters}
-
- )}
-
- {(!props.inlineActions || props.stats != null) && (
-
- {props.stats}
- {!props.inlineActions && desktopActions}
-
- )}
-
- )
-}
diff --git a/web/default/src/components/data-table/toolbar/toolbar.tsx b/web/default/src/components/data-table/toolbar/toolbar.tsx
index 51c3cc4394..6d1881a079 100644
--- a/web/default/src/components/data-table/toolbar/toolbar.tsx
+++ b/web/default/src/components/data-table/toolbar/toolbar.tsx
@@ -17,15 +17,18 @@ along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
import type { Table } from '@tanstack/react-table'
+import { ChevronDown, Loader2, X as Cross2Icon } from 'lucide-react'
import * as React from 'react'
import { useState, type ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
-import { Input } from '@/components/design-system/input'
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
import { useDebounce } from '@/hooks'
+import { cn } from '@/lib/utils'
import { DataTableFacetedFilter } from './faceted-filter'
-import { DataTableFilterField, DataTableFilterPanel } from './filter-panel'
+import { DataTableViewOptions } from './view-options'
type FilterDef = {
columnId: string
@@ -150,6 +153,7 @@ export type DataTableToolbarProps = {
*/
export function DataTableToolbar(props: DataTableToolbarProps) {
const { t } = useTranslation()
+ const [expanded, setExpanded] = useState(false)
const [isSearchComposing, setIsSearchComposing] = useState(false)
const filters = props.filters ?? []
@@ -242,29 +246,32 @@ export function DataTableToolbar(props: DataTableToolbarProps) {
const searchInput = (
)
- const filterChips = filters.map((filter) => {
- const column = props.table.getColumn(filter.columnId)
- if (!column) return null
- return (
-
-
-
- )
- })
+ const filterChips = React.useMemo(
+ () =>
+ filters.map((filter) => {
+ const column = props.table.getColumn(filter.columnId)
+ if (!column) return null
+ return (
+
+ )
+ }),
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [props.filters, props.table]
+ )
const handleReset = () => {
setIsSearchComposing(false)
@@ -274,57 +281,118 @@ export function DataTableToolbar(props: DataTableToolbarProps) {
props.onReset?.()
}
- const primarySearch =
- props.customSearch !== undefined ? props.customSearch : searchInput
- const additionalFilterCount =
- filters.length + (props.additionalSearch != null ? 1 : 0)
- const inlineActions =
- additionalFilterCount <= 3 && !hasExpandable && props.leftActions == null
- const useWidePrimarySearch = !inlineActions && additionalFilterCount <= 3
- const secondaryMobileFilters =
- props.additionalSearch != null ||
- filterChips.some(Boolean) ||
- hasExpandable ? (
- <>
- {props.additionalSearch}
- {filterChips}
- {props.expandable}
- >
- ) : undefined
- const nonSearchColumnFilterCount = props.table
- .getState()
- .columnFilters.filter((filter) => filter.id !== props.searchKey).length
- const mobileFilterCount =
- nonSearchColumnFilterCount + (props.hasExpandedActiveFilters ? 1 : 0)
+ // Reset: outline text-only for form mode (always visible, disabled when
+ // nothing to reset); ghost text + X for filter-as-you-type mode (only
+ // visible when active filters exist).
+ let resetButton: ReactNode = null
+ if (hasSearch) {
+ resetButton = (
+
+ )
+ } else if (isFiltered) {
+ resetButton = (
+
+ )
+ }
- return (
-
-
- {primarySearch}
-
+ const searchButton = hasSearch ? (
+
+ ) : null
+
+ const viewOptionsNode = !props.hideViewOptions ? (
+
+ ) : null
+
+ const viewToggleNode = props.viewToggle ?? null
+
+ const expandToggle = hasExpandable ? (
+
+ ) : null
+
+ const hasLeftActions = props.leftActions != null
+
+ if (hasLeftActions) {
+ return (
+
+
+ {props.customSearch !== undefined ? props.customSearch : searchInput}
{props.additionalSearch}
{filterChips}
- >
- }
- advancedFilters={props.expandable}
- mobilePinnedFilters={primarySearch}
- mobileFilters={secondaryMobileFilters}
- mobileFilterCount={mobileFilterCount}
- stats={props.leftActions}
- actionStart={props.preActions}
- viewToggle={props.viewToggle}
- hideViewOptions={props.hideViewOptions}
- hasActiveFilters={isFiltered}
- hasAdvancedActiveFilters={props.hasExpandedActiveFilters}
- advancedFilterCount={props.hasExpandedActiveFilters ? 1 : 0}
- searchLoading={props.searchLoading}
- onReset={handleReset}
- onSearch={hasSearch ? props.onSearch : undefined}
- inlineActions={inlineActions}
- className={props.className}
- />
+
+ {expandToggle}
+
+
+
+ {expanded && hasExpandable && (
+
+ {props.expandable}
+
+ )}
+
+
+ {props.leftActions}
+
+ {props.preActions}
+ {resetButton}
+ {searchButton}
+ {viewToggleNode}
+ {viewOptionsNode}
+
+
+
+ )
+ }
+
+ return (
+
+ {props.customSearch !== undefined ? props.customSearch : searchInput}
+ {props.additionalSearch}
+ {filterChips}
+ {expanded && hasExpandable && props.expandable}
+
+
+ {props.preActions}
+ {resetButton}
+ {searchButton}
+ {viewToggleNode}
+ {viewOptionsNode}
+ {expandToggle}
+
+
)
}
diff --git a/web/default/src/components/data-table/toolbar/view-mode-toggle.tsx b/web/default/src/components/data-table/toolbar/view-mode-toggle.tsx
index b734a5ca04..0e999d6c49 100644
--- a/web/default/src/components/data-table/toolbar/view-mode-toggle.tsx
+++ b/web/default/src/components/data-table/toolbar/view-mode-toggle.tsx
@@ -19,12 +19,12 @@ For commercial licensing, please contact support@quantumnous.com
import { Grid2X2, Table2 } from 'lucide-react'
import { useTranslation } from 'react-i18next'
-import { Tabs, TabsList, TabsTrigger } from '@/components/design-system/tabs'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip'
+import { cn } from '@/lib/utils'
import {
DATA_TABLE_VIEW_MODES,
@@ -37,6 +37,12 @@ export type DataTableViewModeToggleProps = {
className?: string
}
+type Segment = {
+ value: DataTableViewMode
+ icon: React.ComponentType<{ className?: string }>
+ tooltip: string
+}
+
/**
* Reusable icon segmented control for switching a data table between table and
* card views. Shared, accessible version of the local control used by the
@@ -45,42 +51,56 @@ export type DataTableViewModeToggleProps = {
export function DataTableViewModeToggle(props: DataTableViewModeToggleProps) {
const { t } = useTranslation()
+ const segments: Segment[] = [
+ {
+ value: DATA_TABLE_VIEW_MODES.CARD,
+ icon: Grid2X2,
+ tooltip: t('Card view'),
+ },
+ {
+ value: DATA_TABLE_VIEW_MODES.TABLE,
+ icon: Table2,
+ tooltip: t('Table view'),
+ },
+ ]
+
return (
- props.onChange(value as DataTableViewMode)}
- className={props.className}
+
-
-
-
- }
- >
-
- {t('Table view')}
-
- {t('Table view')}
-
-
-
- }
- >
-
- {t('Card view')}
-
- {t('Card view')}
-
-
-
+ {segments.map((segment) => {
+ const Icon = segment.icon
+ const isActive = segment.value === props.value
+ return (
+
+ props.onChange(segment.value)}
+ aria-pressed={isActive}
+ className={cn(
+ 'inline-flex h-full w-7 items-center justify-center rounded-md text-xs font-medium transition-all',
+ isActive
+ ? 'bg-primary text-primary-foreground shadow-sm'
+ : 'text-muted-foreground hover:text-foreground'
+ )}
+ >
+
+
+ }
+ />
+
+ {segment.tooltip}
+
+
+ )
+ })}
+
)
}
diff --git a/web/default/src/components/data-table/toolbar/view-options.tsx b/web/default/src/components/data-table/toolbar/view-options.tsx
index 2bba58ead8..76d0d57c05 100644
--- a/web/default/src/components/data-table/toolbar/view-options.tsx
+++ b/web/default/src/components/data-table/toolbar/view-options.tsx
@@ -20,7 +20,7 @@ import { type Table } from '@tanstack/react-table'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Button } from '@/components/design-system/button'
+import { Button } from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuCheckboxItem,
diff --git a/web/default/src/components/date-picker.tsx b/web/default/src/components/date-picker.tsx
index d46b388228..12d2d30c93 100644
--- a/web/default/src/components/date-picker.tsx
+++ b/web/default/src/components/date-picker.tsx
@@ -20,7 +20,7 @@ import { Calendar as CalendarIcon } from 'lucide-react'
import { enUS, fr, ja, ru, vi, zhCN } from 'react-day-picker/locale'
import { useTranslation } from 'react-i18next'
-import { Button } from '@/components/design-system/button'
+import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar'
import {
Popover,
diff --git a/web/default/src/components/datetime-picker.tsx b/web/default/src/components/datetime-picker.tsx
index ae3b147874..b9dd3f60bf 100644
--- a/web/default/src/components/datetime-picker.tsx
+++ b/web/default/src/components/datetime-picker.tsx
@@ -21,9 +21,9 @@ import * as React from 'react'
import { enUS, fr, ja, ru, vi, zhCN } from 'react-day-picker/locale'
import { useTranslation } from 'react-i18next'
-import { Button } from '@/components/design-system/button'
-import { Input } from '@/components/design-system/input'
+import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar'
+import { Input } from '@/components/ui/input'
import {
Popover,
PopoverContent,
diff --git a/web/default/src/components/design-system/README.md b/web/default/src/components/design-system/README.md
deleted file mode 100644
index fc8e13d469..0000000000
--- a/web/default/src/components/design-system/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Design-system adapters
-
-This directory is the product-policy boundary above the shadcn source in
-`src/components/ui/`.
-
-## Import rule
-
-- Application and feature code imports policy-bearing controls from
- `@/components/design-system/*`.
-- Files in this directory may import `@/components/ui/*`.
-- Do not make `components/ui` depend on this directory.
-- Do not proxy a shadcn component unless it carries a stable cross-application
- policy. Components without product policy continue to be imported directly
- from `components/ui`.
-
-The lint configuration enforces this rule for the managed controls.
-
-## Responsive sizing
-
-Default controls are 28px below the `sm` breakpoint and 32px at `sm` and above.
-Dense and micro sizes remain fixed:
-
-- `sm` / `icon-sm`: 28px
-- `xs` / `icon-xs`: 24px
-- `xl`: 40px below `sm`, 44px at `sm` and above
-
-Call sites should select a semantic size and use `className` only for layout.
-They must not pin a managed control to a fixed `h-*` or `size-*` value.
-
-## Updating shadcn
-
-Keep `components.json` pointed at `@/components/ui`. Preview upstream changes
-before merging:
-
-```sh
-bunx --bun shadcn@latest add --dry-run
-bunx --bun shadcn@latest add --diff
-```
-
-Merge the upstream source into `components/ui`, then verify that the adapter's
-prop forwarding and class overrides still match the upstream API. Never use
-`--overwrite` without explicit approval.
diff --git a/web/default/src/components/design-system/alert-dialog.tsx b/web/default/src/components/design-system/alert-dialog.tsx
deleted file mode 100644
index 3f8ffa332b..0000000000
--- a/web/default/src/components/design-system/alert-dialog.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import { AlertDialog as AlertDialogPrimitive } from '@base-ui/react/alert-dialog'
-import * as React from 'react'
-
-import { Button } from '@/components/design-system/button'
-import {
- AlertDialog,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogMedia,
- AlertDialogOverlay,
- AlertDialogPortal,
- AlertDialogTitle,
- AlertDialogTrigger,
-} from '@/components/ui/alert-dialog'
-import { cn } from '@/lib/utils'
-
-function AlertDialogAction({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function AlertDialogCancel({
- className,
- variant = 'outline',
- size = 'default',
- ...props
-}: AlertDialogPrimitive.Close.Props &
- Pick, 'variant' | 'size'>) {
- return (
- }
- {...props}
- />
- )
-}
-
-export {
- AlertDialog,
- AlertDialogAction,
- AlertDialogCancel,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogMedia,
- AlertDialogOverlay,
- AlertDialogPortal,
- AlertDialogTitle,
- AlertDialogTrigger,
-}
diff --git a/web/default/src/components/design-system/button.tsx b/web/default/src/components/design-system/button.tsx
deleted file mode 100644
index 3d3d800749..0000000000
--- a/web/default/src/components/design-system/button.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import { cva, type VariantProps } from 'class-variance-authority'
-import * as React from 'react'
-
-import { Button as ShadcnButton } from '@/components/ui/button'
-import { cn } from '@/lib/utils'
-
-const responsiveButtonSizeVariants = cva('', {
- variants: {
- size: {
- default:
- "h-7 gap-1 px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5 sm:h-8 sm:gap-1.5 sm:text-sm sm:has-data-[icon=inline-end]:pr-2 sm:has-data-[icon=inline-start]:pl-2 sm:[&_svg:not([class*='size-'])]:size-4",
- xs: null,
- sm: null,
- lg: 'h-8 sm:h-9',
- xl: 'h-10 gap-2 px-4 sm:h-11 sm:px-5',
- icon: 'size-7 sm:size-8',
- 'icon-xs': null,
- 'icon-sm': null,
- 'icon-lg': 'size-8 sm:size-9',
- },
- },
- defaultVariants: {
- size: 'default',
- },
-})
-
-type ButtonSize = NonNullable<
- VariantProps['size']
->
-
-type ButtonProps = Omit, 'size'> & {
- size?: ButtonSize
-}
-
-function Button({ className, size = 'default', ...props }: ButtonProps) {
- return (
-
- )
-}
-
-export { Button }
-export type { ButtonProps, ButtonSize }
diff --git a/web/default/src/components/design-system/combobox-input.tsx b/web/default/src/components/design-system/combobox-input.tsx
deleted file mode 100644
index 014188042f..0000000000
--- a/web/default/src/components/design-system/combobox-input.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- ComboboxInput as ShadcnComboboxInput,
- type ComboboxInputOption,
-} from '@/components/ui/combobox-input'
-import { cn } from '@/lib/utils'
-
-function ComboboxInput({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export { ComboboxInput }
-export type { ComboboxInputOption }
diff --git a/web/default/src/components/design-system/combobox.tsx b/web/default/src/components/design-system/combobox.tsx
deleted file mode 100644
index 6dcef1c14d..0000000000
--- a/web/default/src/components/design-system/combobox.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import { Combobox as ComboboxPrimitive } from '@base-ui/react'
-import * as React from 'react'
-
-import {
- ComboboxInput as LegacyComboboxInput,
- type ComboboxInputOption,
-} from '@/components/design-system/combobox-input'
-import {
- ComboboxChip,
- ComboboxChips as ShadcnComboboxChips,
- ComboboxChipsInput,
- ComboboxCollection,
- ComboboxContent as ShadcnComboboxContent,
- ComboboxEmpty,
- ComboboxGroup,
- ComboboxInput as ShadcnComboboxInput,
- ComboboxItem,
- ComboboxLabel,
- ComboboxList,
- ComboboxSeparator,
- ComboboxTrigger,
- ComboboxValue,
- useComboboxAnchor,
-} from '@/components/ui/combobox'
-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(
- props: ComboboxPrimitive.Root.Props
-): React.ReactElement
-function Combobox(
- props:
- | ComboboxPrimitive.Root.Props
- | LegacyComboboxProps
-) {
- if ('options' in props) {
- return (
- props.onValueChange?.(value)}
- placeholder={props.searchPlaceholder ?? props.placeholder}
- emptyText={props.emptyText}
- className={props.className}
- allowCustomValue={props.allowCustomValue}
- openOnFocus={props.openOnFocus}
- />
- )
- }
-
- return
-}
-
-function ComboboxInput({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function ComboboxContent({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function ComboboxChips({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export {
- Combobox,
- ComboboxChip,
- ComboboxChips,
- ComboboxChipsInput,
- ComboboxCollection,
- ComboboxContent,
- ComboboxEmpty,
- ComboboxGroup,
- ComboboxInput,
- ComboboxItem,
- ComboboxLabel,
- ComboboxList,
- ComboboxSeparator,
- ComboboxTrigger,
- ComboboxValue,
- useComboboxAnchor,
-}
diff --git a/web/default/src/components/design-system/command.tsx b/web/default/src/components/design-system/command.tsx
deleted file mode 100644
index 32222dfcfc..0000000000
--- a/web/default/src/components/design-system/command.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import { SearchIcon } from '@hugeicons/core-free-icons'
-import { HugeiconsIcon } from '@hugeicons/react'
-import { Command as CommandPrimitive } from 'cmdk'
-import * as React from 'react'
-
-import {
- InputGroup,
- InputGroupAddon,
-} from '@/components/design-system/input-group'
-import {
- Command,
- CommandDialog,
- CommandEmpty,
- CommandGroup,
- CommandItem,
- CommandList,
- CommandSeparator,
- CommandShortcut,
-} from '@/components/ui/command'
-import { cn } from '@/lib/utils'
-
-function CommandInput({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
-
-
-
-
-
-
-
- )
-}
-
-export {
- Command,
- CommandDialog,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList,
- CommandSeparator,
- CommandShortcut,
-}
diff --git a/web/default/src/components/design-system/dialog.tsx b/web/default/src/components/design-system/dialog.tsx
deleted file mode 100644
index d5207f66ca..0000000000
--- a/web/default/src/components/design-system/dialog.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import { Dialog as DialogPrimitive } from '@base-ui/react/dialog'
-import * as React from 'react'
-
-import { Button } from '@/components/design-system/button'
-import {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogHeader,
- DialogOverlay,
- DialogPortal,
- DialogTitle,
- DialogTrigger,
-} from '@/components/ui/dialog'
-import { cn } from '@/lib/utils'
-
-function DialogFooter({
- className,
- showCloseButton = false,
- children,
- ...props
-}: React.ComponentProps<'div'> & {
- showCloseButton?: boolean
-}) {
- return (
-
- {children}
- {showCloseButton && (
- }>
- Close
-
- )}
-
- )
-}
-
-export {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogOverlay,
- DialogPortal,
- DialogTitle,
- DialogTrigger,
-}
diff --git a/web/default/src/components/design-system/input-group.tsx b/web/default/src/components/design-system/input-group.tsx
deleted file mode 100644
index 8d2ed9da2a..0000000000
--- a/web/default/src/components/design-system/input-group.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- InputGroup as ShadcnInputGroup,
- InputGroupAddon,
- InputGroupButton as ShadcnInputGroupButton,
- InputGroupInput as ShadcnInputGroupInput,
- InputGroupText,
- InputGroupTextarea,
-} from '@/components/ui/input-group'
-import { cn } from '@/lib/utils'
-
-function InputGroup({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function InputGroupButton({
- className,
- size = 'xs',
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function InputGroupInput({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export {
- InputGroup,
- InputGroupAddon,
- InputGroupButton,
- InputGroupInput,
- InputGroupText,
- InputGroupTextarea,
-}
diff --git a/web/default/src/components/design-system/input.tsx b/web/default/src/components/design-system/input.tsx
deleted file mode 100644
index e2b15297d9..0000000000
--- a/web/default/src/components/design-system/input.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import { Input as ShadcnInput } from '@/components/ui/input'
-import { cn } from '@/lib/utils'
-
-function Input({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export { Input }
diff --git a/web/default/src/components/design-system/pagination.tsx b/web/default/src/components/design-system/pagination.tsx
deleted file mode 100644
index b0120267a1..0000000000
--- a/web/default/src/components/design-system/pagination.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- Pagination as ShadcnPagination,
- PaginationContent,
- PaginationEllipsis,
- PaginationItem,
- PaginationLink,
- PaginationNext,
- PaginationPrevious,
-} from '@/components/ui/pagination'
-import { cn } from '@/lib/utils'
-
-function Pagination({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export {
- Pagination,
- PaginationContent,
- PaginationEllipsis,
- PaginationItem,
- PaginationLink,
- PaginationNext,
- PaginationPrevious,
-}
diff --git a/web/default/src/components/design-system/select.tsx b/web/default/src/components/design-system/select.tsx
deleted file mode 100644
index d76265513c..0000000000
--- a/web/default/src/components/design-system/select.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectScrollDownButton,
- SelectScrollUpButton,
- SelectSeparator,
- SelectTrigger as ShadcnSelectTrigger,
- SelectValue,
-} from '@/components/ui/select'
-import { cn } from '@/lib/utils'
-
-function SelectTrigger({
- className,
- size = 'default',
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectScrollDownButton,
- SelectScrollUpButton,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
-}
diff --git a/web/default/src/components/design-system/sidebar.tsx b/web/default/src/components/design-system/sidebar.tsx
deleted file mode 100644
index b5fabadbf8..0000000000
--- a/web/default/src/components/design-system/sidebar.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- Sidebar,
- SidebarContent,
- SidebarFooter,
- SidebarGroup,
- SidebarGroupAction,
- SidebarGroupContent,
- SidebarGroupLabel,
- SidebarHeader,
- SidebarInput as ShadcnSidebarInput,
- SidebarInset,
- SidebarMenu,
- SidebarMenuAction,
- SidebarMenuBadge,
- SidebarMenuButton,
- SidebarMenuItem,
- SidebarMenuSkeleton,
- SidebarMenuSub,
- SidebarMenuSubButton,
- SidebarMenuSubItem,
- SidebarProvider,
- SidebarRail,
- SidebarSeparator,
- SidebarTrigger as ShadcnSidebarTrigger,
- useSidebar,
-} from '@/components/ui/sidebar'
-import { cn } from '@/lib/utils'
-
-function SidebarTrigger({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function SidebarInput({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export {
- Sidebar,
- SidebarContent,
- SidebarFooter,
- SidebarGroup,
- SidebarGroupAction,
- SidebarGroupContent,
- SidebarGroupLabel,
- SidebarHeader,
- SidebarInput,
- SidebarInset,
- SidebarMenu,
- SidebarMenuAction,
- SidebarMenuBadge,
- SidebarMenuButton,
- SidebarMenuItem,
- SidebarMenuSkeleton,
- SidebarMenuSub,
- SidebarMenuSubButton,
- SidebarMenuSubItem,
- SidebarProvider,
- SidebarRail,
- SidebarSeparator,
- SidebarTrigger,
- useSidebar,
-}
diff --git a/web/default/src/components/design-system/table.tsx b/web/default/src/components/design-system/table.tsx
deleted file mode 100644
index 978e468c2f..0000000000
--- a/web/default/src/components/design-system/table.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- Table,
- TableBody,
- TableCaption,
- TableCell,
- TableFooter,
- TableHead as ShadcnTableHead,
- TableHeader,
- TableRow,
-} from '@/components/ui/table'
-import { cn } from '@/lib/utils'
-
-function TableHead({
- className,
- ...props
-}: React.ComponentProps) {
- return
-}
-
-export {
- Table,
- TableBody,
- TableCaption,
- TableCell,
- TableFooter,
- TableHead,
- TableHeader,
- TableRow,
-}
diff --git a/web/default/src/components/design-system/tabs.tsx b/web/default/src/components/design-system/tabs.tsx
deleted file mode 100644
index 66b463b4f4..0000000000
--- a/web/default/src/components/design-system/tabs.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- Tabs,
- TabsContent,
- TabsList as ShadcnTabsList,
- TabsTrigger as ShadcnTabsTrigger,
-} from '@/components/ui/tabs'
-import { cn } from '@/lib/utils'
-
-function TabsList({
- className,
- variant = 'default',
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-function TabsTrigger({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export { Tabs, TabsContent, TabsList, TabsTrigger }
diff --git a/web/default/src/components/design-system/toggle-group.tsx b/web/default/src/components/design-system/toggle-group.tsx
deleted file mode 100644
index 3f2f05e126..0000000000
--- a/web/default/src/components/design-system/toggle-group.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import * as React from 'react'
-
-import {
- ToggleGroup as ShadcnToggleGroup,
- ToggleGroupItem,
-} from '@/components/ui/toggle-group'
-import { cn } from '@/lib/utils'
-
-function ToggleGroup({
- className,
- size = 'default',
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export { ToggleGroup, ToggleGroupItem }
diff --git a/web/default/src/components/design-system/toggle.tsx b/web/default/src/components/design-system/toggle.tsx
deleted file mode 100644
index c7ec966afc..0000000000
--- a/web/default/src/components/design-system/toggle.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Copyright (C) 2023-2026 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-import { cva, type VariantProps } from 'class-variance-authority'
-import * as React from 'react'
-
-import { Toggle as ShadcnToggle } from '@/components/ui/toggle'
-import { cn } from '@/lib/utils'
-
-const responsiveToggleSizeVariants = cva('', {
- variants: {
- size: {
- default:
- "h-7 min-w-7 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5 sm:h-8 sm:min-w-8 sm:text-sm sm:has-data-[icon=inline-end]:pr-2 sm:has-data-[icon=inline-start]:pl-2 sm:[&_svg:not([class*='size-'])]:size-4",
- sm: null,
- lg: 'h-8 min-w-8 sm:h-9 sm:min-w-9',
- },
- },
- defaultVariants: {
- size: 'default',
- },
-})
-
-type ToggleSize = NonNullable<
- VariantProps['size']
->
-
-type ToggleProps = Omit, 'size'> & {
- size?: ToggleSize
-}
-
-function Toggle({ className, size = 'default', ...props }: ToggleProps) {
- return (
-
- )
-}
-
-export { Toggle }
-export type { ToggleProps, ToggleSize }
diff --git a/web/default/src/components/dialog.tsx b/web/default/src/components/dialog.tsx
index e32021ad3d..d31eddd7e0 100644
--- a/web/default/src/components/dialog.tsx
+++ b/web/default/src/components/dialog.tsx
@@ -26,7 +26,7 @@ import {
DialogHeader,
DialogTitle,
DialogTrigger,
-} from '@/components/design-system/dialog'
+} from '@/components/ui/dialog'
import { cn } from '@/lib/utils'
type DialogProps = React.ComponentProps & {
@@ -71,8 +71,6 @@ export function Dialog({
{trigger ? : null}
cn(
- // Width: pass `sm:max-w-*` (or `sm:max-w-none`) in className. SheetContent
- // defaults to 75% width on mobile and `sm:max-w-sm` for left/right.
- // Match its side variants so product drawers occupy the full mobile viewport.
- 'bg-background text-foreground flex h-dvh w-full flex-col gap-0 overflow-hidden p-0 shadow-none data-[side=left]:w-full data-[side=right]:w-full',
+ 'bg-background text-foreground flex h-dvh w-full flex-col gap-0 overflow-hidden p-0 shadow-none',
className
)
export const sideDrawerHeaderClassName = (className?: string) =>
cn(
- // pr-12 reserves space for SheetContent's absolute close button
- 'border-border/70 bg-background/95 border-b px-4 py-3 pr-12 text-start backdrop-blur supports-[backdrop-filter]:bg-background/80 sm:px-6 sm:py-4 sm:pr-14',
+ 'border-border/70 bg-background/95 border-b px-4 py-3 text-start backdrop-blur supports-[backdrop-filter]:bg-background/80 sm:px-6 sm:py-4',
className
)
diff --git a/web/default/src/components/error-state.tsx b/web/default/src/components/error-state.tsx
index 80a65af2e4..adfc2f2db3 100644
--- a/web/default/src/components/error-state.tsx
+++ b/web/default/src/components/error-state.tsx
@@ -20,8 +20,8 @@ import { AlertTriangle, type LucideIcon } from 'lucide-react'
import type { ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
-import { Button } from '@/components/design-system/button'
import { FadeIn } from '@/components/page-transition'
+import { Button } from '@/components/ui/button'
import {
Empty,
EmptyContent,
@@ -61,7 +61,7 @@ export function ErrorState(props: ErrorStateProps) {
{props.onRetry != null && (
-