@trycompai/design-system 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ import * as React from 'react';
|
|
|
5
5
|
import { Spinner } from './spinner';
|
|
6
6
|
|
|
7
7
|
const buttonVariants = cva(
|
|
8
|
-
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent text-
|
|
8
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent text-[13px] font-medium leading-none [text-box-trim:both] [text-box-edge:cap_alphabetic] focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all duration-200 ease-out active:scale-[0.97] active:duration-75 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none cursor-pointer",
|
|
9
9
|
{
|
|
10
10
|
variants: {
|
|
11
11
|
variant: {
|
|
@@ -16,7 +16,7 @@ const buttonVariants = cva(
|
|
|
16
16
|
secondary:
|
|
17
17
|
'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',
|
|
18
18
|
ghost:
|
|
19
|
-
'hover:bg-
|
|
19
|
+
'hover:bg-accent hover:text-foreground dark:hover:bg-accent/50 aria-expanded:bg-accent aria-expanded:text-foreground',
|
|
20
20
|
destructive:
|
|
21
21
|
'bg-destructive/10 text-destructive hover:bg-destructive/15 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 focus-visible:border-destructive/40 dark:bg-destructive/20 dark:hover:bg-destructive/30',
|
|
22
22
|
link: 'text-primary underline-offset-4 hover:underline',
|
|
@@ -27,21 +27,21 @@ const buttonVariants = cva(
|
|
|
27
27
|
},
|
|
28
28
|
size: {
|
|
29
29
|
default:
|
|
30
|
-
'h-
|
|
31
|
-
xs: "h-
|
|
32
|
-
sm: "h-
|
|
33
|
-
lg: 'h-
|
|
34
|
-
icon: 'size-
|
|
30
|
+
'h-7 gap-1 px-2 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5',
|
|
31
|
+
xs: "h-5 gap-0.5 px-1.5 text-[11px] has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 [&_svg:not([class*='size-'])]:size-3",
|
|
32
|
+
sm: "h-6 gap-1 px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
33
|
+
lg: 'h-8 gap-1 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
|
|
34
|
+
icon: 'size-7',
|
|
35
35
|
'icon-xs':
|
|
36
|
-
"size-
|
|
36
|
+
"size-5 [&_svg:not([class*='size-'])]:size-3",
|
|
37
37
|
'icon-sm':
|
|
38
|
-
'size-
|
|
39
|
-
'icon-lg': 'size-
|
|
38
|
+
'size-6',
|
|
39
|
+
'icon-lg': 'size-8',
|
|
40
40
|
// Round icon buttons - for avatar triggers and circular icons
|
|
41
|
-
'icon-round': 'size-
|
|
42
|
-
'icon-round-xs': "size-
|
|
43
|
-
'icon-round-sm': 'size-
|
|
44
|
-
'icon-round-lg': 'size-
|
|
41
|
+
'icon-round': 'size-7 rounded-full',
|
|
42
|
+
'icon-round-xs': "size-5 rounded-full [&_svg:not([class*='size-'])]:size-3",
|
|
43
|
+
'icon-round-sm': 'size-6 rounded-full',
|
|
44
|
+
'icon-round-lg': 'size-8 rounded-full',
|
|
45
45
|
// Calendar day button - special size for calendar day cells
|
|
46
46
|
'calendar-day': [
|
|
47
47
|
// Base sizing
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
+
import { ArrowLeft } from '@carbon/icons-react';
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
|
|
3
4
|
import { Heading } from '../atoms/heading';
|
|
4
|
-
import {
|
|
5
|
-
import { Stack } from '../atoms/stack';
|
|
5
|
+
import { Breadcrumb, type BreadcrumbItemData } from './breadcrumb';
|
|
6
6
|
|
|
7
7
|
interface PageHeaderProps extends Omit<React.ComponentProps<'div'>, 'className'> {
|
|
8
8
|
title: string;
|
|
9
|
-
description?: string;
|
|
10
|
-
/** Additional descriptive text below description */
|
|
11
|
-
meta?: string;
|
|
12
9
|
actions?: React.ReactNode;
|
|
10
|
+
/** Breadcrumb items to display above the title */
|
|
11
|
+
breadcrumbs?: BreadcrumbItemData[];
|
|
12
|
+
/** Back button href - displays a back arrow link above the title */
|
|
13
|
+
backHref?: string;
|
|
14
|
+
/** Back button label (default: "Back") */
|
|
15
|
+
backLabel?: string;
|
|
16
|
+
/** Tabs to display below the header (typically TabsList) */
|
|
17
|
+
tabs?: React.ReactNode;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
function PageHeader({ title,
|
|
20
|
+
function PageHeader({ title, actions, breadcrumbs, backHref, backLabel = 'Back', tabs, children, ...props }: PageHeaderProps) {
|
|
16
21
|
const childArray = React.Children.toArray(children);
|
|
17
22
|
const extractedActionChildren: React.ReactNode[] = [];
|
|
18
|
-
const nonActionChildren: React.ReactNode[] = [];
|
|
19
23
|
|
|
20
24
|
childArray.forEach((child) => {
|
|
21
25
|
if (
|
|
@@ -25,9 +29,7 @@ function PageHeader({ title, description, meta, actions, children, ...props }: P
|
|
|
25
29
|
(child.type as unknown as { __pageHeaderSlot?: string }).__pageHeaderSlot === 'actions'))
|
|
26
30
|
) {
|
|
27
31
|
extractedActionChildren.push((child.props as { children?: React.ReactNode }).children);
|
|
28
|
-
return;
|
|
29
32
|
}
|
|
30
|
-
nonActionChildren.push(child);
|
|
31
33
|
});
|
|
32
34
|
|
|
33
35
|
const resolvedActions =
|
|
@@ -35,46 +37,55 @@ function PageHeader({ title, description, meta, actions, children, ...props }: P
|
|
|
35
37
|
(extractedActionChildren.length > 0 ? extractedActionChildren : undefined);
|
|
36
38
|
|
|
37
39
|
return (
|
|
38
|
-
<div data-slot="page-header" className="flex
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
<div data-slot="page-header" className="flex flex-col gap-1" {...props}>
|
|
41
|
+
{/* Navigation: breadcrumbs or back button */}
|
|
42
|
+
{breadcrumbs && breadcrumbs.length > 0 ? (
|
|
43
|
+
<div className="overflow-hidden">
|
|
44
|
+
<Breadcrumb items={breadcrumbs} separator="chevron" />
|
|
45
|
+
</div>
|
|
46
|
+
) : backHref ? (
|
|
47
|
+
<a
|
|
48
|
+
href={backHref}
|
|
49
|
+
className="inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground hover:underline underline-offset-2 transition-colors w-fit"
|
|
50
|
+
>
|
|
51
|
+
<ArrowLeft className="size-4" />
|
|
52
|
+
<span>{backLabel}</span>
|
|
53
|
+
</a>
|
|
54
|
+
) : null}
|
|
55
|
+
|
|
56
|
+
{/* Main header row */}
|
|
57
|
+
<div className="flex items-center justify-between gap-4 min-w-0">
|
|
58
|
+
<div className="min-w-0 flex-1 truncate">
|
|
59
|
+
<Heading level="1">{title}</Heading>
|
|
60
|
+
</div>
|
|
61
|
+
{resolvedActions && (
|
|
62
|
+
<div className="shrink-0">
|
|
63
|
+
{React.isValidElement(resolvedActions) && resolvedActions.type === PageHeaderActions ? (
|
|
64
|
+
resolvedActions
|
|
65
|
+
) : (
|
|
66
|
+
<PageHeaderActions>{resolvedActions}</PageHeaderActions>
|
|
67
|
+
)}
|
|
68
|
+
</div>
|
|
50
69
|
)}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{/* Tabs section */}
|
|
73
|
+
{tabs && (
|
|
74
|
+
<div className="mt-2 -mb-px">
|
|
75
|
+
{tabs}
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
59
78
|
</div>
|
|
60
79
|
);
|
|
61
80
|
}
|
|
62
81
|
|
|
63
|
-
function PageHeaderTitle({ ...props }: Omit<React.ComponentProps<typeof Heading>, 'className'>) {
|
|
64
|
-
return <Heading data-slot="page-header-title" level="1" {...props} />;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function PageHeaderDescription({ ...props }: Omit<React.ComponentProps<typeof Text>, 'className'>) {
|
|
68
|
-
return <Text data-slot="page-header-description" size="sm" variant="muted" {...props} />;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
82
|
function PageHeaderActions({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
72
83
|
return (
|
|
73
|
-
<div data-slot="page-header-actions" className="flex shrink-0 items-center gap-
|
|
84
|
+
<div data-slot="page-header-actions" className="flex shrink-0 items-center gap-2" {...props} />
|
|
74
85
|
);
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
// Mark compound slots so PageHeader can detect them even if module instances differ.
|
|
78
89
|
(PageHeaderActions as unknown as { __pageHeaderSlot?: string }).__pageHeaderSlot = 'actions';
|
|
79
90
|
|
|
80
|
-
export { PageHeader, PageHeaderActions
|
|
91
|
+
export { PageHeader, PageHeaderActions };
|
|
@@ -63,7 +63,7 @@ function TableCell({ ...props }: Omit<React.ComponentProps<'td'>, 'className'>)
|
|
|
63
63
|
return (
|
|
64
64
|
<td
|
|
65
65
|
data-slot="table-cell"
|
|
66
|
-
className="px-3 py-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [[data-variant=bordered]_&]:border-r [[data-variant=bordered]_&]:last:border-r-0"
|
|
66
|
+
className="px-3 py-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [[data-variant=bordered]_&]:border-r [[data-variant=bordered]_&]:last:border-r-0 [&_[data-slot=button]]:relative [&_[data-slot=button]]:z-10"
|
|
67
67
|
{...props}
|
|
68
68
|
/>
|
|
69
69
|
);
|
|
@@ -12,9 +12,9 @@ const pageLayoutVariants = cva('min-h-full bg-background text-foreground', {
|
|
|
12
12
|
},
|
|
13
13
|
padding: {
|
|
14
14
|
none: '',
|
|
15
|
-
sm: 'px-4
|
|
16
|
-
default: 'px-4
|
|
17
|
-
lg: 'px-6
|
|
15
|
+
sm: 'px-4',
|
|
16
|
+
default: 'px-4 sm:px-6 lg:px-8',
|
|
17
|
+
lg: 'px-6 sm:px-8 lg:px-12',
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
defaultVariants: {
|