refactor(icons): migrate workspace to Icones

This commit is contained in:
Maofeng
2026-09-20 15:52:22 +08:00
parent 1fc56b6982
commit ea00a71112
95 changed files with 1409 additions and 725 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
import { ChevronDownIcon, ChevronUpIcon } from "@workspace/ui/components/icon"
function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
return (
+4 -1
View File
@@ -3,7 +3,10 @@ import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
import {
ChevronRightIcon,
MoreHorizontalIcon,
} from "@workspace/ui/components/icon"
import { LocalizedText, uiMessages, useMessage } from "./i18n"
function Breadcrumb({
+184 -159
View File
@@ -14,7 +14,68 @@ import {
ChevronLeftIcon,
ChevronRightIcon,
ChevronDownIcon,
} from "lucide-react"
} from "@workspace/ui/components/icon"
type CalendarComponents = NonNullable<
React.ComponentProps<typeof DayPicker>["components"]
>
const CalendarLocaleContext = React.createContext<string | undefined>(undefined)
const CalendarRoot: NonNullable<CalendarComponents["Root"]> = ({
className: rootClassName,
rootRef,
...rootProps
}) => (
<div
data-slot="calendar"
ref={rootRef}
className={cn(rootClassName)}
{...rootProps}
/>
)
const CalendarChevron: NonNullable<CalendarComponents["Chevron"]> = ({
className: chevronClassName,
orientation,
...chevronProps
}) => {
if (orientation === "left") {
return (
<ChevronLeftIcon
className={cn("size-4 rtl:rotate-180", chevronClassName)}
{...chevronProps}
/>
)
}
if (orientation === "right") {
return (
<ChevronRightIcon
className={cn("size-4 rtl:rotate-180", chevronClassName)}
{...chevronProps}
/>
)
}
return (
<ChevronDownIcon
className={cn("size-4", chevronClassName)}
{...chevronProps}
/>
)
}
const CalendarWeekNumber: NonNullable<CalendarComponents["WeekNumber"]> = ({
children,
...weekNumberProps
}) => (
<td {...weekNumberProps}>
<div className="flex size-(--cell-size) items-center justify-center text-center">
{children}
</div>
</td>
)
function Calendar({
className,
@@ -37,162 +98,126 @@ function Calendar({
const localeCode = locale?.code ?? contextLocale
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn(
"group/calendar bg-background p-3 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(8)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent",
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
className
)}
captionLayout={captionLayout}
locale={locale}
lang={lang ?? localeCode}
formatters={{
formatMonthDropdown: (date) =>
date.toLocaleString(localeCode, { month: "short" }),
...formatters,
}}
classNames={{
root: cn("w-fit", defaultClassNames.root),
months: cn(
"relative flex flex-col gap-4 md:flex-row",
defaultClassNames.months
),
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
nav: cn(
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
defaultClassNames.nav
),
button_previous: cn(
buttonVariants({ variant: buttonVariant }),
"size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
defaultClassNames.button_previous
),
button_next: cn(
buttonVariants({ variant: buttonVariant }),
"size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
defaultClassNames.button_next
),
month_caption: cn(
"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
defaultClassNames.month_caption
),
dropdowns: cn(
"flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
defaultClassNames.dropdowns
),
dropdown_root: cn(
"relative rounded-(--cell-radius)",
defaultClassNames.dropdown_root
),
dropdown: cn(
"absolute inset-0 bg-popover opacity-0",
defaultClassNames.dropdown
),
caption_label: cn(
"font-medium select-none",
captionLayout === "label"
? "text-sm"
: "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
defaultClassNames.caption_label
),
month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
weekdays: cn("flex", defaultClassNames.weekdays),
weekday: cn(
"flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none",
defaultClassNames.weekday
),
week: cn("mt-2 flex w-full", defaultClassNames.week),
week_number_header: cn(
"w-(--cell-size) select-none",
defaultClassNames.week_number_header
),
week_number: cn(
"text-[0.8rem] text-muted-foreground select-none",
defaultClassNames.week_number
),
day: cn(
"group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-e-(--cell-radius)",
props.showWeekNumber
? "[&:nth-child(2)[data-selected=true]_button]:rounded-s-(--cell-radius)"
: "[&:first-child[data-selected=true]_button]:rounded-s-(--cell-radius)",
defaultClassNames.day
),
range_start: cn(
"relative isolate z-0 rounded-s-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:end-0 after:w-4 after:bg-muted",
defaultClassNames.range_start
),
range_middle: cn("rounded-none", defaultClassNames.range_middle),
range_end: cn(
"relative isolate z-0 rounded-e-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:start-0 after:w-4 after:bg-muted",
defaultClassNames.range_end
),
today: cn(
"rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none",
defaultClassNames.today
),
outside: cn(
"text-muted-foreground aria-selected:text-muted-foreground",
defaultClassNames.outside
),
disabled: cn(
"text-muted-foreground opacity-50",
defaultClassNames.disabled
),
hidden: cn("invisible", defaultClassNames.hidden),
...classNames,
}}
components={{
Root: ({ className, rootRef, ...props }) => {
return (
<div
data-slot="calendar"
ref={rootRef}
className={cn(className)}
{...props}
/>
)
},
Chevron: ({ className, orientation, ...props }) => {
if (orientation === "left") {
return (
<ChevronLeftIcon
className={cn("size-4 rtl:rotate-180", className)}
{...props}
/>
)
}
if (orientation === "right") {
return (
<ChevronRightIcon
className={cn("size-4 rtl:rotate-180", className)}
{...props}
/>
)
}
return (
<ChevronDownIcon className={cn("size-4", className)} {...props} />
)
},
DayButton: ({ ...props }) => (
<CalendarDayButton locale={localeCode} {...props} />
),
WeekNumber: ({ children, ...props }) => {
return (
<td {...props}>
<div className="flex size-(--cell-size) items-center justify-center text-center">
{children}
</div>
</td>
)
},
...components,
}}
{...props}
/>
<CalendarLocaleContext.Provider value={localeCode}>
<DayPicker
showOutsideDays={showOutsideDays}
className={cn(
"group/calendar bg-background p-3 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(8)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent",
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
className
)}
captionLayout={captionLayout}
locale={locale}
lang={lang ?? localeCode}
formatters={{
formatMonthDropdown: (date) =>
date.toLocaleString(localeCode, { month: "short" }),
...formatters,
}}
classNames={{
root: cn("w-fit", defaultClassNames.root),
months: cn(
"relative flex flex-col gap-4 md:flex-row",
defaultClassNames.months
),
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
nav: cn(
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
defaultClassNames.nav
),
button_previous: cn(
buttonVariants({ variant: buttonVariant }),
"size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
defaultClassNames.button_previous
),
button_next: cn(
buttonVariants({ variant: buttonVariant }),
"size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
defaultClassNames.button_next
),
month_caption: cn(
"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
defaultClassNames.month_caption
),
dropdowns: cn(
"flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
defaultClassNames.dropdowns
),
dropdown_root: cn(
"relative rounded-(--cell-radius)",
defaultClassNames.dropdown_root
),
dropdown: cn(
"absolute inset-0 bg-popover opacity-0",
defaultClassNames.dropdown
),
caption_label: cn(
"font-medium select-none",
captionLayout === "label"
? "text-sm"
: "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
defaultClassNames.caption_label
),
month_grid: cn(
"w-full border-collapse",
defaultClassNames.month_grid
),
weekdays: cn("flex", defaultClassNames.weekdays),
weekday: cn(
"flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none",
defaultClassNames.weekday
),
week: cn("mt-2 flex w-full", defaultClassNames.week),
week_number_header: cn(
"w-(--cell-size) select-none",
defaultClassNames.week_number_header
),
week_number: cn(
"text-[0.8rem] text-muted-foreground select-none",
defaultClassNames.week_number
),
day: cn(
"group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-e-(--cell-radius)",
props.showWeekNumber
? "[&:nth-child(2)[data-selected=true]_button]:rounded-s-(--cell-radius)"
: "[&:first-child[data-selected=true]_button]:rounded-s-(--cell-radius)",
defaultClassNames.day
),
range_start: cn(
"relative isolate z-0 rounded-s-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:end-0 after:w-4 after:bg-muted",
defaultClassNames.range_start
),
range_middle: cn("rounded-none", defaultClassNames.range_middle),
range_end: cn(
"relative isolate z-0 rounded-e-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:start-0 after:w-4 after:bg-muted",
defaultClassNames.range_end
),
today: cn(
"rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none",
defaultClassNames.today
),
outside: cn(
"text-muted-foreground aria-selected:text-muted-foreground",
defaultClassNames.outside
),
disabled: cn(
"text-muted-foreground opacity-50",
defaultClassNames.disabled
),
hidden: cn("invisible", defaultClassNames.hidden),
...classNames,
}}
components={{
Root: CalendarRoot,
Chevron: CalendarChevron,
DayButton: CalendarDayButton,
WeekNumber: CalendarWeekNumber,
...components,
}}
{...props}
/>
</CalendarLocaleContext.Provider>
)
}
@@ -200,10 +225,10 @@ function CalendarDayButton({
className,
day,
modifiers,
locale,
...props
}: React.ComponentProps<typeof DayButton> & { locale?: string }) {
}: React.ComponentProps<typeof DayButton>) {
const defaultClassNames = getDefaultClassNames()
const locale = React.useContext(CalendarLocaleContext)
const ref = React.useRef<HTMLButtonElement>(null)
React.useEffect(() => {
+37 -18
View File
@@ -5,7 +5,10 @@ import useEmblaCarousel, {
import { cn } from "@workspace/ui/lib/utils"
import { Button } from "@workspace/ui/components/button"
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
import {
ChevronLeftIcon,
ChevronRightIcon,
} from "@workspace/ui/components/icon"
import { LocalizedText, uiMessages } from "./i18n"
type CarouselApi = UseEmblaCarouselType[1]
@@ -60,10 +63,10 @@ function Carousel({
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
const [canScrollNext, setCanScrollNext] = React.useState(false)
const onSelect = React.useCallback((api: CarouselApi) => {
if (!api) return
setCanScrollPrev(api.canScrollPrev())
setCanScrollNext(api.canScrollNext())
const onSelect = React.useCallback((carouselApi: CarouselApi) => {
if (!carouselApi) return
setCanScrollPrev(carouselApi.canScrollPrev())
setCanScrollNext(carouselApi.canScrollNext())
}, [])
const scrollPrev = React.useCallback(() => {
@@ -103,20 +106,36 @@ function Carousel({
}
}, [api, onSelect])
const contextValue = React.useMemo<CarouselContextProps>(
() => ({
carouselRef,
api,
opts,
orientation:
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
scrollPrev,
scrollNext,
canScrollPrev,
canScrollNext,
plugins,
setApi,
}),
[
api,
canScrollNext,
canScrollPrev,
carouselRef,
opts,
orientation,
plugins,
scrollNext,
scrollPrev,
setApi,
]
)
return (
<CarouselContext.Provider
value={{
carouselRef,
api: api,
opts,
orientation:
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
scrollPrev,
scrollNext,
canScrollPrev,
canScrollNext,
}}
>
<CarouselContext.Provider value={contextValue}>
<div
onKeyDownCapture={handleKeyDown}
className={cn("relative", className)}
+1 -1
View File
@@ -3,7 +3,7 @@
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
import { cn } from "@workspace/ui/lib/utils"
import { CheckIcon } from "lucide-react"
import { CheckIcon } from "@workspace/ui/components/icon"
function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
return (
+5 -1
View File
@@ -11,7 +11,11 @@ import {
InputGroupButton,
InputGroupInput,
} from "@workspace/ui/components/input-group"
import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react"
import {
ChevronDownIcon,
XIcon,
CheckIcon,
} from "@workspace/ui/components/icon"
const Combobox = ComboboxPrimitive.Root
+1 -1
View File
@@ -13,7 +13,7 @@ import {
InputGroup,
InputGroupAddon,
} from "@workspace/ui/components/input-group"
import { SearchIcon, CheckIcon } from "lucide-react"
import { SearchIcon, CheckIcon } from "@workspace/ui/components/icon"
function Command({
className,
+1 -1
View File
@@ -4,7 +4,7 @@ import * as React from "react"
import { ContextMenu as ContextMenuPrimitive } from "@base-ui/react/context-menu"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronRightIcon, CheckIcon } from "lucide-react"
import { ChevronRightIcon, CheckIcon } from "@workspace/ui/components/icon"
function ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />
+1 -1
View File
@@ -5,7 +5,7 @@ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
import { cn } from "@workspace/ui/lib/utils"
import { Button } from "@workspace/ui/components/button"
import { XIcon } from "lucide-react"
import { XIcon } from "@workspace/ui/components/icon"
import { LocalizedText, uiMessages } from "./i18n"
type DialogHandle<Payload> = DialogPrimitive.Handle<Payload>
+1 -1
View File
@@ -9,7 +9,7 @@ import {
getAnchoredSurfaceSideOffset,
} from "@workspace/ui/components/anchored-surface"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronRightIcon, CheckIcon } from "lucide-react"
import { ChevronRightIcon, CheckIcon } from "@workspace/ui/components/icon"
import { useRippleRef } from "../hooks/use-ripple"
function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
+229
View File
@@ -0,0 +1,229 @@
import * as React from "react"
import { Icon, type IconName, type IconProps } from "@icones/react"
export type IconComponentProps = Omit<
Extract<IconProps, { name: string }>,
"name"
>
export type IconComponent = React.ComponentType<IconComponentProps>
function createIcon(name: IconName<"lucide">): IconComponent {
const Component = (props: IconComponentProps) => (
<Icon name={name} size={24} strokeWidth={2} {...props} />
)
Component.displayName = `Icon(${name})`
return Component
}
export const ALargeSmall = createIcon("lucide:a-large-small")
export const AlignCenter = createIcon("lucide:text-align-center")
export const AlignCenterIcon = AlignCenter
export const AlignJustify = createIcon("lucide:text-align-justify")
export const AlignLeft = createIcon("lucide:text-align-start")
export const AlignLeftIcon = AlignLeft
export const AlignRight = createIcon("lucide:text-align-end")
export const AlignRightIcon = AlignRight
export const AppWindowIcon = createIcon("lucide:app-window")
export const ArrowDownIcon = createIcon("lucide:arrow-down")
export const ArrowLeftIcon = createIcon("lucide:arrow-left")
export const Baseline = createIcon("lucide:baseline")
export const Bold = createIcon("lucide:bold")
export const CalendarDays = createIcon("lucide:calendar-days")
export const CaseLower = createIcon("lucide:case-lower")
export const CaseSensitive = createIcon("lucide:case-sensitive")
export const CaseUpper = createIcon("lucide:case-upper")
export const Check = createIcon("lucide:check")
export const CheckIcon = Check
export const CheckCheckIcon = createIcon("lucide:check-check")
export const ChevronDown = createIcon("lucide:chevron-down")
export const ChevronDownIcon = ChevronDown
export const ChevronLeftIcon = createIcon("lucide:chevron-left")
export const ChevronRightIcon = createIcon("lucide:chevron-right")
export const ChevronUpIcon = createIcon("lucide:chevron-up")
export const CircleAlertIcon = createIcon("lucide:circle-alert")
export const CircleCheckIcon = createIcon("lucide:circle-check")
export const ClipboardCopyIcon = createIcon("lucide:clipboard-copy")
export const CloudIcon = createIcon("lucide:cloud")
export const CloudUploadIcon = createIcon("lucide:cloud-upload")
export const CopyIcon = createIcon("lucide:copy")
export const CornerDownLeftIcon = createIcon("lucide:corner-down-left")
export const Eraser = createIcon("lucide:eraser")
export const ExternalLinkIcon = createIcon("lucide:external-link")
export const EyeIcon = createIcon("lucide:eye")
export const EyeOffIcon = createIcon("lucide:eye-off")
export const FileCode2Icon = createIcon("lucide:file-code-corner")
export const FileTextIcon = createIcon("lucide:file-text")
export const FilmIcon = createIcon("lucide:film")
export const FolderIcon = createIcon("lucide:folder")
export const FolderInputIcon = createIcon("lucide:folder-input")
export const FolderOpenIcon = createIcon("lucide:folder-open")
export const FolderPlusIcon = createIcon("lucide:folder-plus")
export const GlobeIcon = createIcon("lucide:globe")
export const GripVertical = createIcon("lucide:grip-vertical")
export const Heading1 = createIcon("lucide:heading-1")
export const Heading2 = createIcon("lucide:heading-2")
export const Heading3 = createIcon("lucide:heading-3")
export const HeartIcon = createIcon("lucide:heart")
export const HistoryIcon = createIcon("lucide:rotate-ccw-clock")
export const ImageIcon = createIcon("lucide:image")
export const ImagePlusIcon = createIcon("lucide:image-plus")
export const ImagesIcon = createIcon("lucide:images")
export const IndentDecrease = createIcon("lucide:list-indent-decrease")
export const IndentIncrease = createIcon("lucide:list-indent-increase")
export const InfoIcon = createIcon("lucide:info")
export const Italic = createIcon("lucide:italic")
export const LanguagesIcon = createIcon("lucide:languages")
export const LibraryIcon = createIcon("lucide:library")
export const Link = createIcon("lucide:link")
export const LinkIcon = Link
export const List = createIcon("lucide:list")
export const ListChecks = createIcon("lucide:list-checks")
export const ListOrdered = createIcon("lucide:list-ordered")
export const LoaderCircleIcon = createIcon("lucide:loader-circle")
export const Loader2Icon = LoaderCircleIcon
export const Maximize2Icon = createIcon("lucide:maximize-2")
export const MessageCircleIcon = createIcon("lucide:message-circle")
export const Minimize2Icon = createIcon("lucide:minimize-2")
export const Minus = createIcon("lucide:minus")
export const MinusIcon = Minus
export const MonitorIcon = createIcon("lucide:monitor")
export const MoonIcon = createIcon("lucide:moon")
export const MoreHorizontalIcon = createIcon("lucide:ellipsis")
export const OctagonXIcon = createIcon("lucide:octagon-x")
export const PackageIcon = createIcon("lucide:package")
export const PanelLeftIcon = createIcon("lucide:panel-left")
export const PaperclipIcon = createIcon("lucide:paperclip")
export const Pencil = createIcon("lucide:pencil")
export const PencilIcon = Pencil
export const Pilcrow = createIcon("lucide:pilcrow")
export const Pipette = createIcon("lucide:pipette")
export const Plus = createIcon("lucide:plus")
export const PlusIcon = Plus
export const Quote = createIcon("lucide:quote")
export const Redo2 = createIcon("lucide:redo-2")
export const RotateCcwIcon = createIcon("lucide:rotate-ccw")
export const SaveIcon = createIcon("lucide:save")
export const SearchIcon = createIcon("lucide:search")
export const SendHorizontalIcon = createIcon("lucide:send-horizontal")
export const SettingsIcon = createIcon("lucide:settings")
export const SmileIcon = createIcon("lucide:face-slightly-smiling")
export const Strikethrough = createIcon("lucide:strikethrough")
export const Subscript = createIcon("lucide:subscript")
export const SunIcon = createIcon("lucide:sun")
export const Superscript = createIcon("lucide:superscript")
export const TelescopeIcon = createIcon("lucide:telescope")
export const TerminalIcon = createIcon("lucide:terminal")
export const Trash2 = createIcon("lucide:trash")
export const Trash2Icon = Trash2
export const TriangleAlertIcon = createIcon("lucide:triangle-alert")
export const Underline = createIcon("lucide:underline")
export const Undo2 = createIcon("lucide:undo-2")
export const UnlinkIcon = createIcon("lucide:unlink")
export const UploadIcon = createIcon("lucide:upload")
export const VideoIcon = createIcon("lucide:video")
export const XIcon = createIcon("lucide:x")
// Literal references let @icones/vite emit assets for compatibility components.
export function IconAssetCatalog() {
return (
<>
<Icon name="lucide:a-large-small" />
<Icon name="lucide:text-align-center" />
<Icon name="lucide:text-align-justify" />
<Icon name="lucide:text-align-start" />
<Icon name="lucide:text-align-end" />
<Icon name="lucide:app-window" />
<Icon name="lucide:arrow-down" />
<Icon name="lucide:arrow-left" />
<Icon name="lucide:baseline" />
<Icon name="lucide:bold" />
<Icon name="lucide:calendar-days" />
<Icon name="lucide:case-lower" />
<Icon name="lucide:case-sensitive" />
<Icon name="lucide:case-upper" />
<Icon name="lucide:check" />
<Icon name="lucide:check-check" />
<Icon name="lucide:chevron-down" />
<Icon name="lucide:chevron-left" />
<Icon name="lucide:chevron-right" />
<Icon name="lucide:chevron-up" />
<Icon name="lucide:circle-alert" />
<Icon name="lucide:circle-check" />
<Icon name="lucide:clipboard-copy" />
<Icon name="lucide:cloud" />
<Icon name="lucide:cloud-upload" />
<Icon name="lucide:copy" />
<Icon name="lucide:corner-down-left" />
<Icon name="lucide:eraser" />
<Icon name="lucide:external-link" />
<Icon name="lucide:eye" />
<Icon name="lucide:eye-off" />
<Icon name="lucide:file-code-corner" />
<Icon name="lucide:file-text" />
<Icon name="lucide:film" />
<Icon name="lucide:folder" />
<Icon name="lucide:folder-input" />
<Icon name="lucide:folder-open" />
<Icon name="lucide:folder-plus" />
<Icon name="lucide:globe" />
<Icon name="lucide:grip-vertical" />
<Icon name="lucide:heading-1" />
<Icon name="lucide:heading-2" />
<Icon name="lucide:heading-3" />
<Icon name="lucide:heart" />
<Icon name="lucide:rotate-ccw-clock" />
<Icon name="lucide:image" />
<Icon name="lucide:image-plus" />
<Icon name="lucide:images" />
<Icon name="lucide:list-indent-decrease" />
<Icon name="lucide:list-indent-increase" />
<Icon name="lucide:info" />
<Icon name="lucide:italic" />
<Icon name="lucide:languages" />
<Icon name="lucide:library" />
<Icon name="lucide:link" />
<Icon name="lucide:list" />
<Icon name="lucide:list-checks" />
<Icon name="lucide:list-ordered" />
<Icon name="lucide:loader-circle" />
<Icon name="lucide:maximize-2" />
<Icon name="lucide:message-circle" />
<Icon name="lucide:minimize-2" />
<Icon name="lucide:minus" />
<Icon name="lucide:monitor" />
<Icon name="lucide:moon" />
<Icon name="lucide:ellipsis" />
<Icon name="lucide:octagon-x" />
<Icon name="lucide:package" />
<Icon name="lucide:panel-left" />
<Icon name="lucide:paperclip" />
<Icon name="lucide:pencil" />
<Icon name="lucide:pilcrow" />
<Icon name="lucide:pipette" />
<Icon name="lucide:plus" />
<Icon name="lucide:quote" />
<Icon name="lucide:redo-2" />
<Icon name="lucide:rotate-ccw" />
<Icon name="lucide:save" />
<Icon name="lucide:search" />
<Icon name="lucide:send-horizontal" />
<Icon name="lucide:settings" />
<Icon name="lucide:face-slightly-smiling" />
<Icon name="lucide:strikethrough" />
<Icon name="lucide:subscript" />
<Icon name="lucide:sun" />
<Icon name="lucide:superscript" />
<Icon name="lucide:telescope" />
<Icon name="lucide:terminal" />
<Icon name="lucide:trash" />
<Icon name="lucide:triangle-alert" />
<Icon name="lucide:underline" />
<Icon name="lucide:undo-2" />
<Icon name="lucide:unlink" />
<Icon name="lucide:upload" />
<Icon name="lucide:video" />
<Icon name="lucide:x" />
</>
)
}
+1 -1
View File
@@ -2,7 +2,7 @@ import * as React from "react"
import { OTPInput, OTPInputContext } from "input-otp"
import { cn } from "@workspace/ui/lib/utils"
import { MinusIcon } from "lucide-react"
import { MinusIcon } from "@workspace/ui/components/icon"
function InputOTP({
className,
+1 -1
View File
@@ -18,7 +18,7 @@ import {
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@workspace/ui/components/dropdown-menu"
import { CheckIcon } from "lucide-react"
import { CheckIcon } from "@workspace/ui/components/icon"
function Menubar({ className, ...props }: MenubarPrimitive.Props) {
return (
@@ -8,7 +8,7 @@ import {
import { cn } from "@workspace/ui/lib/utils"
import { Button } from "@workspace/ui/components/button"
import { ArrowDownIcon } from "lucide-react"
import { ArrowDownIcon } from "@workspace/ui/components/icon"
function MessageScrollerProvider(
props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>
+1 -1
View File
@@ -1,7 +1,7 @@
import * as React from "react"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronDownIcon } from "lucide-react"
import { ChevronDownIcon } from "@workspace/ui/components/icon"
type NativeSelectProps = Omit<React.ComponentProps<"select">, "size"> & {
size?: "sm" | "default"
@@ -2,7 +2,7 @@ import { NavigationMenu as NavigationMenuPrimitive } from "@base-ui/react/naviga
import { cva } from "class-variance-authority"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronDownIcon } from "lucide-react"
import { ChevronDownIcon } from "@workspace/ui/components/icon"
function NavigationMenu({
align = "start",
+1 -1
View File
@@ -6,7 +6,7 @@ import {
ChevronLeftIcon,
ChevronRightIcon,
MoreHorizontalIcon,
} from "lucide-react"
} from "@workspace/ui/components/icon"
import { LocalizedText, uiMessages, useMessage } from "./i18n"
function Pagination({
+5 -1
View File
@@ -4,7 +4,11 @@ import * as React from "react"
import { Select as SelectPrimitive } from "@base-ui/react/select"
import { cn } from "@workspace/ui/lib/utils"
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
import {
ChevronDownIcon,
CheckIcon,
ChevronUpIcon,
} from "@workspace/ui/components/icon"
const Select = SelectPrimitive.Root
+1 -1
View File
@@ -5,7 +5,7 @@ import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"
import { cn } from "@workspace/ui/lib/utils"
import { Button } from "@workspace/ui/components/button"
import { XIcon } from "lucide-react"
import { XIcon } from "@workspace/ui/components/icon"
import { LocalizedText, uiMessages } from "./i18n"
function createSheetHandle<Payload>(): SheetPrimitive.Handle<Payload> {
+4 -2
View File
@@ -21,7 +21,7 @@ import {
TooltipContent,
TooltipTrigger,
} from "@workspace/ui/components/tooltip"
import { PanelLeftIcon } from "lucide-react"
import { PanelLeftIcon } from "@workspace/ui/components/icon"
import { LocalizedText, uiMessages, useMessage } from "./i18n"
const SIDEBAR_COOKIE_NAME = "sidebar_state"
@@ -89,7 +89,9 @@ function SidebarProvider({
// Helper to toggle the sidebar.
const toggleSidebar = React.useCallback(() => {
return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
return isMobile
? setOpenMobile((currentOpen) => !currentOpen)
: setOpen((currentOpen) => !currentOpen)
}, [isMobile, setOpen, setOpenMobile])
// Adds a keyboard shortcut to toggle the sidebar.
+5 -2
View File
@@ -1,8 +1,11 @@
import { cn } from "@workspace/ui/lib/utils"
import { Loader2Icon } from "lucide-react"
import {
Loader2Icon,
type IconComponentProps,
} from "@workspace/ui/components/icon"
import { uiMessages, useMessage } from "./i18n"
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
function Spinner({ className, ...props }: IconComponentProps) {
const loadingLabel = useMessage(uiMessages.loading)
return (
+5 -3
View File
@@ -10,10 +10,12 @@ import {
TriangleAlertIcon,
OctagonXIcon,
Loader2Icon,
} from "lucide-react"
} from "@workspace/ui/components/icon"
import { uiMessages, useMessage } from "./i18n"
const toast = ToastPrimitive.createToastManager()
const defaultToastActionRender = <Button variant="outline" size="sm" />
const defaultToastCloseRender = <Button variant="ghost" size="icon-sm" />
function ToastProvider({ ...props }: ToastPrimitive.Provider.Props) {
return <ToastPrimitive.Provider {...props} />
@@ -101,7 +103,7 @@ function ToastDescription({
function ToastAction({
className,
render = <Button variant="outline" size="sm" />,
render = defaultToastActionRender,
...props
}: ToastPrimitive.Action.Props) {
return (
@@ -118,7 +120,7 @@ function ToastClose({
"aria-label": ariaLabel,
className,
children,
render = <Button variant="ghost" size="icon-sm" />,
render = defaultToastCloseRender,
...props
}: ToastPrimitive.Close.Props) {
const closeLabel = useMessage(uiMessages.closeToast)