mirror of
https://github.com/walkxcode/dashboard-icons.git
synced 2025-06-28 15:30:22 +08:00
refactor(web): enhance consistency and accessibility across components
This commit is contained in:
parent
d6cb15aab0
commit
df3c53818a
@ -199,7 +199,7 @@
|
|||||||
--secondary: oklch(0.31 0.03 266.71);
|
--secondary: oklch(0.31 0.03 266.71);
|
||||||
--secondary-foreground: oklch(0.92 0 0);
|
--secondary-foreground: oklch(0.92 0 0);
|
||||||
--muted: oklch(0.31 0.03 266.71);
|
--muted: oklch(0.31 0.03 266.71);
|
||||||
--muted-foreground: oklch(0.72 0 0);
|
--muted-foreground: oklch(0.78 0 0);
|
||||||
--accent: oklch(0.34 0.06 267.59);
|
--accent: oklch(0.34 0.06 267.59);
|
||||||
--accent-foreground: oklch(0.88 0.06 254.13);
|
--accent-foreground: oklch(0.88 0.06 254.13);
|
||||||
--destructive: oklch(0.64 0.21 25.33);
|
--destructive: oklch(0.64 0.21 25.33);
|
||||||
|
@ -277,14 +277,14 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
{/* Filter dropdown */}
|
{/* Filter dropdown */}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="outline" size="sm" className="flex-1 sm:flex-none cursor-pointer bg-background border-border shadow-sm ">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="flex-1 sm:flex-none cursor-pointer bg-background border-border shadow-sm"
|
||||||
|
aria-label="Filter icons"
|
||||||
|
>
|
||||||
<Filter className="h-4 w-4 mr-2" />
|
<Filter className="h-4 w-4 mr-2" />
|
||||||
<span>Categories</span>
|
<span>{selectedCategories.length > 0 ? `Filters (${selectedCategories.length})` : "Filter"}</span>
|
||||||
{selectedCategories.length > 0 && (
|
|
||||||
<Badge variant="secondary" className="ml-2 px-1.5">
|
|
||||||
{selectedCategories.length}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start" className="w-64 sm:w-56">
|
<DropdownMenuContent align="start" className="w-64 sm:w-56">
|
||||||
@ -353,7 +353,13 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
|
|
||||||
{/* Clear all button */}
|
{/* Clear all button */}
|
||||||
{(searchQuery || selectedCategories.length > 0 || sortOption !== "relevance") && (
|
{(searchQuery || selectedCategories.length > 0 || sortOption !== "relevance") && (
|
||||||
<Button variant="outline" size="sm" onClick={clearFilters} className="flex-1 sm:flex-none cursor-pointer bg-background">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={clearFilters}
|
||||||
|
className="flex-1 sm:flex-none cursor-pointer bg-background"
|
||||||
|
aria-label="Reset all filters"
|
||||||
|
>
|
||||||
<X className="h-4 w-4 mr-2" />
|
<X className="h-4 w-4 mr-2" />
|
||||||
<span>Reset</span>
|
<span>Reset</span>
|
||||||
</Button>
|
</Button>
|
||||||
@ -406,15 +412,15 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
<div className="flex flex-col gap-4 items-center w-full">
|
<div className="flex flex-col gap-4 items-center w-full">
|
||||||
<IconSubmissionContent />
|
<IconSubmissionContent />
|
||||||
<div className="mt-4 flex items-center gap-2 justify-center">
|
<div className="mt-4 flex items-center gap-2 justify-center">
|
||||||
<span className="text-sm text-muted-foreground">Need help?</span>
|
<span className="text-sm text-muted-foreground">Can't submit it yourself?</span>
|
||||||
<Button
|
<Button
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsLazyRequestSubmitted(true)
|
setIsLazyRequestSubmitted(true)
|
||||||
toast("Request submitted", {
|
toast("Request received!", {
|
||||||
description: `We've added "${searchQuery || "this icon"}" to our request list.`,
|
description: `We've noted your request for "${searchQuery || "this icon"}". Thanks for your suggestion.`,
|
||||||
})
|
})
|
||||||
posthog.capture("lazy icon request", {
|
posthog.capture("lazy icon request", {
|
||||||
query: searchQuery,
|
query: searchQuery,
|
||||||
@ -423,7 +429,7 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
}}
|
}}
|
||||||
disabled={isLazyRequestSubmitted}
|
disabled={isLazyRequestSubmitted}
|
||||||
>
|
>
|
||||||
Submit request
|
Request this icon
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -432,7 +438,8 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex justify-between items-center pb-2">
|
<div className="flex justify-between items-center pb-2">
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{filteredIcons.length} {filteredIcons.length === 1 ? "icon" : "icons"} found
|
Found {filteredIcons.length} icon
|
||||||
|
{filteredIcons.length !== 1 ? "s" : ""}.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||||
{getSortIcon(sortOption)}
|
{getSortIcon(sortOption)}
|
||||||
|
@ -54,7 +54,7 @@ export default async function IconsPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="isolate overflow-hidden">
|
<div className="isolate overflow-hidden">
|
||||||
<div className="py-8">
|
<div className="py-8">
|
||||||
<div className="space-y-4 mb-8 mx-auto max-w-7xl">
|
<div className="space-y-4 mb-8 mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold">Icons</h1>
|
<h1 className="text-3xl font-bold">Icons</h1>
|
||||||
|
@ -103,9 +103,14 @@ export function CommandMenu({ icons, open: externalOpen, onOpenChange: externalO
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandDialog open={isOpen} onOpenChange={setIsOpen}>
|
<CommandDialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<CommandInput placeholder="Search for icons by name, category, or purpose..." value={query} onValueChange={setQuery} />
|
<CommandInput placeholder="Search icons by name, category, or alias..." value={query} onValueChange={setQuery} />
|
||||||
<CommandList>
|
<CommandList className="max-h-[350px]">
|
||||||
<CommandEmpty>No matching icons found. Try a different search term or browse all icons.</CommandEmpty>
|
<CommandEmpty>
|
||||||
|
<div className="py-6 text-center">
|
||||||
|
<p className="text-sm text-muted-foreground">No matching icons found.</p>
|
||||||
|
<p className="text-xs text-muted-foreground mt-1">Try a different search term or browse all icons.</p>
|
||||||
|
</div>
|
||||||
|
</CommandEmpty>
|
||||||
<CommandGroup heading="Icons">
|
<CommandGroup heading="Icons">
|
||||||
{filteredIcons.map(({ name, data }) => {
|
{filteredIcons.map(({ name, data }) => {
|
||||||
// Find matched alias for display if available
|
// Find matched alias for display if available
|
||||||
@ -115,19 +120,25 @@ export function CommandMenu({ icons, open: externalOpen, onOpenChange: externalO
|
|||||||
: null
|
: null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandItem key={name} value={name} onSelect={() => handleSelect(name)} className="flex items-center gap-2 cursor-pointer">
|
<CommandItem key={name} value={name} onSelect={() => handleSelect(name)} className="flex items-center gap-3 cursor-pointer">
|
||||||
<div className="flex-shrink-0 h-5 w-5 relative">
|
<div className="flex-shrink-0 h-8 w-8 relative">
|
||||||
<div className="h-5 w-5 bg-rose-100 dark:bg-rose-900/30 rounded-md flex items-center justify-center">
|
<div className="h-8 w-8 bg-accent/40 dark:bg-accent/25 rounded-lg border border-border/60 flex items-center justify-center shadow-sm backdrop-blur-sm">
|
||||||
<span className="text-[10px] font-medium text-rose-800 dark:text-rose-300">{name.substring(0, 2).toUpperCase()}</span>
|
<span className="text-[10px] font-medium">{name.substring(0, 2).toUpperCase()}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span className="flex-grow capitalize">{name.replace(/-/g, " ")}</span>
|
<div className="flex flex-col gap-0.5">
|
||||||
{matchedAlias && <span className="text-xs text-primary-500 truncate max-w-[100px]">alias: {matchedAlias}</span>}
|
<span className="capitalize text-sm font-medium">{name.replace(/-/g, " ")}</span>
|
||||||
{!matchedAlias && data.categories && data.categories.length > 0 && (
|
{matchedAlias && (
|
||||||
<span className="text-xs text-muted-foreground truncate max-w-[100px]">
|
<span className="text-xs text-muted-foreground truncate max-w-[180px]">
|
||||||
{data.categories[0].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())}
|
Alias: {matchedAlias}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
{!matchedAlias && data.categories && data.categories.length > 0 && (
|
||||||
|
<span className="text-xs text-muted-foreground truncate max-w-[180px]">
|
||||||
|
{data.categories[0].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</CommandItem>
|
</CommandItem>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
@ -205,7 +205,7 @@ export function HeroSection({ totalIcons, stars }: { totalIcons: number; stars:
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10 container mx-auto px-4 md:px-6 mt-4 py-20">
|
<div className="relative z-10 container mx-auto px-4 sm:px-6 lg:px-8 mt-4 py-20">
|
||||||
<div className="max-w-4xl mx-auto text-center flex flex-col gap-4 ">
|
<div className="max-w-4xl mx-auto text-center flex flex-col gap-4 ">
|
||||||
<h1 className="relative text-3xl sm:text-5xl md:text-7xl font-bold mb-4 md:mb-8 tracking-tight motion-preset-slide-up motion-duration-500 ">
|
<h1 className="relative text-3xl sm:text-5xl md:text-7xl font-bold mb-4 md:mb-8 tracking-tight motion-preset-slide-up motion-duration-500 ">
|
||||||
Your definitive source for
|
Your definitive source for
|
||||||
|
@ -207,6 +207,7 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
size="icon"
|
size="icon"
|
||||||
className="h-8 w-8 rounded-lg cursor-pointer"
|
className="h-8 w-8 rounded-lg cursor-pointer"
|
||||||
onClick={(e) => handleDownload(e, imageUrl, `${iconName}.${format}`)}
|
onClick={(e) => handleDownload(e, imageUrl, `${iconName}.${format}`)}
|
||||||
|
aria-label={`Download ${iconName} in ${format} format${theme ? ` (${theme} theme)` : ""}`}
|
||||||
>
|
>
|
||||||
<Download className="w-4 h-4" />
|
<Download className="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
@ -223,6 +224,7 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
size="icon"
|
size="icon"
|
||||||
className="h-8 w-8 rounded-lg cursor-pointer"
|
className="h-8 w-8 rounded-lg cursor-pointer"
|
||||||
onClick={(e) => handleCopy(imageUrl, `btn-${variantKey}`, e)}
|
onClick={(e) => handleCopy(imageUrl, `btn-${variantKey}`, e)}
|
||||||
|
aria-label={`Copy URL for ${iconName} in ${format} format${theme ? ` (${theme} theme)` : ""}`}
|
||||||
>
|
>
|
||||||
{copiedVariants[`btn-${variantKey}`] ? <Check className="w-4 h-4 text-green-500" /> : <Copy className="w-4 h-4" />}
|
{copiedVariants[`btn-${variantKey}`] ? <Check className="w-4 h-4 text-green-500" /> : <Copy className="w-4 h-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
@ -234,8 +236,18 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button variant="outline" size="icon" className="h-8 w-8 rounded-lg" asChild>
|
<Button
|
||||||
<Link href={githubUrl} target="_blank" rel="noopener noreferrer">
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
className="h-8 w-8 rounded-lg"
|
||||||
|
asChild
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={githubUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
aria-label={`View ${iconName} ${format} file on GitHub`}
|
||||||
|
>
|
||||||
<Github className="w-4 h-4" />
|
<Github className="w-4 h-4" />
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
@ -252,7 +264,7 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto pt-12 pb-14">
|
<div className="container mx-auto pt-12 pb-14 px-4 sm:px-6 lg:px-8">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
||||||
{/* Left Column: Icon Info and Author */}
|
{/* Left Column: Icon Info and Author */}
|
||||||
<div className="lg:col-span-1">
|
<div className="lg:col-span-1">
|
||||||
|
@ -30,7 +30,7 @@ export function RecentlyAddedIcons({ icons }: { icons: IconWithName[] }) {
|
|||||||
{/* Background glow */}
|
{/* Background glow */}
|
||||||
<div className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true" />
|
<div className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true" />
|
||||||
|
|
||||||
<div className="mx-auto px-6 lg:px-8">
|
<div className="mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div className="mx-auto max-w-2xl text-center my-4">
|
<div className="mx-auto max-w-2xl text-center my-4">
|
||||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl bg-clip-text text-transparent bg-gradient-to-r from-rose-600 to-rose-500 motion-safe:motion-preset-fade-lg motion-duration-500">
|
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl bg-clip-text text-transparent bg-gradient-to-r from-rose-600 to-rose-500 motion-safe:motion-preset-fade-lg motion-duration-500">
|
||||||
Recently Added Icons
|
Recently Added Icons
|
||||||
|
@ -21,7 +21,7 @@ function Command({
|
|||||||
<CommandPrimitive
|
<CommandPrimitive
|
||||||
data-slot="command"
|
data-slot="command"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
|
"bg-transparent text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -30,8 +30,8 @@ function Command({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CommandDialog({
|
function CommandDialog({
|
||||||
title = "Command Palette",
|
title = "Command Menu",
|
||||||
description = "Search for a command to run...",
|
description = "Search for icons...",
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof Dialog> & {
|
}: React.ComponentProps<typeof Dialog> & {
|
||||||
@ -44,8 +44,8 @@ function CommandDialog({
|
|||||||
<DialogTitle>{title}</DialogTitle>
|
<DialogTitle>{title}</DialogTitle>
|
||||||
<DialogDescription>{description}</DialogDescription>
|
<DialogDescription>{description}</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DialogContent className="overflow-hidden p-0">
|
<DialogContent className="overflow-hidden p-0 border-border bg-background/80 backdrop-blur-xl shadow-lg sm:max-w-md rounded-xl transition-all duration-200 ease-in-out">
|
||||||
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-3 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||||
{children}
|
{children}
|
||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@ -60,13 +60,13 @@ function CommandInput({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="command-input-wrapper"
|
data-slot="command-input-wrapper"
|
||||||
className="flex h-9 items-center gap-2 border-b px-3"
|
className="flex h-12 items-center gap-3 border-b border-border/60 px-4 bg-transparent"
|
||||||
>
|
>
|
||||||
<SearchIcon className="size-4 shrink-0 opacity-50" />
|
<SearchIcon className="size-4 shrink-0 text-muted-foreground" />
|
||||||
<CommandPrimitive.Input
|
<CommandPrimitive.Input
|
||||||
data-slot="command-input"
|
data-slot="command-input"
|
||||||
className={cn(
|
className={cn(
|
||||||
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
"placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -92,12 +92,16 @@ function CommandList({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CommandEmpty({
|
function CommandEmpty({
|
||||||
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
||||||
return (
|
return (
|
||||||
<CommandPrimitive.Empty
|
<CommandPrimitive.Empty
|
||||||
data-slot="command-empty"
|
data-slot="command-empty"
|
||||||
className="py-6 text-center text-sm"
|
className={cn(
|
||||||
|
"py-6 text-center text-sm text-muted-foreground",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -111,7 +115,7 @@ function CommandGroup({
|
|||||||
<CommandPrimitive.Group
|
<CommandPrimitive.Group
|
||||||
data-slot="command-group"
|
data-slot="command-group"
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
|
"text-foreground overflow-hidden p-1.5 px-2 [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -140,7 +144,7 @@ function CommandItem({
|
|||||||
<CommandPrimitive.Item
|
<CommandPrimitive.Item
|
||||||
data-slot="command-item"
|
data-slot="command-item"
|
||||||
className={cn(
|
className={cn(
|
||||||
"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
"data-[selected=true]:bg-accent/70 data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors duration-200",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user