fix(ui): update coss ui components (#26989)
* fix(ui): update coss ui components * fix(sidebar): remove redundant overflow-auto from SidebarContent ScrollArea already provides the scroll container, so keeping overflow-auto on the child creates a nested scroll area and prevents scrollFade from reflecting actual overflow. Addresses Cubic AI review feedback with confidence 9/10. Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
40 files changed
+720
-223
No files matched your search
@@ -28,14 +28,17 @@ function AccordionTrigger({
|
||||
<AccordionPrimitive.Header className="flex">
|
||||
<AccordionPrimitive.Trigger
|
||||
className={cn(
|
||||
"flex flex-1 cursor-pointer items-start justify-between gap-4 rounded-md py-4 text-left font-medium text-sm outline-none transition-all focus-visible:ring-[3px] focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-64 [&[data-panel-open]>svg]:rotate-180",
|
||||
"flex flex-1 cursor-pointer items-start justify-between gap-4 rounded-md py-4 text-left font-medium text-sm outline-none transition-all focus-visible:ring-[3px] focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-64 data-panel-open:*:data-[slot=accordion-indicator]:rotate-180",
|
||||
className,
|
||||
)}
|
||||
data-slot="accordion-trigger"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronDownIcon className="pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-80 transition-transform duration-200 ease-in-out" />
|
||||
<ChevronDownIcon
|
||||
className="pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-80 transition-transform duration-200 ease-in-out"
|
||||
data-slot="accordion-indicator"
|
||||
/>
|
||||
</AccordionPrimitive.Trigger>
|
||||
</AccordionPrimitive.Header>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,8 @@ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog
|
||||
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
|
||||
const AlertDialogCreateHandle = AlertDialogPrimitive.createHandle;
|
||||
|
||||
const AlertDialog = AlertDialogPrimitive.Root;
|
||||
|
||||
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
||||
@@ -37,7 +39,7 @@ function AlertDialogViewport({
|
||||
return (
|
||||
<AlertDialogPrimitive.Viewport
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 grid grid-rows-[1fr_auto] justify-items-center pt-6 sm:grid-rows-[1fr_auto_3fr] sm:p-4",
|
||||
"fixed inset-0 z-50 grid grid-rows-[1fr_auto_3fr] justify-items-center p-4",
|
||||
className,
|
||||
)}
|
||||
data-slot="alert-dialog-viewport"
|
||||
@@ -48,15 +50,25 @@ function AlertDialogViewport({
|
||||
|
||||
function AlertDialogPopup({
|
||||
className,
|
||||
bottomStickOnMobile = true,
|
||||
...props
|
||||
}: AlertDialogPrimitive.Popup.Props) {
|
||||
}: AlertDialogPrimitive.Popup.Props & {
|
||||
bottomStickOnMobile?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogBackdrop />
|
||||
<AlertDialogViewport>
|
||||
<AlertDialogViewport
|
||||
className={cn(
|
||||
bottomStickOnMobile &&
|
||||
"max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12",
|
||||
)}
|
||||
>
|
||||
<AlertDialogPrimitive.Popup
|
||||
className={cn(
|
||||
"sm:-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 grid max-h-full w-full min-w-0 border-t bg-popover bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] data-nested-dialog-open:origin-top data-ending-style:opacity-0 data-starting-style:opacity-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden sm:max-w-lg sm:data-nested:data-ending-style:translate-y-8 sm:data-nested:data-starting-style:translate-y-8 sm:scale-[calc(1-0.1*var(--nested-dialogs))] sm:rounded-2xl sm:border sm:data-ending-style:scale-98 sm:data-starting-style:scale-98 sm:before:rounded-[calc(var(--radius-2xl)-1px)] dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
bottomStickOnMobile &&
|
||||
"max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden max-sm:before:rounded-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="alert-dialog-popup"
|
||||
@@ -94,7 +106,7 @@ function AlertDialogFooter({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]",
|
||||
variant === "default" && "border-t bg-muted/50 py-4",
|
||||
variant === "default" && "border-t bg-muted/72 py-4",
|
||||
variant === "bare" && "pt-4 pb-6",
|
||||
className,
|
||||
)}
|
||||
@@ -110,7 +122,10 @@ function AlertDialogTitle({
|
||||
}: AlertDialogPrimitive.Title.Props) {
|
||||
return (
|
||||
<AlertDialogPrimitive.Title
|
||||
className={cn("font-heading text-xl leading-none", className)}
|
||||
className={cn(
|
||||
"font-heading font-semibold text-xl leading-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="alert-dialog-title"
|
||||
{...props}
|
||||
/>
|
||||
@@ -137,6 +152,7 @@ function AlertDialogClose(props: AlertDialogPrimitive.Close.Props) {
|
||||
}
|
||||
|
||||
export {
|
||||
AlertDialogCreateHandle,
|
||||
AlertDialog,
|
||||
AlertDialogPortal,
|
||||
AlertDialogBackdrop,
|
||||
|
||||
@@ -13,26 +13,40 @@ function AutocompleteInput({
|
||||
className,
|
||||
showTrigger = false,
|
||||
showClear = false,
|
||||
startAddon,
|
||||
size,
|
||||
...props
|
||||
}: Omit<AutocompletePrimitive.Input.Props, "size"> & {
|
||||
showTrigger?: boolean;
|
||||
showClear?: boolean;
|
||||
startAddon?: React.ReactNode;
|
||||
size?: "sm" | "default" | "lg" | number;
|
||||
ref?: React.Ref<HTMLInputElement>;
|
||||
}) {
|
||||
const sizeValue = (size ?? "default") as "sm" | "default" | "lg" | number;
|
||||
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
<div className="relative not-has-[>*.w-full]:w-fit w-full has-disabled:opacity-64">
|
||||
{startAddon && (
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="[&_svg]:-mx-0.5 pointer-events-none absolute inset-y-0 start-px z-10 flex items-center ps-[calc(--spacing(3)-1px)] opacity-80 has-[+[data-size=sm]]:ps-[calc(--spacing(2.5)-1px)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4"
|
||||
data-slot="autocomplete-start-addon"
|
||||
>
|
||||
{startAddon}
|
||||
</div>
|
||||
)}
|
||||
<AutocompletePrimitive.Input
|
||||
className={cn(
|
||||
startAddon &&
|
||||
"data-[size=sm]:*:data-[slot=autocomplete-input]:ps-[calc(--spacing(7.5)-1px)] *:data-[slot=autocomplete-input]:ps-[calc(--spacing(8.5)-1px)] sm:data-[size=sm]:*:data-[slot=autocomplete-input]:ps-[calc(--spacing(7)-1px)] sm:*:data-[slot=autocomplete-input]:ps-[calc(--spacing(8)-1px)]",
|
||||
sizeValue === "sm"
|
||||
? "has-[+[data-slot=autocomplete-trigger],+[data-slot=autocomplete-clear]]:*:data-[slot=autocomplete-input]:pe-6.5"
|
||||
: "has-[+[data-slot=autocomplete-trigger],+[data-slot=autocomplete-clear]]:*:data-[slot=autocomplete-input]:pe-7",
|
||||
className,
|
||||
)}
|
||||
data-slot="autocomplete-input"
|
||||
render={<Input size={sizeValue} />}
|
||||
render={<Input nativeInput size={sizeValue} />}
|
||||
{...props}
|
||||
/>
|
||||
{showTrigger && (
|
||||
@@ -76,7 +90,7 @@ function AutocompletePopup({
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"relative flex max-h-full origin-(--transform-origin) rounded-lg border bg-popover bg-clip-padding transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-lg has-data-starting-style:scale-98 has-data-starting-style:opacity-0 dark:not-in-data-[slot=group]:bg-clip-border",
|
||||
"relative flex max-h-full origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
@@ -131,7 +145,7 @@ function AutocompleteGroup({
|
||||
}: AutocompletePrimitive.Group.Props) {
|
||||
return (
|
||||
<AutocompletePrimitive.Group
|
||||
className={className}
|
||||
className={cn("[[role=group]+&]:mt-1.5", className)}
|
||||
data-slot="autocomplete-group"
|
||||
{...props}
|
||||
/>
|
||||
@@ -197,7 +211,7 @@ function AutocompleteList({
|
||||
<ScrollArea scrollbarGutter scrollFade>
|
||||
<AutocompletePrimitive.List
|
||||
className={cn(
|
||||
"not-empty:scroll-py-1 not-empty:px-1 not-empty:py-1 in-data-has-overflow-y:pe-3",
|
||||
"not-empty:scroll-py-1 not-empty:p-1 in-data-has-overflow-y:pe-3",
|
||||
className,
|
||||
)}
|
||||
data-slot="autocomplete-list"
|
||||
@@ -265,6 +279,8 @@ function AutocompleteTrigger({
|
||||
);
|
||||
}
|
||||
|
||||
const useAutocompleteFilter = AutocompletePrimitive.useFilter;
|
||||
|
||||
export {
|
||||
Autocomplete,
|
||||
AutocompleteInput,
|
||||
@@ -281,4 +297,5 @@ export {
|
||||
AutocompleteStatus,
|
||||
AutocompleteRow,
|
||||
AutocompleteCollection,
|
||||
useAutocompleteFilter,
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
@@ -27,7 +29,7 @@ const badgeVariants = cva(
|
||||
"bg-destructive/8 text-destructive-foreground dark:bg-destructive/16",
|
||||
info: "bg-info/8 text-info-foreground dark:bg-info/16",
|
||||
outline:
|
||||
"border-border bg-transparent dark:bg-input/32 [button,a&]:hover:bg-accent/50 dark:[button,a&]:hover:bg-input/48",
|
||||
"border-input bg-background dark:bg-input/32 [button,a&]:hover:bg-accent/50 dark:[button,a&]:hover:bg-input/48",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground [button,a&]:hover:bg-secondary/90",
|
||||
success: "bg-success/8 text-success-foreground dark:bg-success/16",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
||||
@@ -14,7 +16,7 @@ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
||||
<ol
|
||||
className={cn(
|
||||
"wrap-break-word flex flex-wrap items-center gap-1.5 text-muted-foreground text-sm sm:gap-2.5",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
data-slot="breadcrumb-list"
|
||||
{...props}
|
||||
@@ -51,6 +53,7 @@ function BreadcrumbLink({
|
||||
|
||||
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
||||
return (
|
||||
// biome-ignore lint(a11y/useFocusableInteractive): known
|
||||
<span
|
||||
aria-current="page"
|
||||
aria-disabled="true"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
@@ -29,17 +31,18 @@ const buttonVariants = cva(
|
||||
},
|
||||
variant: {
|
||||
default:
|
||||
"not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 shadow-xs hover:bg-primary/90 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none",
|
||||
"not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 shadow-xs [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-primary/90",
|
||||
destructive:
|
||||
"not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 shadow-xs hover:bg-destructive/90 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none",
|
||||
"not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 shadow-xs [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-destructive/90",
|
||||
"destructive-outline":
|
||||
"border-border bg-transparent bg-clip-padding text-destructive-foreground shadow-xs not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-in-data-[slot=group]:bg-clip-border dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/4%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-destructive/4",
|
||||
ghost: "border-transparent hover:bg-accent data-pressed:bg-accent",
|
||||
link: "border-transparent underline-offset-4 hover:underline",
|
||||
"border-input bg-transparent not-dark:bg-clip-padding text-destructive-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:border-destructive/32 [:hover,[data-pressed]]:bg-destructive/4",
|
||||
ghost:
|
||||
"border-transparent data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
|
||||
link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
|
||||
outline:
|
||||
"border-border bg-background bg-clip-padding shadow-xs not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-in-data-[slot=group]:bg-clip-border dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/4%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64",
|
||||
"border-input bg-background not-dark:bg-clip-padding shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64",
|
||||
secondary:
|
||||
"border-secondary bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90",
|
||||
"border-transparent bg-secondary text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80 [:hover,[data-pressed]]:bg-secondary/90",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,93 +1,145 @@
|
||||
import type * as React from "react";
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
|
||||
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative flex flex-col gap-6 rounded-2xl border bg-card bg-clip-padding py-6 text-card-foreground shadow-xs before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="card"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function Card({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn(
|
||||
"relative flex flex-col gap-6 rounded-2xl border bg-card not-dark:bg-clip-padding py-6 text-card-foreground shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
),
|
||||
"data-slot": "card",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||
className,
|
||||
)}
|
||||
data-slot="card-header"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardHeader({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn(
|
||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||
className,
|
||||
),
|
||||
"data-slot": "card-header",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn("font-semibold text-lg leading-none", className)}
|
||||
data-slot="card-title"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardTitle({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn("font-semibold text-lg leading-none", className),
|
||||
"data-slot": "card-title",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
data-slot="card-description"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardDescription({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn("text-muted-foreground text-sm", className),
|
||||
"data-slot": "card-description",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className,
|
||||
)}
|
||||
data-slot="card-action"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardAction({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className,
|
||||
),
|
||||
"data-slot": "card-action",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
function CardPanel({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn("px-6", className)}
|
||||
data-slot="card-content"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardPanel({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn("px-6", className),
|
||||
"data-slot": "card-content",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
||||
data-slot="card-footer"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function CardFooter({
|
||||
className,
|
||||
render,
|
||||
...props
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn("flex items-center px-6 [.border-t]:pt-6", className),
|
||||
"data-slot": "card-footer",
|
||||
};
|
||||
|
||||
return useRender({
|
||||
defaultTagName: "div",
|
||||
props: mergeProps<"div">(defaultProps, props),
|
||||
render,
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardPanel,
|
||||
CardPanel as CardContent,
|
||||
CardTitle,
|
||||
};
|
||||
@@ -8,7 +8,7 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
|
||||
return (
|
||||
<CheckboxPrimitive.Root
|
||||
className={cn(
|
||||
"relative inline-flex size-4.5 shrink-0 items-center justify-center rounded-[4px] border border-input bg-background bg-clip-padding shadow-xs outline-none ring-ring transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[3px] not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-offset-background aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/48 data-disabled:opacity-64 sm:size-4 dark:not-data-checked:bg-input/32 dark:bg-clip-border dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/8%)] [[data-disabled],[data-checked],[aria-invalid]]:shadow-none",
|
||||
"relative inline-flex size-4.5 shrink-0 items-center justify-center rounded-[4px] border border-input bg-background not-dark:bg-clip-padding shadow-xs/5 outline-none ring-ring transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[3px] not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-offset-background aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/48 data-disabled:opacity-64 sm:size-4 dark:not-data-checked:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)] [[data-disabled],[data-checked],[aria-invalid]]:shadow-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="checkbox"
|
||||
|
||||
@@ -38,12 +38,15 @@ function ComboboxInput({
|
||||
className,
|
||||
showTrigger = true,
|
||||
showClear = false,
|
||||
startAddon,
|
||||
size,
|
||||
...props
|
||||
}: Omit<ComboboxPrimitive.Input.Props, "size"> & {
|
||||
showTrigger?: boolean;
|
||||
showClear?: boolean;
|
||||
startAddon?: React.ReactNode;
|
||||
size?: "sm" | "default" | "lg" | number;
|
||||
ref?: React.Ref<HTMLInputElement>;
|
||||
}) {
|
||||
const { multiple } = React.useContext(ComboboxContext);
|
||||
const sizeValue = (size ?? "default") as "sm" | "default" | "lg" | number;
|
||||
@@ -64,18 +67,36 @@ function ComboboxInput({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// single mode
|
||||
return (
|
||||
<div className="relative w-full has-disabled:opacity-64">
|
||||
<div className="relative not-has-[>*.w-full]:w-fit w-full has-disabled:opacity-64">
|
||||
{startAddon && (
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="[&_svg]:-mx-0.5 pointer-events-none absolute inset-y-0 start-px z-10 flex items-center ps-[calc(--spacing(3)-1px)] opacity-80 has-[+[data-size=sm]]:ps-[calc(--spacing(2.5)-1px)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4"
|
||||
data-slot="combobox-start-addon"
|
||||
>
|
||||
{startAddon}
|
||||
</div>
|
||||
)}
|
||||
<ComboboxPrimitive.Input
|
||||
className={cn(
|
||||
startAddon &&
|
||||
"data-[size=sm]:*:data-[slot=combobox-input]:ps-[calc(--spacing(7.5)-1px)] *:data-[slot=combobox-input]:ps-[calc(--spacing(8.5)-1px)] sm:data-[size=sm]:*:data-[slot=combobox-input]:ps-[calc(--spacing(7)-1px)] sm:*:data-[slot=combobox-input]:ps-[calc(--spacing(8)-1px)]",
|
||||
sizeValue === "sm"
|
||||
? "has-[+[data-slot=combobox-trigger],+[data-slot=combobox-clear]]:*:data-[slot=combobox-input]:pe-6.5"
|
||||
: "has-[+[data-slot=combobox-trigger],+[data-slot=combobox-clear]]:*:data-[slot=combobox-input]:pe-7",
|
||||
className,
|
||||
)}
|
||||
data-slot="combobox-input"
|
||||
render={<Input className="has-disabled:opacity-100" size={sizeValue} />}
|
||||
render={
|
||||
<Input
|
||||
className="has-disabled:opacity-100"
|
||||
nativeInput
|
||||
size={sizeValue}
|
||||
/>
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
{showTrigger && (
|
||||
@@ -135,7 +156,7 @@ function ComboboxPopup({
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"relative flex max-h-full origin-(--transform-origin) rounded-lg border bg-popover bg-clip-padding transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-lg has-data-starting-style:scale-98 has-data-starting-style:opacity-0 dark:not-in-data-[slot=group]:bg-clip-border",
|
||||
"relative flex max-h-full origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
@@ -202,7 +223,7 @@ function ComboboxSeparator({
|
||||
function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
|
||||
return (
|
||||
<ComboboxPrimitive.Group
|
||||
className={className}
|
||||
className={cn("[[role=group]+&]:mt-1.5", className)}
|
||||
data-slot="combobox-group"
|
||||
{...props}
|
||||
/>
|
||||
@@ -299,19 +320,48 @@ function ComboboxCollection(props: ComboboxPrimitive.Collection.Props) {
|
||||
);
|
||||
}
|
||||
|
||||
function ComboboxChips({ className, ...props }: ComboboxPrimitive.Chips.Props) {
|
||||
function ComboboxChips({
|
||||
className,
|
||||
children,
|
||||
startAddon,
|
||||
...props
|
||||
}: ComboboxPrimitive.Chips.Props & {
|
||||
startAddon?: React.ReactNode;
|
||||
}) {
|
||||
const { chipsRef } = React.useContext(ComboboxContext);
|
||||
|
||||
return (
|
||||
<ComboboxPrimitive.Chips
|
||||
className={cn(
|
||||
"relative inline-flex min-h-9 w-full flex-wrap gap-1 rounded-lg border border-input bg-background bg-clip-padding p-[calc(--spacing(1)-1px)] text-base shadow-xs outline-none ring-ring/24 transition-shadow *:min-h-7 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] focus-within:border-ring focus-within:ring-[3px] has-disabled:pointer-events-none has-data-[size=lg]:min-h-10 has-data-[size=sm]:min-h-8 has-aria-invalid:border-destructive/36 has-disabled:opacity-64 has-[:disabled,:focus-within,[aria-invalid]]:shadow-none focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/16 has-data-[size=lg]:*:min-h-8 has-data-[size=sm]:*:min-h-6 sm:min-h-8 sm:text-sm sm:has-data-[size=lg]:min-h-9 sm:has-data-[size=sm]:min-h-7 sm:*:min-h-6 sm:has-data-[size=lg]:*:min-h-7 sm:has-data-[size=sm]:*:min-h-5 dark:not-has-disabled:bg-input/32 dark:not-in-data-[slot=group]:bg-clip-border dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative inline-flex min-h-9 w-full flex-wrap gap-1 rounded-lg border border-input bg-background not-dark:bg-clip-padding p-[calc(--spacing(1)-1px)] text-base shadow-xs/5 outline-none ring-ring/24 transition-shadow *:min-h-7 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-within:border-ring focus-within:ring-[3px] has-disabled:pointer-events-none has-data-[size=lg]:min-h-10 has-data-[size=sm]:min-h-8 has-aria-invalid:border-destructive/36 has-disabled:opacity-64 has-[:disabled,:focus-within,[aria-invalid]]:shadow-none focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/16 has-data-[size=lg]:*:min-h-8 has-data-[size=sm]:*:min-h-6 sm:min-h-8 sm:text-sm sm:has-data-[size=lg]:min-h-9 sm:has-data-[size=sm]:min-h-7 sm:*:min-h-6 sm:has-data-[size=lg]:*:min-h-7 sm:has-data-[size=sm]:*:min-h-5 dark:not-has-disabled:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="combobox-chips"
|
||||
onMouseDown={(e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const isChip = target.closest('[data-slot="combobox-chip"]');
|
||||
if (isChip || !chipsRef?.current) return;
|
||||
e.preventDefault();
|
||||
const input: HTMLInputElement | null =
|
||||
chipsRef.current.querySelector("input");
|
||||
if (input && !chipsRef.current.querySelector("input:focus")) {
|
||||
input.focus();
|
||||
}
|
||||
}}
|
||||
ref={chipsRef as React.Ref<HTMLDivElement> | null}
|
||||
{...props}
|
||||
/>
|
||||
>
|
||||
{startAddon && (
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="[&_svg]:-ms-0.5 [&_svg]:-me-1.5 flex shrink-0 items-center ps-2 opacity-80 has-[~[data-size=sm]]:has-[+[data-slot=combobox-chip]]:pe-1.5 has-[~[data-size=sm]]:ps-1.5 has-[+[data-slot=combobox-chip]]:pe-2 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none"
|
||||
data-slot="combobox-start-addon"
|
||||
>
|
||||
{startAddon}
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</ComboboxPrimitive.Chips>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -341,6 +391,8 @@ function ComboboxChipRemove(props: ComboboxPrimitive.ChipRemove.Props) {
|
||||
);
|
||||
}
|
||||
|
||||
const useComboboxFilter = ComboboxPrimitive.useFilter;
|
||||
|
||||
export {
|
||||
Combobox,
|
||||
ComboboxInput,
|
||||
@@ -359,4 +411,5 @@ export {
|
||||
ComboboxCollection,
|
||||
ComboboxChips,
|
||||
ComboboxChip,
|
||||
useComboboxFilter,
|
||||
};
|
||||
@@ -0,0 +1,264 @@
|
||||
"use client";
|
||||
|
||||
import { Dialog as CommandDialogPrimitive } from "@base-ui/react/dialog";
|
||||
import { SearchIcon } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
import {
|
||||
Autocomplete,
|
||||
AutocompleteCollection,
|
||||
AutocompleteEmpty,
|
||||
AutocompleteGroup,
|
||||
AutocompleteGroupLabel,
|
||||
AutocompleteInput,
|
||||
AutocompleteItem,
|
||||
AutocompleteList,
|
||||
AutocompleteSeparator,
|
||||
} from "@coss/ui/components/autocomplete";
|
||||
|
||||
const CommandDialog = CommandDialogPrimitive.Root;
|
||||
|
||||
const CommandDialogPortal = CommandDialogPrimitive.Portal;
|
||||
|
||||
const CommandCreateHandle = CommandDialogPrimitive.createHandle;
|
||||
|
||||
function CommandDialogTrigger(props: CommandDialogPrimitive.Trigger.Props) {
|
||||
return (
|
||||
<CommandDialogPrimitive.Trigger
|
||||
data-slot="command-dialog-trigger"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandDialogBackdrop({
|
||||
className,
|
||||
...props
|
||||
}: CommandDialogPrimitive.Backdrop.Props) {
|
||||
return (
|
||||
<CommandDialogPrimitive.Backdrop
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/32 backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0",
|
||||
className,
|
||||
)}
|
||||
data-slot="command-dialog-backdrop"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandDialogViewport({
|
||||
className,
|
||||
...props
|
||||
}: CommandDialogPrimitive.Viewport.Props) {
|
||||
return (
|
||||
<CommandDialogPrimitive.Viewport
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 flex flex-col items-center px-4 py-[max(--spacing(4),4vh)] sm:py-[10vh]",
|
||||
className,
|
||||
)}
|
||||
data-slot="command-dialog-viewport"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandDialogPopup({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: CommandDialogPrimitive.Popup.Props) {
|
||||
return (
|
||||
<CommandDialogPortal>
|
||||
<CommandDialogBackdrop />
|
||||
<CommandDialogViewport>
|
||||
<CommandDialogPrimitive.Popup
|
||||
className={cn(
|
||||
"-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-105 min-h-0 w-full min-w-0 max-w-xl scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 outline-none transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:bg-muted/72 before:shadow-[0_1px_--theme(--color-black/6%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=scroll-area-viewport]:data-has-overflow-y:pe-1 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="command-dialog-popup"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</CommandDialogPrimitive.Popup>
|
||||
</CommandDialogViewport>
|
||||
</CommandDialogPortal>
|
||||
);
|
||||
}
|
||||
|
||||
function Command({
|
||||
autoHighlight = "always",
|
||||
keepHighlight = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Autocomplete>) {
|
||||
return (
|
||||
<Autocomplete
|
||||
autoHighlight={autoHighlight}
|
||||
inline
|
||||
keepHighlight={keepHighlight}
|
||||
open
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandInput({
|
||||
className,
|
||||
placeholder = undefined,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteInput>) {
|
||||
return (
|
||||
<div className="px-2.5 py-1.5">
|
||||
<AutocompleteInput
|
||||
autoFocus
|
||||
className={cn(
|
||||
"border-transparent! bg-transparent! shadow-none before:hidden has-focus-visible:ring-0",
|
||||
className,
|
||||
)}
|
||||
placeholder={placeholder}
|
||||
size="lg"
|
||||
startAddon={<SearchIcon />}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandList({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteList>) {
|
||||
return (
|
||||
<AutocompleteList
|
||||
className={cn("not-empty:scroll-py-2 not-empty:p-2", className)}
|
||||
data-slot="command-list"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandEmpty({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteEmpty>) {
|
||||
return (
|
||||
<AutocompleteEmpty
|
||||
className={cn("not-empty:py-6", className)}
|
||||
data-slot="command-empty"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandPanel({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className="-mx-px not-has-[+[data-slot=command-footer]]:-mb-px relative min-h-0 rounded-t-xl not-has-[+[data-slot=command-footer]]:rounded-b-2xl border border-b-0 bg-popover not-dark:bg-clip-padding shadow-xs/5 [clip-path:inset(0_1px)] not-has-[+[data-slot=command-footer]]:[clip-path:inset(0_1px_1px_1px_round_0_0_calc(var(--radius-2xl)-1px)_calc(var(--radius-2xl)-1px))] before:pointer-events-none before:absolute before:inset-0 before:rounded-t-[calc(var(--radius-xl)-1px)] **:data-[slot=scroll-area-scrollbar]:mt-2 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandGroup({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteGroup>) {
|
||||
return (
|
||||
<AutocompleteGroup
|
||||
className={className}
|
||||
data-slot="command-group"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandGroupLabel({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteGroupLabel>) {
|
||||
return (
|
||||
<AutocompleteGroupLabel
|
||||
className={className}
|
||||
data-slot="command-group-label"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandCollection({
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteCollection>) {
|
||||
return <AutocompleteCollection data-slot="command-collection" {...props} />;
|
||||
}
|
||||
|
||||
function CommandItem({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteItem>) {
|
||||
return (
|
||||
<AutocompleteItem
|
||||
className={cn("py-1.5", className)}
|
||||
data-slot="command-item"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AutocompleteSeparator>) {
|
||||
return (
|
||||
<AutocompleteSeparator
|
||||
className={cn("my-2", className)}
|
||||
data-slot="command-separator"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandShortcut({ className, ...props }: React.ComponentProps<"kbd">) {
|
||||
return (
|
||||
<kbd
|
||||
className={cn(
|
||||
"ms-auto font-medium font-sans text-muted-foreground/72 text-xs tracking-widest",
|
||||
className,
|
||||
)}
|
||||
data-slot="command-shortcut"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CommandFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-between gap-2 rounded-b-[calc(var(--radius-2xl)-1px)] border-t px-5 py-3 text-muted-foreground text-xs",
|
||||
className,
|
||||
)}
|
||||
data-slot="command-footer"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
CommandCreateHandle,
|
||||
Command,
|
||||
CommandCollection,
|
||||
CommandDialog,
|
||||
CommandDialogPopup,
|
||||
CommandDialogTrigger,
|
||||
CommandEmpty,
|
||||
CommandFooter,
|
||||
CommandGroup,
|
||||
CommandGroupLabel,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandPanel,
|
||||
CommandSeparator,
|
||||
CommandShortcut,
|
||||
};
|
||||
@@ -6,6 +6,8 @@ import { cn } from "@coss/ui/lib/utils";
|
||||
import { Button } from "@coss/ui/components/button";
|
||||
import { ScrollArea } from "@coss/ui/components/scroll-area";
|
||||
|
||||
const DialogCreateHandle = DialogPrimitive.createHandle;
|
||||
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
@@ -41,7 +43,7 @@ function DialogViewport({
|
||||
return (
|
||||
<DialogPrimitive.Viewport
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 grid grid-rows-[1fr_auto] justify-items-center pt-12 sm:grid-rows-[1fr_auto_3fr] sm:p-4",
|
||||
"fixed inset-0 z-50 grid grid-rows-[1fr_auto_3fr] justify-items-center p-4",
|
||||
className,
|
||||
)}
|
||||
data-slot="dialog-viewport"
|
||||
@@ -54,17 +56,26 @@ function DialogPopup({
|
||||
className,
|
||||
children,
|
||||
showCloseButton = true,
|
||||
bottomStickOnMobile = true,
|
||||
...props
|
||||
}: DialogPrimitive.Popup.Props & {
|
||||
showCloseButton?: boolean;
|
||||
bottomStickOnMobile?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<DialogPortal>
|
||||
<DialogBackdrop />
|
||||
<DialogViewport>
|
||||
<DialogViewport
|
||||
className={cn(
|
||||
bottomStickOnMobile &&
|
||||
"max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12",
|
||||
)}
|
||||
>
|
||||
<DialogPrimitive.Popup
|
||||
className={cn(
|
||||
"sm:-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 flex-col border-t bg-popover bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] data-nested-dialog-open:origin-top data-ending-style:opacity-0 data-starting-style:opacity-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden sm:max-w-lg sm:data-nested:data-ending-style:translate-y-8 sm:data-nested:data-starting-style:translate-y-8 sm:scale-[calc(1-0.1*var(--nested-dialogs))] sm:rounded-2xl sm:border sm:data-ending-style:scale-98 sm:data-starting-style:scale-98 sm:before:rounded-[calc(var(--radius-2xl)-1px)] dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
bottomStickOnMobile &&
|
||||
"max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden max-sm:before:rounded-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="dialog-popup"
|
||||
@@ -110,7 +121,7 @@ function DialogFooter({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]",
|
||||
variant === "default" && "border-t bg-muted/50 py-4",
|
||||
variant === "default" && "border-t bg-muted/72 py-4",
|
||||
variant === "bare" &&
|
||||
"in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pt-3 pt-4 pb-6",
|
||||
className,
|
||||
@@ -124,7 +135,10 @@ function DialogFooter({
|
||||
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
|
||||
return (
|
||||
<DialogPrimitive.Title
|
||||
className={cn("font-heading text-xl leading-none", className)}
|
||||
className={cn(
|
||||
"font-heading font-semibold text-xl leading-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="dialog-title"
|
||||
{...props}
|
||||
/>
|
||||
@@ -144,9 +158,13 @@ function DialogDescription({
|
||||
);
|
||||
}
|
||||
|
||||
function DialogPanel({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function DialogPanel({
|
||||
className,
|
||||
scrollFade = true,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
|
||||
return (
|
||||
<ScrollArea>
|
||||
<ScrollArea scrollFade={scrollFade}>
|
||||
<div
|
||||
className={cn(
|
||||
"px-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-header])]:pt-1 in-[[data-slot=dialog-popup]:not(:has([data-slot=dialog-header]))]:pt-6 in-[[data-slot=dialog-popup]:not(:has([data-slot=dialog-footer]))]:pb-6! in-[[data-slot=dialog-popup]:not(:has([data-slot=dialog-footer].border-t))]:pb-1 pb-6",
|
||||
@@ -160,6 +178,7 @@ function DialogPanel({ className, ...props }: React.ComponentProps<"div">) {
|
||||
}
|
||||
|
||||
export {
|
||||
DialogCreateHandle,
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
DialogPortal,
|
||||
|
||||
@@ -6,7 +6,7 @@ function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance rounded-xl border-dashed p-6 text-center md:p-12",
|
||||
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance p-6 text-center md:p-12",
|
||||
className,
|
||||
)}
|
||||
data-slot="empty"
|
||||
@@ -37,7 +37,7 @@ const emptyMediaVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-transparent",
|
||||
icon: "relative flex size-9 shrink-0 items-center justify-center rounded-md border bg-card text-foreground shadow-black/5 shadow-sm before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-md)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_svg:not([class*='size-'])]:size-4.5",
|
||||
icon: "relative flex size-9 shrink-0 items-center justify-center rounded-md border bg-card text-foreground shadow-sm/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-md)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -84,7 +84,7 @@ function EmptyMedia({
|
||||
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn("font-heading text-xl leading-none", className)}
|
||||
className={cn("font-heading font-semibold text-xl", className)}
|
||||
data-slot="empty-title"
|
||||
{...props}
|
||||
/>
|
||||
@@ -95,7 +95,7 @@ function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"text-muted-foreground text-sm/relaxed [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1",
|
||||
"text-muted-foreground text-sm [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1",
|
||||
className,
|
||||
)}
|
||||
data-slot="empty-description"
|
||||
|
||||
@@ -27,6 +27,16 @@ function FieldLabel({ className, ...props }: FieldPrimitive.Label.Props) {
|
||||
);
|
||||
}
|
||||
|
||||
function FieldItem({ className, ...props }: FieldPrimitive.Item.Props) {
|
||||
return (
|
||||
<FieldPrimitive.Item
|
||||
className={cn("flex", className)}
|
||||
data-slot="field-item"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function FieldDescription({
|
||||
className,
|
||||
...props
|
||||
@@ -59,5 +69,6 @@ export {
|
||||
FieldDescription,
|
||||
FieldError,
|
||||
FieldControl,
|
||||
FieldItem,
|
||||
FieldValidity,
|
||||
};
|
||||
@@ -2,18 +2,12 @@ import type * as React from "react";
|
||||
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
|
||||
function Frame({
|
||||
className,
|
||||
stackedPanels = false,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { stackedPanels?: boolean }) {
|
||||
function Frame({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative flex flex-col rounded-2xl bg-muted/50 p-1",
|
||||
stackedPanels
|
||||
? "*:has-[+[data-slot=frame-panel]]:rounded-b-none *:has-[+[data-slot=frame-panel]]:before:hidden dark:*:has-[+[data-slot=frame-panel]]:before:block *:[[data-slot=frame-panel]+[data-slot=frame-panel]]:rounded-t-none *:[[data-slot=frame-panel]+[data-slot=frame-panel]]:border-t-0 dark:*:[[data-slot=frame-panel]+[data-slot=frame-panel]]:before:hidden"
|
||||
: "*:[[data-slot=frame-panel]+[data-slot=frame-panel]]:mt-1",
|
||||
"relative flex flex-col rounded-2xl bg-muted/72 p-1",
|
||||
"*:[[data-slot=frame-panel]+[data-slot=frame-panel]]:mt-1",
|
||||
className,
|
||||
)}
|
||||
data-slot="frame"
|
||||
@@ -26,7 +20,7 @@ function FramePanel({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative rounded-xl border bg-background bg-clip-padding p-5 shadow-xs before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative rounded-xl border bg-background bg-clip-padding p-5 shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="frame-panel"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
@@ -7,7 +9,7 @@ import { cn } from "@coss/ui/lib/utils";
|
||||
import { Separator } from "@coss/ui/components/separator";
|
||||
|
||||
const groupVariants = cva(
|
||||
"flex w-fit *:focus-visible:z-10 has-[>[data-slot=group]]:gap-2 *:has-focus-visible:z-10",
|
||||
"flex w-fit *:focus-visible:z-1 has-[>[data-slot=group]]:gap-2 *:has-focus-visible:z-1 dark:*:[[data-slot=button]:hover~[data-slot=separator]:not([data-slot]:hover~[data-slot=separator]~[data-slot=separator]),[data-slot][data-pressed]~[data-slot=separator]:not([data-slot][data-pressed]~[data-slot=separator]~[data-slot=separator])]:before:bg-input/64 dark:*:[[data-slot=separator]:has(~[data-slot=button]:hover):not(:has(~[data-slot=separator]~[data-slot]:hover)),[data-slot=separator]:has(~[data-slot][data-pressed]):not(:has(~[data-slot=separator]~[data-slot][data-pressed]))]:before:bg-input/64",
|
||||
{
|
||||
defaultVariants: {
|
||||
orientation: "horizontal",
|
||||
@@ -15,9 +17,9 @@ const groupVariants = cva(
|
||||
variants: {
|
||||
orientation: {
|
||||
horizontal:
|
||||
"*:not-first:before:-start-[0.5px] *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:before:-end-[0.5px] *:not-first:rounded-s-none *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:rounded-e-none *:not-first:border-s-0 *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:border-e-0 *:not-first:before:rounded-s-none *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:before:rounded-e-none *:after:absolute *:after:start-full *:after:h-full *:after:w-px *:pointer-coarse:after:min-w-auto",
|
||||
"*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-start-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-end-[0.5px] *:pointer-coarse:after:min-w-auto *:data-slot:has-[~[data-slot]]:rounded-e-none *:data-slot:has-[~[data-slot]]:border-e-0 *:data-slot:has-[~[data-slot]]:before:rounded-e-none *:[[data-slot]~[data-slot]]:rounded-s-none *:[[data-slot]~[data-slot]]:border-s-0 *:[[data-slot]~[data-slot]]:before:rounded-s-none",
|
||||
vertical:
|
||||
"*:not-first:before:-top-[0.5px] *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:before:-bottom-[0.5px] flex-col *:not-first:rounded-t-none *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:rounded-b-none *:not-first:border-t-0 *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:border-b-0 *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:before:hidden *:not-first:before:rounded-t-none *:not-nth-last-[1_of_:not(span[data-base-ui-focus-guard],span[data-base-ui-inert])]:before:rounded-b-none *:after:absolute *:after:top-full *:after:h-px *:pointer-coarse:after:min-h-auto *:after:w-full dark:*:last:before:hidden dark:*:first:before:block",
|
||||
"*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-top-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-bottom-[0.5px] flex-col *:pointer-coarse:after:min-h-auto *:data-slot:has-[~[data-slot]]:rounded-b-none *:data-slot:has-[~[data-slot]]:border-b-0 *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:hidden *:data-slot:has-[~[data-slot]]:before:rounded-b-none dark:*:last:before:hidden dark:*:first:before:block *:[[data-slot]~[data-slot]]:rounded-t-none *:[[data-slot]~[data-slot]]:border-t-0 *:[[data-slot]~[data-slot]]:before:rounded-t-none",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -53,7 +55,7 @@ function GroupText({
|
||||
}: useRender.ComponentProps<"div">) {
|
||||
const defaultProps = {
|
||||
className: cn(
|
||||
"relative inline-flex items-center whitespace-nowrap rounded-lg border border-border bg-muted bg-clip-padding px-[calc(--spacing(3)-1px)] text-muted-foreground text-base sm:text-sm shadow-xs outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/64 dark:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 [&_svg]:-mx-0.5",
|
||||
"relative inline-flex items-center whitespace-nowrap rounded-lg border border-input bg-muted not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-muted-foreground text-base sm:text-sm shadow-xs/5 outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/64 dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 [&_svg]:-mx-0.5",
|
||||
className,
|
||||
),
|
||||
"data-slot": "group-text",
|
||||
@@ -75,7 +77,7 @@ function GroupSeparator({
|
||||
return (
|
||||
<Separator
|
||||
className={cn(
|
||||
"[[data-slot=input-control]:focus-within+&,[data-slot=select-trigger]:focus-visible+*+&]:-translate-x-px pointer-events-none relative z-20 has-[+[data-slot=input-control]:focus-within,+[data-slot=select-trigger]:focus-visible+*,+[data-slot=number-field]:focus-within]:translate-x-px has-[+[data-slot=input-control]:focus-within,+[data-slot=select-trigger]:focus-visible+*,+[data-slot=number-field]:focus-within]:bg-ring [[data-slot=input-control]:focus-within+&,[data-slot=select-trigger]:focus-visible+*+&,[data-slot=number-field]:focus-within+&]:bg-ring",
|
||||
"[[data-slot=input-control]:focus-within+&,[data-slot=input-group]:focus-within+&,[data-slot=select-trigger]:focus-visible+*+&,[data-slot=number-field]:focus-within+input+&]:-translate-x-px pointer-events-none relative z-2 before:absolute before:inset-0 has-[+[data-slot=input-control]:focus-within,+[data-slot=input-group]:focus-within,+[data-slot=select-trigger]:focus-visible+*,+[data-slot=number-field]:focus-within]:translate-x-px has-[+[data-slot=input-control]:focus-within,+[data-slot=input-group]:focus-within,+[data-slot=select-trigger]:focus-visible+*,+[data-slot=number-field]:focus-within]:bg-ring dark:before:bg-input/32 [[data-slot=input-control]:focus-within+&,[data-slot=input-group]:focus-within+&,[data-slot=select-trigger]:focus-visible+*+&,[data-slot=number-field]:focus-within+&,[data-slot=number-field]:focus-within+input+&]:bg-ring",
|
||||
className,
|
||||
)}
|
||||
orientation={orientation}
|
||||
|
||||
@@ -11,7 +11,7 @@ function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative inline-flex w-full min-w-0 items-center rounded-lg border border-input bg-background bg-clip-padding text-base shadow-xs ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_1px_--theme(--color-black/4%)] has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/64 has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/16 has-[textarea]:h-auto has-data-[align=block-end]:h-auto has-data-[align=block-start]:h-auto has-data-[align=block-end]:flex-col has-data-[align=block-start]:flex-col has-[input:focus-visible,textarea:focus-visible]:border-ring has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/36 has-[input:disabled,textarea:disabled]:opacity-64 has-[input:disabled,textarea:disabled,input:focus-visible,textarea:focus-visible,input[aria-invalid],textarea[aria-invalid]]:shadow-none has-[input:focus-visible,textarea:focus-visible]:ring-[3px] sm:text-sm dark:bg-input/32 dark:bg-clip-border dark:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/24 dark:not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_-1px_--theme(--color-white/8%)] has-data-[align=inline-start]:**:[[data-size=sm]_input]:ps-1.5 has-data-[align=inline-end]:**:[[data-size=sm]_input]:pe-1.5 *:[[data-slot=input-control],[data-slot=textarea-control]]:contents *:[[data-slot=input-control],[data-slot=textarea-control]]:before:hidden has-[[data-align=block-start],[data-align=block-end]]:**:[input]:h-auto has-data-[align=inline-start]:**:[input]:ps-2 has-data-[align=inline-end]:**:[input]:pe-2 has-data-[align=block-end]:**:[input]:pt-1.5 has-data-[align=block-start]:**:[input]:pb-1.5 **:[textarea]:min-h-20.5 **:[textarea]:resize-none **:[textarea]:py-[calc(--spacing(3)-1px)] **:[textarea]:max-sm:min-h-23.5 **:[textarea_button]:rounded-[calc(var(--radius-md)-1px)]",
|
||||
"relative inline-flex w-full min-w-0 items-center rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_1px_--theme(--color-black/6%)] has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/64 has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/16 has-[textarea]:h-auto has-data-[align=block-end]:h-auto has-data-[align=block-start]:h-auto has-data-[align=block-end]:flex-col has-data-[align=block-start]:flex-col has-[input:focus-visible,textarea:focus-visible]:border-ring has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/36 has-[input:disabled,textarea:disabled]:opacity-64 has-[input:disabled,textarea:disabled,input:focus-visible,textarea:focus-visible,input[aria-invalid],textarea[aria-invalid]]:shadow-none has-[input:focus-visible,textarea:focus-visible]:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/24 dark:not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_-1px_--theme(--color-white/6%)] has-data-[align=inline-start]:**:[[data-size=sm]_input]:ps-1.5 has-data-[align=inline-end]:**:[[data-size=sm]_input]:pe-1.5 *:[[data-slot=input-control],[data-slot=textarea-control]]:contents *:[[data-slot=input-control],[data-slot=textarea-control]]:before:hidden has-[[data-align=block-start],[data-align=block-end]]:**:[input]:h-auto has-data-[align=inline-start]:**:[input]:ps-2 has-data-[align=inline-end]:**:[input]:pe-2 has-data-[align=block-end]:**:[input]:pt-1.5 has-data-[align=block-start]:**:[input]:pb-1.5 **:[textarea]:min-h-20.5 **:[textarea]:resize-none **:[textarea]:py-[calc(--spacing(3)-1px)] **:[textarea]:max-sm:min-h-23.5 **:[textarea_button]:rounded-[calc(var(--radius-md)-1px)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="input-group"
|
||||
@@ -22,7 +22,7 @@ function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
||||
}
|
||||
|
||||
const inputGroupAddonVariants = cva(
|
||||
"[&_svg]:-mx-0.5 not-has-[button]:**:[svg]:not([class*='opacity-'])]:opacity-80 flex h-auto cursor-text select-none items-center justify-center gap-2 [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4",
|
||||
"[&_svg]:-mx-0.5 flex h-auto cursor-text select-none items-center justify-center gap-2 leading-none [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 not-has-[button]:**:[svg:not([class*='opacity-'])]:opacity-80",
|
||||
{
|
||||
defaultVariants: {
|
||||
align: "inline-start",
|
||||
@@ -54,7 +54,9 @@ function InputGroupAddon({
|
||||
data-slot="input-group-addon"
|
||||
onMouseDown={(e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const isInteractive = target.closest("button, a");
|
||||
const isInteractive = target.closest(
|
||||
"button, a, input, select, textarea, [role='button'], [role='combobox'], [role='listbox'], [data-slot='select-trigger']",
|
||||
);
|
||||
if (isInteractive) return;
|
||||
e.preventDefault();
|
||||
const parent = e.currentTarget.parentElement;
|
||||
@@ -74,7 +76,7 @@ function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"[&_svg]:-mx-0.5 line-clamp-1 flex items-center gap-2 text-muted-foreground in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
|
||||
"[&_svg]:-mx-0.5 line-clamp-1 flex items-center gap-2 text-muted-foreground leading-none in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -11,41 +11,54 @@ type InputProps = Omit<
|
||||
> & {
|
||||
size?: "sm" | "default" | "lg" | number;
|
||||
unstyled?: boolean;
|
||||
nativeInput?: boolean;
|
||||
};
|
||||
|
||||
function Input({
|
||||
className,
|
||||
size = "default",
|
||||
unstyled = false,
|
||||
nativeInput = false,
|
||||
...props
|
||||
}: InputProps) {
|
||||
const inputClassName = cn(
|
||||
"h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5",
|
||||
size === "sm" &&
|
||||
"h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5",
|
||||
size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
|
||||
props.type === "search" &&
|
||||
"[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
|
||||
props.type === "file" &&
|
||||
"text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
|
||||
);
|
||||
|
||||
return (
|
||||
<span
|
||||
className={
|
||||
cn(
|
||||
!unstyled &&
|
||||
"relative inline-flex w-full rounded-lg border border-input bg-background bg-clip-padding text-base shadow-xs ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:not-in-data-[slot=group]:bg-clip-border dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
) || undefined
|
||||
}
|
||||
data-size={size}
|
||||
data-slot="input-control"
|
||||
>
|
||||
<InputPrimitive
|
||||
className={cn(
|
||||
"h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5",
|
||||
size === "sm" &&
|
||||
"h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5",
|
||||
size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
|
||||
props.type === "search" &&
|
||||
"[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
|
||||
props.type === "file" &&
|
||||
"text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
|
||||
)}
|
||||
data-slot="input"
|
||||
size={typeof size === "number" ? size : undefined}
|
||||
{...props}
|
||||
/>
|
||||
{nativeInput ? (
|
||||
<input
|
||||
className={inputClassName}
|
||||
data-slot="input"
|
||||
size={typeof size === "number" ? size : undefined}
|
||||
{...props}
|
||||
/>
|
||||
) : (
|
||||
<InputPrimitive
|
||||
className={inputClassName}
|
||||
data-slot="input"
|
||||
size={typeof size === "number" ? size : undefined}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import { ChevronRightIcon } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
|
||||
const MenuCreateHandle = MenuPrimitive.createHandle;
|
||||
|
||||
const Menu = MenuPrimitive.Root;
|
||||
|
||||
const MenuPortal = MenuPrimitive.Portal;
|
||||
@@ -39,7 +41,7 @@ function MenuPopup({
|
||||
>
|
||||
<MenuPrimitive.Popup
|
||||
className={cn(
|
||||
"relative flex not-[class*='w-']:min-w-32 origin-(--transform-origin) rounded-lg border bg-popover bg-clip-padding shadow-lg outline-none transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] focus:outline-none has-data-starting-style:scale-98 has-data-starting-style:opacity-0 dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative flex not-[class*='w-']:min-w-32 origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 outline-none before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] focus:outline-none dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="menu-popup"
|
||||
@@ -70,7 +72,7 @@ function MenuItem({
|
||||
return (
|
||||
<MenuPrimitive.Item
|
||||
className={cn(
|
||||
"[&_svg]:-mx-0.5 flex min-h-8 cursor-default select-none items-center gap-2 rounded-sm px-2 py-1 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-inset:ps-8 data-[variant=destructive]:text-destructive-foreground data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
"[&>svg]:-mx-0.5 flex min-h-8 cursor-default select-none items-center gap-2 rounded-sm px-2 py-1 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-inset:ps-8 data-[variant=destructive]:text-destructive-foreground data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&>svg:not([class*='opacity-'])]:opacity-80 [&>svg:not([class*='size-'])]:size-4.5 sm:[&>svg:not([class*='size-'])]:size-4 [&>svg]:pointer-events-none [&>svg]:shrink-0",
|
||||
className,
|
||||
)}
|
||||
data-inset={inset}
|
||||
@@ -85,34 +87,54 @@ function MenuCheckboxItem({
|
||||
className,
|
||||
children,
|
||||
checked,
|
||||
variant = "default",
|
||||
...props
|
||||
}: MenuPrimitive.CheckboxItem.Props) {
|
||||
}: MenuPrimitive.CheckboxItem.Props & {
|
||||
variant?: "default" | "switch";
|
||||
}) {
|
||||
return (
|
||||
<MenuPrimitive.CheckboxItem
|
||||
checked={checked}
|
||||
className={cn(
|
||||
"grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default grid-cols-[1rem_1fr] items-center gap-2 rounded-sm py-1 ps-2 pe-4 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
"grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default items-center gap-2 rounded-sm py-1 ps-2 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
variant === "switch"
|
||||
? "grid-cols-[1fr_auto] gap-4 pe-1.5"
|
||||
: "grid-cols-[1rem_1fr] pe-4",
|
||||
className,
|
||||
)}
|
||||
data-slot="menu-checkbox-item"
|
||||
{...props}
|
||||
>
|
||||
<MenuPrimitive.CheckboxItemIndicator className="col-start-1">
|
||||
<svg
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
|
||||
</svg>
|
||||
</MenuPrimitive.CheckboxItemIndicator>
|
||||
<span className="col-start-2">{children}</span>
|
||||
{variant === "switch" ? (
|
||||
<>
|
||||
<span className="col-start-1">{children}</span>
|
||||
<MenuPrimitive.CheckboxItemIndicator
|
||||
className="inset-shadow-[0_1px_--theme(--color-black/6%)] inline-flex h-[calc(var(--thumb-size)+2px)] w-[calc(var(--thumb-size)*2-2px)] shrink-0 items-center rounded-full p-px outline-none transition-[background-color,box-shadow] duration-200 [--thumb-size:--spacing(4)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input data-disabled:opacity-64 sm:[--thumb-size:--spacing(3)]"
|
||||
keepMounted
|
||||
>
|
||||
<span className="pointer-events-none block aspect-square h-full in-[[data-slot=menu-checkbox-item][data-checked]]:origin-[var(--thumb-size)_50%] origin-left in-[[data-slot=menu-checkbox-item][data-checked]]:translate-x-[calc(var(--thumb-size)-4px)] in-[[data-slot=menu-checkbox-item]:active]:not-data-disabled:scale-x-110 in-[[data-slot=menu-checkbox-item]:active]:rounded-[var(--thumb-size)/calc(var(--thumb-size)*1.10)] rounded-(--thumb-size) bg-background shadow-sm/5 will-change-transform [transition:translate_.15s,border-radius_.15s,scale_.1s_.1s,transform-origin_.15s]" />
|
||||
</MenuPrimitive.CheckboxItemIndicator>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<MenuPrimitive.CheckboxItemIndicator className="col-start-1">
|
||||
<svg
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
|
||||
</svg>
|
||||
</MenuPrimitive.CheckboxItemIndicator>
|
||||
<span className="col-start-2">{children}</span>
|
||||
</>
|
||||
)}
|
||||
</MenuPrimitive.CheckboxItem>
|
||||
);
|
||||
}
|
||||
@@ -185,11 +207,11 @@ function MenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {
|
||||
);
|
||||
}
|
||||
|
||||
function MenuShortcut({ className, ...props }: React.ComponentProps<"span">) {
|
||||
function MenuShortcut({ className, ...props }: React.ComponentProps<"kbd">) {
|
||||
return (
|
||||
<span
|
||||
<kbd
|
||||
className={cn(
|
||||
"ms-auto font-medium text-muted-foreground/72 text-xs tracking-widest",
|
||||
"ms-auto font-medium font-sans text-muted-foreground/72 text-xs tracking-widest",
|
||||
className,
|
||||
)}
|
||||
data-slot="menu-shortcut"
|
||||
@@ -253,6 +275,8 @@ function MenuSubPopup({
|
||||
}
|
||||
|
||||
export {
|
||||
MenuCreateHandle,
|
||||
MenuCreateHandle as DropdownMenuCreateHandle,
|
||||
Menu,
|
||||
Menu as DropdownMenu,
|
||||
MenuPortal,
|
||||
|
||||
@@ -42,7 +42,7 @@ function NumberFieldGroup({
|
||||
return (
|
||||
<NumberFieldPrimitive.Group
|
||||
className={cn(
|
||||
"relative flex w-full justify-between rounded-lg border border-input bg-background bg-clip-padding text-base shadow-xs ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] focus-within:border-ring focus-within:ring-[3px] has-aria-invalid:border-destructive/36 focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/48 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm dark:bg-input/32 dark:not-in-data-[slot=group]:bg-clip-border dark:has-aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-within,[aria-invalid]]:shadow-none",
|
||||
"relative flex w-full justify-between rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-within:border-ring focus-within:ring-[3px] has-aria-invalid:border-destructive/36 focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/48 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-within,[aria-invalid]]:shadow-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="number-field-group"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { mergeProps } from "@base-ui/react/merge-props";
|
||||
import { useRender } from "@base-ui/react/use-render";
|
||||
import {
|
||||
|
||||
@@ -40,9 +40,9 @@ function PopoverPopup({
|
||||
>
|
||||
<PopoverPrimitive.Popup
|
||||
className={cn(
|
||||
"relative flex h-(--popup-height,auto) w-(--popup-width,auto) origin-(--transform-origin) rounded-lg border bg-popover bg-clip-padding text-popover-foreground shadow-lg transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] data-starting-style:scale-98 data-starting-style:opacity-0 dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative flex h-(--popup-height,auto) w-(--popup-width,auto) origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-starting-style:scale-98 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
tooltipStyle &&
|
||||
"w-fit text-balance rounded-md text-xs shadow-black/5 shadow-md before:rounded-[calc(var(--radius-md)-1px)]",
|
||||
"w-fit text-balance rounded-md text-xs shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="popover-popup"
|
||||
|
||||
@@ -32,7 +32,7 @@ function PreviewCardPopup({
|
||||
>
|
||||
<PreviewCardPrimitive.Popup
|
||||
className={cn(
|
||||
"relative flex w-64 origin-(--transform-origin) text-balance rounded-lg border bg-popover bg-clip-padding p-4 text-popover-foreground text-sm shadow-lg transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative flex w-64 origin-(--transform-origin) text-balance rounded-lg border bg-popover not-dark:bg-clip-padding p-4 text-popover-foreground text-sm shadow-lg/5 transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="preview-card-content"
|
||||
|
||||
@@ -19,7 +19,7 @@ function Radio({ className, ...props }: RadioPrimitive.Root.Props) {
|
||||
return (
|
||||
<RadioPrimitive.Root
|
||||
className={cn(
|
||||
"relative inline-flex size-4.5 shrink-0 items-center justify-center rounded-full border border-input bg-background bg-clip-padding shadow-xs outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-full not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/48 data-disabled:opacity-64 sm:size-4 dark:not-data-checked:bg-input/32 dark:bg-clip-border dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/8%)] [[data-disabled],[data-checked],[aria-invalid]]:shadow-none",
|
||||
"relative inline-flex size-4.5 shrink-0 items-center justify-center rounded-full border border-input bg-background not-dark:bg-clip-padding shadow-xs/5 outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-full not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/48 data-disabled:opacity-64 sm:size-4 dark:not-data-checked:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)] [[data-disabled],[data-checked],[aria-invalid]]:shadow-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="radio"
|
||||
|
||||
@@ -21,7 +21,7 @@ function ScrollArea({
|
||||
>
|
||||
<ScrollAreaPrimitive.Viewport
|
||||
className={cn(
|
||||
"h-full overscroll-contain rounded-[inherit] outline-none transition-shadows focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
||||
"h-full rounded-[inherit] outline-none transition-shadows focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-has-overflow-x:overscroll-x-contain",
|
||||
scrollFade &&
|
||||
"mask-t-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-start)))] mask-b-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-end)))] mask-l-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-start)))] mask-r-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-end)))] [--fade-size:1.5rem]",
|
||||
scrollbarGutter &&
|
||||
|
||||
@@ -22,7 +22,7 @@ function SelectTrigger({
|
||||
return (
|
||||
<SelectPrimitive.Trigger
|
||||
className={cn(
|
||||
"relative inline-flex min-h-9 w-full min-w-36 select-none items-center justify-between gap-2 rounded-lg border border-input bg-background bg-clip-padding px-[calc(--spacing(3)-1px)] text-left text-base shadow-xs outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 data-disabled:pointer-events-none data-disabled:opacity-64 sm:min-h-8 sm:text-sm dark:bg-input/32 dark:not-in-data-[slot=group]:bg-clip-border dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
|
||||
"relative inline-flex min-h-9 w-full min-w-36 select-none items-center justify-center gap-2 rounded-lg border border-input bg-background not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-left text-base shadow-xs/5 outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 data-disabled:pointer-events-none data-disabled:opacity-64 sm:min-h-8 sm:text-sm dark:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
|
||||
size === "sm" &&
|
||||
"min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
|
||||
size === "lg" && "min-h-10 sm:min-h-9",
|
||||
@@ -71,7 +71,7 @@ function SelectPopup({
|
||||
sideOffset={sideOffset}
|
||||
>
|
||||
<SelectPrimitive.Popup
|
||||
className="origin-(--transform-origin) transition-[scale,opacity] has-data-[side=none]:scale-100 has-data-starting-style:scale-98 has-data-starting-style:opacity-0 has-data-[side=none]:transition-none"
|
||||
className="origin-(--transform-origin)"
|
||||
data-slot="select-popup"
|
||||
{...props}
|
||||
>
|
||||
@@ -81,7 +81,7 @@ function SelectPopup({
|
||||
>
|
||||
<ChevronUpIcon className="relative size-4.5 sm:size-4" />
|
||||
</SelectPrimitive.ScrollUpArrow>
|
||||
<span className="relative block h-full rounded-lg border bg-popover bg-clip-padding before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-lg dark:not-in-data-[slot=group]:bg-clip-border">
|
||||
<div className="relative h-full rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]">
|
||||
<SelectPrimitive.List
|
||||
className={cn(
|
||||
"max-h-(--available-height) min-w-(--anchor-width) overflow-y-auto p-1",
|
||||
@@ -91,7 +91,7 @@ function SelectPopup({
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.List>
|
||||
</span>
|
||||
</div>
|
||||
<SelectPrimitive.ScrollDownArrow
|
||||
className="bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover"
|
||||
data-slot="select-scroll-down-arrow"
|
||||
|
||||
@@ -10,7 +10,7 @@ function Separator({
|
||||
return (
|
||||
<SeparatorPrimitive
|
||||
className={cn(
|
||||
"shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch",
|
||||
"shrink-0 bg-input data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch",
|
||||
className,
|
||||
)}
|
||||
data-slot="separator"
|
||||
|
||||
@@ -74,7 +74,7 @@ function SheetPopup({
|
||||
<SheetViewport inset={inset} side={side}>
|
||||
<SheetPrimitive.Popup
|
||||
className={cn(
|
||||
"relative flex max-h-full min-h-0 w-full min-w-0 flex-col bg-popover bg-clip-padding text-popover-foreground shadow-lg transition-[opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:opacity-0 data-starting-style:opacity-0 max-sm:before:hidden dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative flex max-h-full min-h-0 w-full min-w-0 flex-col bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 transition-[opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:opacity-0 data-starting-style:opacity-0 max-sm:before:hidden dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
side === "bottom" &&
|
||||
"row-start-2 border-t data-ending-style:translate-y-8 data-starting-style:translate-y-8",
|
||||
side === "top" &&
|
||||
@@ -130,7 +130,7 @@ function SheetFooter({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end",
|
||||
variant === "default" && "border-t bg-muted/50 py-4",
|
||||
variant === "default" && "border-t bg-muted/72 py-4",
|
||||
variant === "bare" &&
|
||||
"in-[[data-slot=sheet-popup]:has([data-slot=sheet-panel])]:pt-3 pt-4 pb-6",
|
||||
className,
|
||||
@@ -144,7 +144,10 @@ function SheetFooter({
|
||||
function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
|
||||
return (
|
||||
<SheetPrimitive.Title
|
||||
className={cn("font-heading text-xl leading-none", className)}
|
||||
className={cn(
|
||||
"font-heading font-semibold text-xl leading-none",
|
||||
className,
|
||||
)}
|
||||
data-slot="sheet-title"
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useIsMobile } from "@coss/ui/hooks/use-mobile";
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
import { Button } from "@coss/ui/components/button";
|
||||
import { Input } from "@coss/ui/components/input";
|
||||
import { ScrollArea } from "@coss/ui/components/scroll-area";
|
||||
import { Separator } from "@coss/ui/components/separator";
|
||||
import {
|
||||
Sheet,
|
||||
@@ -245,7 +246,7 @@ function Sidebar({
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
|
||||
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm/5"
|
||||
data-sidebar="sidebar"
|
||||
data-slot="sidebar-inner"
|
||||
>
|
||||
@@ -313,7 +314,7 @@ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
|
||||
<main
|
||||
className={cn(
|
||||
"relative flex w-full flex-1 flex-col bg-background",
|
||||
"md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2 md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm",
|
||||
"md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2 md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm/5",
|
||||
className,
|
||||
)}
|
||||
data-slot="sidebar-inset"
|
||||
@@ -374,15 +375,20 @@ function SidebarSeparator({
|
||||
|
||||
function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
||||
className,
|
||||
)}
|
||||
data-sidebar="content"
|
||||
data-slot="sidebar-content"
|
||||
{...props}
|
||||
/>
|
||||
<ScrollArea
|
||||
className="**:data-[slot=scroll-area-scrollbar]:hidden"
|
||||
scrollFade
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"flex min-h-0 flex-1 flex-col gap-2 group-data-[collapsible=icon]:overflow-hidden",
|
||||
className,
|
||||
)}
|
||||
data-sidebar="content"
|
||||
data-slot="sidebar-content"
|
||||
{...props}
|
||||
/>
|
||||
</ScrollArea>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ function Slider({
|
||||
/>
|
||||
{Array.from({ length: _values.length }, (_, index) => (
|
||||
<SliderPrimitive.Thumb
|
||||
className="block size-5 shrink-0 select-none rounded-full border border-input bg-white bg-clip-padding shadow-xs outline-none transition-shadow before:absolute before:inset-0 before:rounded-full before:shadow-[0_1px_--theme(--color-black/4%)] focus-visible:ring-[3px] focus-visible:ring-ring/24 has-focus-visible:ring-[3px] has-focus-visible:ring-ring/24 data-dragging:ring-[3px] data-dragging:ring-ring/24 sm:size-4 dark:border-background dark:bg-clip-border dark:data-dragging:ring-ring/48 dark:focus-visible:ring-ring/48 [:focus-visible,[data-dragging]]:shadow-none"
|
||||
className="block size-5 shrink-0 select-none rounded-full border border-input bg-white not-dark:bg-clip-padding shadow-xs/5 outline-none transition-[box-shadow,scale] before:absolute before:inset-0 before:rounded-full before:shadow-[0_1px_--theme(--color-black/6%)] focus-visible:ring-[3px] focus-visible:ring-ring/24 has-focus-visible:ring-[3px] has-focus-visible:ring-ring/24 data-dragging:scale-120 data-dragging:ring-[3px] data-dragging:ring-ring/24 sm:size-4 dark:border-background dark:data-dragging:ring-ring/48 dark:focus-visible:ring-ring/48 [:focus-visible,[data-dragging]]:shadow-none"
|
||||
data-slot="slider-thumb"
|
||||
key={String(index)}
|
||||
/>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Loader2Icon } from "lucide-react";
|
||||
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
|
||||
function Spinner({ className, ...props }: React.ComponentProps<typeof Loader2Icon>) {
|
||||
function Spinner({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Loader2Icon>) {
|
||||
return (
|
||||
<Loader2Icon
|
||||
aria-label="Loading"
|
||||
|
||||
@@ -8,7 +8,7 @@ function Switch({ className, ...props }: SwitchPrimitive.Root.Props) {
|
||||
return (
|
||||
<SwitchPrimitive.Root
|
||||
className={cn(
|
||||
"group/switch inset-shadow-[0_1px_--theme(--color-black/4%)] inline-flex h-5.5 w-9.5 shrink-0 items-center rounded-full p-px outline-none transition-all focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input data-disabled:opacity-64 sm:h-4.5 sm:w-7.5",
|
||||
"inset-shadow-[0_1px_--theme(--color-black/6%)] inline-flex h-[calc(var(--thumb-size)+2px)] w-[calc(var(--thumb-size)*2-2px)] shrink-0 items-center rounded-full p-px outline-none transition-[background-color,box-shadow] duration-200 [--thumb-size:--spacing(5)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input data-disabled:opacity-64 sm:[--thumb-size:--spacing(4)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="switch"
|
||||
@@ -16,7 +16,7 @@ function Switch({ className, ...props }: SwitchPrimitive.Root.Props) {
|
||||
>
|
||||
<SwitchPrimitive.Thumb
|
||||
className={cn(
|
||||
"pointer-events-none block size-5 rounded-full bg-background shadow-sm transition-[translate,width] group-active/switch:not-data-disabled:w-5.5 data-checked:translate-x-4 data-unchecked:translate-x-0 data-checked:group-active/switch:translate-x-3.5 sm:size-4 sm:data-checked:translate-x-3 sm:group-active/switch:not-data-disabled:w-4.5 sm:data-checked:group-active/switch:translate-x-2.5",
|
||||
"pointer-events-none block aspect-square h-full origin-left in-[[role=switch]:active,[data-slot=label]:active]:not-data-disabled:scale-x-110 in-[[role=switch]:active,[data-slot=label]:active]:rounded-[var(--thumb-size)/calc(var(--thumb-size)*1.1)] rounded-(--thumb-size) bg-background shadow-sm/5 will-change-transform [transition:translate_.15s,border-radius_.15s,scale_.1s_.1s,transform-origin_.15s] data-checked:origin-[var(--thumb-size)_50%] data-checked:translate-x-[calc(var(--thumb-size)-4px)]",
|
||||
)}
|
||||
data-slot="switch-thumb"
|
||||
/>
|
||||
|
||||
@@ -37,7 +37,7 @@ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
||||
return (
|
||||
<tbody
|
||||
className={cn(
|
||||
"relative in-data-[slot=frame]:rounded-xl in-data-[slot=frame]:shadow-xs before:pointer-events-none before:absolute before:inset-px not-in-data-[slot=frame]:before:hidden before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_tr:last-child]:border-0 in-data-[slot=frame]:*:[tr]:border-0 in-data-[slot=frame]:*:[tr]:*:[td]:border-b in-data-[slot=frame]:*:[tr]:*:[td]:bg-background in-data-[slot=frame]:*:[tr]:*:[td]:bg-clip-padding in-data-[slot=frame]:*:[tr]:first:*:[td]:first:rounded-ss-xl in-data-[slot=frame]:*:[tr]:*:[td]:first:border-s in-data-[slot=frame]:*:[tr]:first:*:[td]:border-t in-data-[slot=frame]:*:[tr]:last:*:[td]:last:rounded-ee-xl in-data-[slot=frame]:*:[tr]:*:[td]:last:border-e in-data-[slot=frame]:*:[tr]:first:*:[td]:last:rounded-se-xl in-data-[slot=frame]:*:[tr]:last:*:[td]:first:rounded-es-xl in-data-[slot=frame]:*:[tr]:hover:*:[td]:bg-transparent in-data-[slot=frame]:*:[tr]:data-[state=selected]:*:[td]:bg-muted/50",
|
||||
"relative in-data-[slot=frame]:rounded-xl in-data-[slot=frame]:shadow-xs/5 before:pointer-events-none before:absolute before:inset-px not-in-data-[slot=frame]:before:hidden before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/8%)] [&_tr:last-child]:border-0 in-data-[slot=frame]:*:[tr]:border-0 in-data-[slot=frame]:*:[tr]:*:[td]:border-b in-data-[slot=frame]:*:[tr]:*:[td]:bg-background in-data-[slot=frame]:*:[tr]:*:[td]:bg-clip-padding in-data-[slot=frame]:*:[tr]:first:*:[td]:first:rounded-ss-xl in-data-[slot=frame]:*:[tr]:*:[td]:first:border-s in-data-[slot=frame]:*:[tr]:first:*:[td]:border-t in-data-[slot=frame]:*:[tr]:last:*:[td]:last:rounded-ee-xl in-data-[slot=frame]:*:[tr]:*:[td]:last:border-e in-data-[slot=frame]:*:[tr]:first:*:[td]:last:rounded-se-xl in-data-[slot=frame]:*:[tr]:last:*:[td]:first:rounded-es-xl in-data-[slot=frame]:*:[tr]:hover:*:[td]:bg-transparent in-data-[slot=frame]:*:[tr]:data-[state=selected]:*:[td]:bg-muted/72",
|
||||
className,
|
||||
)}
|
||||
data-slot="table-body"
|
||||
@@ -50,7 +50,7 @@ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
||||
return (
|
||||
<tfoot
|
||||
className={cn(
|
||||
"border-t in-data-[slot=frame]:border-none bg-muted/50 in-data-[slot=frame]:bg-transparent font-medium [&>tr]:last:border-b-0 in-data-[slot=frame]:*:[tr]:hover:bg-transparent",
|
||||
"border-t in-data-[slot=frame]:border-none bg-muted/72 in-data-[slot=frame]:bg-transparent font-medium [&>tr]:last:border-b-0 in-data-[slot=frame]:*:[tr]:hover:bg-transparent",
|
||||
className,
|
||||
)}
|
||||
data-slot="table-footer"
|
||||
@@ -63,7 +63,7 @@ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
||||
return (
|
||||
<tr
|
||||
className={cn(
|
||||
"border-b transition-colors hover:bg-muted/50 in-data-[slot=frame]:hover:bg-transparent data-[state=selected]:bg-muted/50 in-data-[slot=frame]:data-[state=selected]:bg-transparent",
|
||||
"border-b transition-colors hover:bg-muted/72 in-data-[slot=frame]:hover:bg-transparent data-[state=selected]:bg-muted/72 in-data-[slot=frame]:data-[state=selected]:bg-transparent",
|
||||
className,
|
||||
)}
|
||||
data-slot="table-row"
|
||||
@@ -76,7 +76,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
||||
return (
|
||||
<th
|
||||
className={cn(
|
||||
"h-10 whitespace-nowrap px-2 text-left align-middle font-medium text-muted-foreground has-[[role=checkbox]]:w-px has-[[role=checkbox]]:pe-0 *:[[role=checkbox]]:translate-y-0.5",
|
||||
"h-10 whitespace-nowrap px-2.5 text-left align-middle font-medium text-muted-foreground leading-none has-[[role=checkbox]]:w-px has-[[role=checkbox]]:pe-0",
|
||||
className,
|
||||
)}
|
||||
data-slot="table-head"
|
||||
@@ -89,7 +89,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||
return (
|
||||
<td
|
||||
className={cn(
|
||||
"whitespace-nowrap p-2 align-middle has-[[role=checkbox]]:pe-0 *:[[role=checkbox]]:translate-y-0.5",
|
||||
"whitespace-nowrap p-2.5 align-middle leading-none in-data-[slot=frame]:first:p-[calc(--spacing(2.5)-1px)] in-data-[slot=frame]:last:p-[calc(--spacing(2.5)-1px)] has-[[role=checkbox]]:pe-0",
|
||||
className,
|
||||
)}
|
||||
data-slot="table-cell"
|
||||
|
||||
@@ -34,7 +34,7 @@ function TabsList({
|
||||
"data-[orientation=vertical]:flex-col",
|
||||
variant === "default"
|
||||
? "rounded-lg bg-muted p-0.5 text-muted-foreground/72"
|
||||
: "data-[orientation=vertical]:px-1 data-[orientation=horizontal]:py-1 *:data-[slot=tabs-trigger]:hover:bg-accent",
|
||||
: "data-[orientation=vertical]:px-1 data-[orientation=horizontal]:py-1 *:data-[slot=tabs-tab]:hover:bg-accent",
|
||||
className,
|
||||
)}
|
||||
data-slot="tabs-list"
|
||||
@@ -46,7 +46,7 @@ function TabsList({
|
||||
"-translate-y-(--active-tab-bottom) absolute bottom-0 left-0 h-(--active-tab-height) w-(--active-tab-width) translate-x-(--active-tab-left) transition-[width,translate] duration-200 ease-in-out",
|
||||
variant === "underline"
|
||||
? "data-[orientation=vertical]:-translate-x-px z-10 bg-primary data-[orientation=horizontal]:h-0.5 data-[orientation=vertical]:w-0.5 data-[orientation=horizontal]:translate-y-px"
|
||||
: "-z-1 rounded-md bg-background shadow-sm dark:bg-accent",
|
||||
: "-z-1 rounded-md bg-background shadow-sm/5 dark:bg-input",
|
||||
)}
|
||||
data-slot="tab-indicator"
|
||||
/>
|
||||
@@ -58,13 +58,10 @@ function TabsTab({ className, ...props }: TabsPrimitive.Tab.Props) {
|
||||
return (
|
||||
<TabsPrimitive.Tab
|
||||
className={cn(
|
||||
"[&_svg]:-mx-0.5 flex shrink-0 grow cursor-pointer items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base outline-none transition-[color,background-color,box-shadow] focus-visible:ring-2 focus-visible:ring-ring data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
"hover:text-muted-foreground data-active:text-foreground",
|
||||
"h-9 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:h-8",
|
||||
"data-[orientation=vertical]:w-full data-[orientation=vertical]:justify-start",
|
||||
"[&_svg]:-mx-0.5 flex h-9 shrink-0 grow cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-[calc(--spacing(2.5)-1px)] font-medium text-base outline-none transition-[color,background-color,box-shadow] hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring data-disabled:pointer-events-none data-[orientation=vertical]:w-full data-[orientation=vertical]:justify-start data-active:text-foreground data-disabled:opacity-64 sm:h-8 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
className,
|
||||
)}
|
||||
data-slot="tabs-trigger"
|
||||
data-slot="tabs-tab"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@ function Textarea({
|
||||
className={
|
||||
cn(
|
||||
!unstyled &&
|
||||
"relative inline-flex w-full rounded-lg border border-input bg-background bg-clip-padding text-base shadow-xs ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] sm:text-sm dark:bg-input/32 dark:bg-clip-border dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
) || undefined
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ function Toasts({ position = "bottom-right" }: { position: ToastPosition }) {
|
||||
return (
|
||||
<Toast.Root
|
||||
className={cn(
|
||||
"absolute z-[calc(9999-var(--toast-index))] h-(--toast-calc-height) w-full select-none rounded-lg border bg-popover bg-clip-padding text-popover-foreground shadow-lg [transition:transform_.5s_cubic-bezier(.22,1,.36,1),opacity_.5s,height_.15s] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"absolute z-[calc(9999-var(--toast-index))] h-(--toast-calc-height) w-full select-none rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 [transition:transform_.5s_cubic-bezier(.22,1,.36,1),opacity_.5s,height_.15s] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
// Base positioning using data-position
|
||||
"data-[position*=right]:right-0 data-[position*=right]:left-auto",
|
||||
"data-[position*=left]:right-auto data-[position*=left]:left-0",
|
||||
@@ -206,10 +206,10 @@ function AnchoredToasts() {
|
||||
>
|
||||
<Toast.Root
|
||||
className={cn(
|
||||
"relative text-balance border bg-popover bg-clip-padding text-popover-foreground text-xs transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative text-balance border bg-popover not-dark:bg-clip-padding text-popover-foreground text-xs transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
tooltipStyle
|
||||
? "rounded-md shadow-black/5 shadow-md before:rounded-[calc(var(--radius-md)-1px)]"
|
||||
: "rounded-lg shadow-lg before:rounded-[calc(var(--radius-lg)-1px)]",
|
||||
? "rounded-md shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]"
|
||||
: "rounded-lg shadow-lg/5 before:rounded-[calc(var(--radius-lg)-1px)]",
|
||||
)}
|
||||
data-slot="toast-popup"
|
||||
toast={toast}
|
||||
|
||||
@@ -30,15 +30,15 @@ function ToggleGroup({
|
||||
return (
|
||||
<ToggleGroupPrimitive
|
||||
className={cn(
|
||||
"flex w-fit *:focus-visible:z-10",
|
||||
"flex w-fit *:focus-visible:z-10 dark:*:[[data-slot=separator]:has(+[data-slot=toggle]:hover)]:before:bg-input/64 dark:*:[[data-slot=separator]:has(+[data-slot=toggle][data-pressed])]:before:bg-input dark:*:[[data-slot=toggle]:hover+[data-slot=separator]]:before:bg-input/64 dark:*:[[data-slot=toggle][data-pressed]+[data-slot=separator]]:before:bg-input",
|
||||
orientation === "horizontal"
|
||||
? "*:pointer-coarse:after:min-w-auto"
|
||||
: "*:pointer-coarse:after:min-h-auto",
|
||||
variant === "default"
|
||||
? "gap-0.5"
|
||||
: orientation === "horizontal"
|
||||
? "*:not-first:before:-start-[0.5px] *:not-last:before:-end-[0.5px] *:not-first:rounded-s-none *:not-last:rounded-e-none *:not-first:border-s-0 *:not-last:border-e-0 *:not-first:before:rounded-s-none *:not-last:before:rounded-e-none"
|
||||
: "*:not-first:before:-top-[0.5px] *:not-last:before:-bottom-[0.5px] flex-col *:not-first:rounded-t-none *:not-last:rounded-b-none *:not-first:border-t-0 *:not-last:border-b-0 *:not-last:before:hidden *:not-first:before:rounded-t-none *:not-last:before:rounded-b-none dark:*:last:before:hidden dark:*:first:before:block",
|
||||
? "*:not-first:not-data-[slot=separator]:before:-start-[0.5px] *:not-last:not-data-[slot=separator]:before:-end-[0.5px] *:not-first:rounded-s-none *:not-last:rounded-e-none *:not-first:border-s-0 *:not-last:border-e-0 *:not-first:before:rounded-s-none *:not-last:before:rounded-e-none"
|
||||
: "*:not-first:not-data-[slot=separator]:before:-top-[0.5px] *:not-last:not-data-[slot=separator]:before:-bottom-[0.5px] flex-col *:not-first:rounded-t-none *:not-last:rounded-b-none *:not-first:border-t-0 *:not-last:border-b-0 *:not-first:before:rounded-t-none *:not-last:before:rounded-b-none *:data-[slot=toggle]:not-last:before:hidden dark:*:last:before:hidden dark:*:first:before:block",
|
||||
className,
|
||||
)}
|
||||
data-size={size}
|
||||
@@ -88,7 +88,14 @@ function ToggleGroupSeparator({
|
||||
className?: string;
|
||||
} & React.ComponentProps<typeof Separator>) {
|
||||
return (
|
||||
<Separator className={className} orientation={orientation} {...props} />
|
||||
<Separator
|
||||
className={cn(
|
||||
"pointer-events-none relative before:absolute before:inset-0 dark:before:bg-input/32",
|
||||
className,
|
||||
)}
|
||||
orientation={orientation}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@coss/ui/lib/utils";
|
||||
|
||||
const toggleVariants = cva(
|
||||
"[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent/50 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-pressed:bg-accent data-pressed:text-accent-foreground data-pressed:transition-none sm:text-sm dark:data-pressed:bg-input/80 dark:hover:bg-accent [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
"[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-pressed:bg-input/64 data-pressed:text-accent-foreground sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
{
|
||||
defaultVariants: {
|
||||
size: "default",
|
||||
@@ -21,7 +21,7 @@ const toggleVariants = cva(
|
||||
variant: {
|
||||
default: "border-transparent",
|
||||
outline:
|
||||
"border-border bg-clip-padding shadow-xs not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:hover:bg-input/64 dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/8%)] dark:not-disabled:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/4%)] [:disabled,:active,[data-pressed]]:shadow-none",
|
||||
"border-input bg-background not-dark:bg-clip-padding shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:data-pressed:bg-input dark:hover:bg-input/64 dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:not-disabled:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/2%)] [:disabled,:active,[data-pressed]]:shadow-none",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@ function Toolbar({ className, ...props }: ToolbarPrimitive.Root.Props) {
|
||||
return (
|
||||
<ToolbarPrimitive.Root
|
||||
className={cn(
|
||||
"relative flex gap-2 rounded-xl border bg-card bg-clip-padding p-1 text-card-foreground",
|
||||
"relative flex gap-2 rounded-xl border bg-card not-dark:bg-clip-padding p-1 text-card-foreground",
|
||||
className,
|
||||
)}
|
||||
data-slot="toolbar"
|
||||
|
||||
@@ -37,7 +37,7 @@ function TooltipPopup({
|
||||
>
|
||||
<TooltipPrimitive.Popup
|
||||
className={cn(
|
||||
"relative flex h-(--popup-height,auto) w-(--popup-width,auto) origin-(--transform-origin) text-balance rounded-md border bg-popover bg-clip-padding text-popover-foreground text-xs shadow-black/5 shadow-md transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-md)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 data-instant:duration-0 dark:bg-clip-border dark:before:shadow-[0_-1px_--theme(--color-white/8%)]",
|
||||
"relative flex h-(--popup-height,auto) w-(--popup-width,auto) origin-(--transform-origin) text-balance rounded-md border bg-popover not-dark:bg-clip-padding text-popover-foreground text-xs shadow-md/5 transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-md)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 data-instant:duration-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
||||
className,
|
||||
)}
|
||||
data-slot="tooltip-popup"
|
||||
|
||||
Reference in new issue
Block a user