Skip to content

Commit 950f955

Browse files
fix(ui): update coss ui components (calcom#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>
1 parent d137787 commit 950f955

40 files changed

Lines changed: 720 additions & 223 deletions

packages/coss-ui/src/components/accordion.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ function AccordionTrigger({
2828
<AccordionPrimitive.Header className="flex">
2929
<AccordionPrimitive.Trigger
3030
className={cn(
31-
"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",
31+
"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",
3232
className,
3333
)}
3434
data-slot="accordion-trigger"
3535
{...props}
3636
>
3737
{children}
38-
<ChevronDownIcon className="pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-80 transition-transform duration-200 ease-in-out" />
38+
<ChevronDownIcon
39+
className="pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-80 transition-transform duration-200 ease-in-out"
40+
data-slot="accordion-indicator"
41+
/>
3942
</AccordionPrimitive.Trigger>
4043
</AccordionPrimitive.Header>
4144
);

packages/coss-ui/src/components/alert-dialog.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog
44

55
import { cn } from "@coss/ui/lib/utils";
66

7+
const AlertDialogCreateHandle = AlertDialogPrimitive.createHandle;
8+
79
const AlertDialog = AlertDialogPrimitive.Root;
810

911
const AlertDialogPortal = AlertDialogPrimitive.Portal;
@@ -37,7 +39,7 @@ function AlertDialogViewport({
3739
return (
3840
<AlertDialogPrimitive.Viewport
3941
className={cn(
40-
"fixed inset-0 z-50 grid grid-rows-[1fr_auto] justify-items-center pt-6 sm:grid-rows-[1fr_auto_3fr] sm:p-4",
42+
"fixed inset-0 z-50 grid grid-rows-[1fr_auto_3fr] justify-items-center p-4",
4143
className,
4244
)}
4345
data-slot="alert-dialog-viewport"
@@ -48,15 +50,25 @@ function AlertDialogViewport({
4850

4951
function AlertDialogPopup({
5052
className,
53+
bottomStickOnMobile = true,
5154
...props
52-
}: AlertDialogPrimitive.Popup.Props) {
55+
}: AlertDialogPrimitive.Popup.Props & {
56+
bottomStickOnMobile?: boolean;
57+
}) {
5358
return (
5459
<AlertDialogPortal>
5560
<AlertDialogBackdrop />
56-
<AlertDialogViewport>
61+
<AlertDialogViewport
62+
className={cn(
63+
bottomStickOnMobile &&
64+
"max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12",
65+
)}
66+
>
5767
<AlertDialogPrimitive.Popup
5868
className={cn(
59-
"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%)]",
69+
"-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%)]",
70+
bottomStickOnMobile &&
71+
"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",
6072
className,
6173
)}
6274
data-slot="alert-dialog-popup"
@@ -94,7 +106,7 @@ function AlertDialogFooter({
94106
<div
95107
className={cn(
96108
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]",
97-
variant === "default" && "border-t bg-muted/50 py-4",
109+
variant === "default" && "border-t bg-muted/72 py-4",
98110
variant === "bare" && "pt-4 pb-6",
99111
className,
100112
)}
@@ -110,7 +122,10 @@ function AlertDialogTitle({
110122
}: AlertDialogPrimitive.Title.Props) {
111123
return (
112124
<AlertDialogPrimitive.Title
113-
className={cn("font-heading text-xl leading-none", className)}
125+
className={cn(
126+
"font-heading font-semibold text-xl leading-none",
127+
className,
128+
)}
114129
data-slot="alert-dialog-title"
115130
{...props}
116131
/>
@@ -137,6 +152,7 @@ function AlertDialogClose(props: AlertDialogPrimitive.Close.Props) {
137152
}
138153

139154
export {
155+
AlertDialogCreateHandle,
140156
AlertDialog,
141157
AlertDialogPortal,
142158
AlertDialogBackdrop,

packages/coss-ui/src/components/autocomplete.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,40 @@ function AutocompleteInput({
1313
className,
1414
showTrigger = false,
1515
showClear = false,
16+
startAddon,
1617
size,
1718
...props
1819
}: Omit<AutocompletePrimitive.Input.Props, "size"> & {
1920
showTrigger?: boolean;
2021
showClear?: boolean;
22+
startAddon?: React.ReactNode;
2123
size?: "sm" | "default" | "lg" | number;
24+
ref?: React.Ref<HTMLInputElement>;
2225
}) {
2326
const sizeValue = (size ?? "default") as "sm" | "default" | "lg" | number;
2427

2528
return (
26-
<div className="relative w-full">
29+
<div className="relative not-has-[>*.w-full]:w-fit w-full has-disabled:opacity-64">
30+
{startAddon && (
31+
<div
32+
aria-hidden="true"
33+
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"
34+
data-slot="autocomplete-start-addon"
35+
>
36+
{startAddon}
37+
</div>
38+
)}
2739
<AutocompletePrimitive.Input
2840
className={cn(
41+
startAddon &&
42+
"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)]",
2943
sizeValue === "sm"
3044
? "has-[+[data-slot=autocomplete-trigger],+[data-slot=autocomplete-clear]]:*:data-[slot=autocomplete-input]:pe-6.5"
3145
: "has-[+[data-slot=autocomplete-trigger],+[data-slot=autocomplete-clear]]:*:data-[slot=autocomplete-input]:pe-7",
3246
className,
3347
)}
3448
data-slot="autocomplete-input"
35-
render={<Input size={sizeValue} />}
49+
render={<Input nativeInput size={sizeValue} />}
3650
{...props}
3751
/>
3852
{showTrigger && (
@@ -76,7 +90,7 @@ function AutocompletePopup({
7690
>
7791
<span
7892
className={cn(
79-
"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",
93+
"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%)]",
8094
className,
8195
)}
8296
>
@@ -131,7 +145,7 @@ function AutocompleteGroup({
131145
}: AutocompletePrimitive.Group.Props) {
132146
return (
133147
<AutocompletePrimitive.Group
134-
className={className}
148+
className={cn("[[role=group]+&]:mt-1.5", className)}
135149
data-slot="autocomplete-group"
136150
{...props}
137151
/>
@@ -197,7 +211,7 @@ function AutocompleteList({
197211
<ScrollArea scrollbarGutter scrollFade>
198212
<AutocompletePrimitive.List
199213
className={cn(
200-
"not-empty:scroll-py-1 not-empty:px-1 not-empty:py-1 in-data-has-overflow-y:pe-3",
214+
"not-empty:scroll-py-1 not-empty:p-1 in-data-has-overflow-y:pe-3",
201215
className,
202216
)}
203217
data-slot="autocomplete-list"
@@ -265,6 +279,8 @@ function AutocompleteTrigger({
265279
);
266280
}
267281

282+
const useAutocompleteFilter = AutocompletePrimitive.useFilter;
283+
268284
export {
269285
Autocomplete,
270286
AutocompleteInput,
@@ -281,4 +297,5 @@ export {
281297
AutocompleteStatus,
282298
AutocompleteRow,
283299
AutocompleteCollection,
300+
useAutocompleteFilter,
284301
};

packages/coss-ui/src/components/badge.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import { mergeProps } from "@base-ui/react/merge-props";
24
import { useRender } from "@base-ui/react/use-render";
35
import { cva, type VariantProps } from "class-variance-authority";
@@ -27,7 +29,7 @@ const badgeVariants = cva(
2729
"bg-destructive/8 text-destructive-foreground dark:bg-destructive/16",
2830
info: "bg-info/8 text-info-foreground dark:bg-info/16",
2931
outline:
30-
"border-border bg-transparent dark:bg-input/32 [button,a&]:hover:bg-accent/50 dark:[button,a&]:hover:bg-input/48",
32+
"border-input bg-background dark:bg-input/32 [button,a&]:hover:bg-accent/50 dark:[button,a&]:hover:bg-input/48",
3133
secondary:
3234
"bg-secondary text-secondary-foreground [button,a&]:hover:bg-secondary/90",
3335
success: "bg-success/8 text-success-foreground dark:bg-success/16",

packages/coss-ui/src/components/breadcrumb.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import { mergeProps } from "@base-ui/react/merge-props";
24
import { useRender } from "@base-ui/react/use-render";
35
import { ChevronRight, MoreHorizontal } from "lucide-react";
@@ -14,7 +16,7 @@ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
1416
<ol
1517
className={cn(
1618
"wrap-break-word flex flex-wrap items-center gap-1.5 text-muted-foreground text-sm sm:gap-2.5",
17-
className
19+
className,
1820
)}
1921
data-slot="breadcrumb-list"
2022
{...props}
@@ -51,6 +53,7 @@ function BreadcrumbLink({
5153

5254
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
5355
return (
56+
// biome-ignore lint(a11y/useFocusableInteractive): known
5457
<span
5558
aria-current="page"
5659
aria-disabled="true"

packages/coss-ui/src/components/button.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import { mergeProps } from "@base-ui/react/merge-props";
24
import { useRender } from "@base-ui/react/use-render";
35
import { cva, type VariantProps } from "class-variance-authority";
@@ -29,17 +31,18 @@ const buttonVariants = cva(
2931
},
3032
variant: {
3133
default:
32-
"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",
34+
"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",
3335
destructive:
34-
"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",
36+
"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",
3537
"destructive-outline":
36-
"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",
37-
ghost: "border-transparent hover:bg-accent data-pressed:bg-accent",
38-
link: "border-transparent underline-offset-4 hover:underline",
38+
"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",
39+
ghost:
40+
"border-transparent data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
41+
link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
3942
outline:
40-
"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",
43+
"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",
4144
secondary:
42-
"border-secondary bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90",
45+
"border-transparent bg-secondary text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80 [:hover,[data-pressed]]:bg-secondary/90",
4346
},
4447
},
4548
},

0 commit comments

Comments
 (0)