@ciridae/ui 1.0.3 → 1.0.5
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/dist/chat/conversation-source.d.ts +15 -1
- package/dist/chat/describe-tool-call.d.ts +3 -3
- package/dist/chat/describe-tool-call.js +3 -3
- package/dist/chat/message-text.js +2 -2
- package/dist/ciridae.css +16 -4
- package/dist/components/activity-feed.d.ts +1 -0
- package/dist/components/activity-feed.js +1 -0
- package/dist/components/app-frame.d.ts +13 -1
- package/dist/components/app-frame.js +45 -3
- package/dist/components/app-navigation.d.ts +28 -1
- package/dist/components/app-navigation.js +110 -14
- package/dist/components/badge.d.ts +29 -4
- package/dist/components/badge.js +134 -15
- package/dist/components/bulk-action-bar.js +3 -3
- package/dist/components/button.d.ts +10 -3
- package/dist/components/button.js +77 -44
- package/dist/components/calendar.js +44 -17
- package/dist/components/centered-page.js +2 -2
- package/dist/components/chart.d.ts +1 -1
- package/dist/components/chart.js +16 -11
- package/dist/components/chat-client-source.js +47 -6
- package/dist/components/chat-sheet-controller.d.ts +1 -0
- package/dist/components/chat-sheet-controller.js +1 -0
- package/dist/components/chat-sheet.d.ts +10 -2
- package/dist/components/chat-sheet.js +74 -37
- package/dist/components/chat.d.ts +90 -14
- package/dist/components/chat.js +401 -101
- package/dist/components/checkbox-item.d.ts +5 -2
- package/dist/components/checkbox-item.js +9 -5
- package/dist/components/chip.d.ts +5 -0
- package/dist/components/chip.js +27 -1
- package/dist/components/column-settings.js +1 -1
- package/dist/components/command-menu.d.ts +5 -1
- package/dist/components/command-menu.js +98 -32
- package/dist/components/command-palette.d.ts +6 -2
- package/dist/components/command-palette.js +20 -10
- package/dist/components/data-display.d.ts +35 -4
- package/dist/components/data-display.js +138 -19
- package/dist/components/data-grid.d.ts +14 -2
- package/dist/components/data-grid.js +61 -26
- package/dist/components/date-range-picker.js +9 -20
- package/dist/components/drawer.d.ts +5 -0
- package/dist/components/drawer.js +91 -54
- package/dist/components/editable-field.d.ts +17 -3
- package/dist/components/editable-field.js +57 -27
- package/dist/components/email-input.js +6 -5
- package/dist/components/environment-frame.d.ts +1 -1
- package/dist/components/environment-frame.js +37 -6
- package/dist/components/filter-bar.js +39 -28
- package/dist/components/form-controls.d.ts +9 -0
- package/dist/components/form-controls.js +46 -22
- package/dist/components/form-layout.d.ts +7 -3
- package/dist/components/form-layout.js +68 -23
- package/dist/components/glass-menu.d.ts +3 -0
- package/dist/components/glass-menu.js +63 -0
- package/dist/components/gradient-edge.d.ts +9 -0
- package/dist/components/gradient-edge.js +31 -0
- package/dist/components/input.d.ts +4 -2
- package/dist/components/input.js +26 -15
- package/dist/components/keycap.d.ts +9 -5
- package/dist/components/keycap.js +57 -19
- package/dist/components/lightbox.js +2 -1
- package/dist/components/locale.d.ts +10 -0
- package/dist/components/locale.js +18 -2
- package/dist/components/log-entry.d.ts +40 -0
- package/dist/components/log-entry.js +146 -0
- package/dist/components/mention-input.js +4 -3
- package/dist/components/menu.d.ts +6 -2
- package/dist/components/menu.js +34 -37
- package/dist/components/meter.d.ts +9 -1
- package/dist/components/meter.js +64 -6
- package/dist/components/navigation.d.ts +21 -4
- package/dist/components/navigation.js +84 -19
- package/dist/components/notification-tray.js +5 -4
- package/dist/components/overlays.d.ts +3 -1
- package/dist/components/overlays.js +69 -40
- package/dist/components/page-frame.js +1 -1
- package/dist/components/panel.d.ts +1 -1
- package/dist/components/panel.js +18 -12
- package/dist/components/radio-card.js +10 -9
- package/dist/components/record.d.ts +25 -1
- package/dist/components/record.js +147 -18
- package/dist/components/segmented-bar.d.ts +3 -1
- package/dist/components/segmented-bar.js +16 -6
- package/dist/components/select.d.ts +5 -2
- package/dist/components/select.js +103 -127
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +2 -2
- package/dist/components/shell.js +43 -45
- package/dist/components/sidebar.d.ts +7 -2
- package/dist/components/sidebar.js +55 -27
- package/dist/components/single-line-text.d.ts +2 -0
- package/dist/components/single-line-text.js +16 -0
- package/dist/components/site-banner.d.ts +5 -2
- package/dist/components/site-banner.js +17 -6
- package/dist/components/skeleton.d.ts +7 -6
- package/dist/components/skeleton.js +28 -16
- package/dist/components/skeletons.d.ts +12 -0
- package/dist/components/skeletons.js +71 -8
- package/dist/components/stages.d.ts +78 -6
- package/dist/components/stages.js +512 -156
- package/dist/components/stat-card.d.ts +10 -2
- package/dist/components/stat-card.js +92 -37
- package/dist/components/status-banner.js +1 -1
- package/dist/components/tabs.js +26 -13
- package/dist/components/theme-toggle.d.ts +4 -0
- package/dist/components/theme-toggle.js +67 -0
- package/dist/components/toast.d.ts +9 -2
- package/dist/components/toast.js +78 -29
- package/dist/preset.js +291 -33
- package/dist/styled-system/styles.css +3107 -1039
- package/dist/styled-system/tokens/index.mjs +602 -22
- package/dist/styled-system/tokens/tokens.d.ts +11 -11
- package/dist/styled-system/types/prop-type.d.ts +2 -2
- package/dist/styles.css +16 -4
- package/dist/theme/color.d.ts +3 -0
- package/dist/theme/color.js +5 -0
- package/dist/theme/derive.d.ts +9 -2
- package/dist/theme/derive.js +72 -12
- package/dist/theme/palettes.d.ts +49 -6
- package/dist/theme/palettes.js +84 -15
- package/dist/theme/tokens.d.ts +3 -3
- package/dist/theme/tokens.js +108 -32
- package/package.json +9 -1
package/dist/components/shell.js
CHANGED
|
@@ -7,14 +7,13 @@ import { IconButton, IconButtonSizeContext } from "./button.js";
|
|
|
7
7
|
import { PageHotkeys, useHotkey } from "./hotkeys.js";
|
|
8
8
|
import { icon } from "./icon.js";
|
|
9
9
|
import { useCiridaeLocale } from "./locale.js";
|
|
10
|
+
import { singleLineTextClass } from "./single-line-text.js";
|
|
10
11
|
// The sidebar sits flush against the window; only the main panel is inset from the edges.
|
|
11
12
|
const shell = css({
|
|
12
13
|
display: "flex",
|
|
13
14
|
height: "100dvh",
|
|
14
|
-
paddingBlock: "panel.compact",
|
|
15
|
-
paddingInlineEnd: "panel.compact",
|
|
16
15
|
overflow: "hidden",
|
|
17
|
-
background: "
|
|
16
|
+
background: "token(gradients.canvas)",
|
|
18
17
|
color: "fg.primary",
|
|
19
18
|
// Compact line height leaves clipped text room for its descenders throughout the app frame.
|
|
20
19
|
textStyle: "body",
|
|
@@ -23,26 +22,23 @@ const shell = css({
|
|
|
23
22
|
const sidebar = css({
|
|
24
23
|
display: "flex",
|
|
25
24
|
flexDirection: "column",
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// line beside it: half the difference, plus the main panel's 1px edge.
|
|
30
|
-
// The last row, the account, mirrors it at the foot: as far inside the main panel's bottom edge
|
|
31
|
-
// as the first row sits inside its top.
|
|
32
|
-
_notPhone: {
|
|
33
|
-
paddingBlock: "calc((token(sizes.shell.header) - token(sizes.control.default)) / 2 + 1px)",
|
|
34
|
-
},
|
|
25
|
+
// Between the navigation and the footer; the navigation's own groups stand `sidebar.groupGap` apart.
|
|
26
|
+
gap: "sidebar.footerGap",
|
|
27
|
+
paddingBlock: "sidebar.block",
|
|
35
28
|
paddingInline: "sidebar.inline",
|
|
36
29
|
width: "shell.sidebar",
|
|
37
30
|
flexShrink: "0",
|
|
38
31
|
overflowY: "auto",
|
|
39
32
|
// The rail swaps every expanded control for its `data-compact-sidebar` icon twin.
|
|
40
33
|
"& [data-compact-sidebar]": { display: "none" },
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
// A phone's menu always shows the labelled navigation, whatever the desktop sidebar's state.
|
|
35
|
+
_notPhone: {
|
|
36
|
+
"&[data-collapsed]": {
|
|
37
|
+
width: "shell.collapsed",
|
|
38
|
+
alignItems: "center",
|
|
39
|
+
"& [data-expanded-sidebar]": { display: "none" },
|
|
40
|
+
"& [data-compact-sidebar]": { display: "flex" },
|
|
41
|
+
},
|
|
46
42
|
},
|
|
47
43
|
_rail: {
|
|
48
44
|
width: "shell.collapsed",
|
|
@@ -62,7 +58,7 @@ const sidebar = css({
|
|
|
62
58
|
zIndex: "drawer",
|
|
63
59
|
width: "shell.sidebar",
|
|
64
60
|
alignItems: "stretch",
|
|
65
|
-
background: "
|
|
61
|
+
background: "token(gradients.canvas)",
|
|
66
62
|
borderInlineEnd: "1px solid token(colors.border.panel)",
|
|
67
63
|
boxShadow: "card",
|
|
68
64
|
transform: "translateX(-100%)",
|
|
@@ -89,12 +85,15 @@ const main = css({
|
|
|
89
85
|
flexDirection: "column",
|
|
90
86
|
flex: "1",
|
|
91
87
|
minWidth: "0",
|
|
92
|
-
|
|
88
|
+
marginBlock: "panel.compact",
|
|
89
|
+
marginInlineEnd: "panel.compact",
|
|
90
|
+
border: "1px solid token(colors.border.canvas)",
|
|
93
91
|
borderRadius: "action",
|
|
94
|
-
background: "
|
|
92
|
+
background: "token(gradients.panel)",
|
|
95
93
|
overflow: "hidden",
|
|
96
94
|
// Only once the panel spans the whole window does rounding read as a gap.
|
|
97
95
|
_phone: {
|
|
96
|
+
margin: "none",
|
|
98
97
|
borderRadius: "0",
|
|
99
98
|
height: "100dvh",
|
|
100
99
|
border: "0",
|
|
@@ -109,7 +108,7 @@ const header = css({
|
|
|
109
108
|
flexShrink: "0",
|
|
110
109
|
paddingInlineEnd: "control.compactInline",
|
|
111
110
|
paddingInlineStart: "control.inline",
|
|
112
|
-
borderBottom: "1px solid token(colors.border.
|
|
111
|
+
borderBottom: "1px solid token(colors.border.divider)",
|
|
113
112
|
"& > :last-child": { minWidth: "0", maxWidth: "100%" },
|
|
114
113
|
// Once the sidebar is gone the header stays one row: the title truncates, the actions keep
|
|
115
114
|
// their width.
|
|
@@ -118,22 +117,25 @@ const header = css({
|
|
|
118
117
|
padding: "panel.default",
|
|
119
118
|
"& > [data-header-title]": {
|
|
120
119
|
minWidth: "0",
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
overflowX: "clip",
|
|
121
|
+
overflowY: "visible",
|
|
123
122
|
textOverflow: "ellipsis",
|
|
124
|
-
|
|
123
|
+
whiteSpace: "nowrap",
|
|
125
124
|
},
|
|
126
125
|
// The actions hold one line: a slicer keeps its value and drops the dimension it names.
|
|
127
126
|
"& > :last-child": { flexShrink: "0", flexWrap: "nowrap" },
|
|
128
127
|
"& [data-slicer-label]": { srOnly: true },
|
|
129
128
|
},
|
|
130
129
|
});
|
|
130
|
+
// The trail's parents; the page itself, last, is in the primary text.
|
|
131
131
|
const headerTitle = css({
|
|
132
132
|
flex: "1",
|
|
133
133
|
minWidth: "0",
|
|
134
134
|
color: "fg.muted",
|
|
135
|
+
_light: { color: "fg.secondary" },
|
|
135
136
|
fontSize: "caption",
|
|
136
137
|
fontWeight: "medium",
|
|
138
|
+
lineHeight: "tight",
|
|
137
139
|
});
|
|
138
140
|
const content = css({
|
|
139
141
|
flex: "1",
|
|
@@ -201,14 +203,14 @@ const sidebarRail = css({
|
|
|
201
203
|
display: "flex",
|
|
202
204
|
flexDirection: "column",
|
|
203
205
|
alignItems: "center",
|
|
204
|
-
gap: "
|
|
206
|
+
gap: "sidebar.groupGap",
|
|
205
207
|
});
|
|
206
208
|
/* One sidebar's content stacks at its container's own gap, so a footer's controls keep their room. */
|
|
207
209
|
const sidebarOnly = css({ display: "flex", flexDirection: "column", gap: "inherit" });
|
|
208
210
|
const sidebarNav = css({
|
|
209
211
|
display: "flex",
|
|
210
212
|
flexDirection: "column",
|
|
211
|
-
gap: "
|
|
213
|
+
gap: "sidebar.groupGap",
|
|
212
214
|
minHeight: "0",
|
|
213
215
|
overflowY: "auto",
|
|
214
216
|
// Scrolling would clip the ring of anything outer-ringed placed among the items.
|
|
@@ -216,11 +218,9 @@ const sidebarNav = css({
|
|
|
216
218
|
});
|
|
217
219
|
const sidebarFooter = css({
|
|
218
220
|
marginTop: "auto",
|
|
219
|
-
// Room above the footer's first control, so it never sits tight under the last nav row.
|
|
220
|
-
paddingTop: "layout.contentGap",
|
|
221
221
|
display: "flex",
|
|
222
222
|
flexDirection: "column",
|
|
223
|
-
gap: "layout.
|
|
223
|
+
gap: "layout.controlGap",
|
|
224
224
|
// A phone shows the footer in its menu at full width, as the expanded sidebar does.
|
|
225
225
|
_rail: { _notPhone: { alignItems: "center" } },
|
|
226
226
|
});
|
|
@@ -270,7 +270,7 @@ const headerActions = css({
|
|
|
270
270
|
display: "flex",
|
|
271
271
|
alignItems: "center",
|
|
272
272
|
justifyContent: "flex-end",
|
|
273
|
-
gap: "layout.
|
|
273
|
+
gap: "layout.tightGap",
|
|
274
274
|
minWidth: "0",
|
|
275
275
|
});
|
|
276
276
|
/** The header's copy of the rail, for widths where the sidebar is gone altogether. */
|
|
@@ -290,9 +290,9 @@ const crumbs = css({
|
|
|
290
290
|
whiteSpace: "nowrap",
|
|
291
291
|
"& > :last-child": {
|
|
292
292
|
minWidth: "0",
|
|
293
|
-
|
|
293
|
+
overflowX: "clip",
|
|
294
|
+
overflowY: "visible",
|
|
294
295
|
textOverflow: "ellipsis",
|
|
295
|
-
lineHeight: "compact",
|
|
296
296
|
},
|
|
297
297
|
_phone: { gap: "layout.tightGap" },
|
|
298
298
|
"& a:hover": { textDecoration: "underline" },
|
|
@@ -331,7 +331,7 @@ export function AppBreadcrumbs({ className, ...props }) {
|
|
|
331
331
|
const { labels } = useCiridaeLocale();
|
|
332
332
|
return _jsx("nav", { "aria-label": labels.shell.breadcrumb, ...props, className: cx(crumbs, className) });
|
|
333
333
|
}
|
|
334
|
-
const crumbSeparator = css({ color: "fg.
|
|
334
|
+
const crumbSeparator = css({ color: "fg.subtle" });
|
|
335
335
|
// The page's title, as its one h1, set in the trail's own type.
|
|
336
336
|
const crumbCurrent = css({
|
|
337
337
|
margin: "none",
|
|
@@ -373,9 +373,9 @@ const account = css({
|
|
|
373
373
|
alignItems: "center",
|
|
374
374
|
gap: "sidebar.markGap",
|
|
375
375
|
width: "100%",
|
|
376
|
-
padding: "
|
|
376
|
+
padding: "control.compactBlock",
|
|
377
377
|
border: "0",
|
|
378
|
-
borderRadius: "
|
|
378
|
+
borderRadius: "keycap",
|
|
379
379
|
background: "transparent",
|
|
380
380
|
color: "inherit",
|
|
381
381
|
font: "inherit",
|
|
@@ -393,25 +393,23 @@ const accountAvatarOnly = css({
|
|
|
393
393
|
cursor: "pointer",
|
|
394
394
|
_focusVisible: { focusRing: "outer" },
|
|
395
395
|
});
|
|
396
|
+
// The name and the detail under it, 4px apart as the design's account row stacks them: each line
|
|
397
|
+
// sits at its type's own height, so without the gap the two would touch.
|
|
396
398
|
const accountCopy = css({
|
|
397
399
|
display: "grid",
|
|
400
|
+
gap: "layout.tightGap",
|
|
398
401
|
flex: "1",
|
|
399
402
|
minWidth: "0",
|
|
400
|
-
"& >
|
|
401
|
-
|
|
402
|
-
textOverflow: "ellipsis",
|
|
403
|
-
whiteSpace: "nowrap",
|
|
404
|
-
lineHeight: "compact",
|
|
405
|
-
},
|
|
406
|
-
"& > :last-child": { color: "fg.muted", fontSize: "caption" },
|
|
403
|
+
"& > strong": { fontWeight: "medium" },
|
|
404
|
+
"& > :nth-child(2)": { color: "fg.muted", fontSize: "caption" },
|
|
407
405
|
});
|
|
408
406
|
/**
|
|
409
|
-
* The signed-in account as a menu trigger: avatar, name, and a detail line, or with
|
|
410
|
-
* avatar alone.
|
|
407
|
+
* The signed-in account as a menu trigger: avatar, name, and a detail line if given, or with
|
|
408
|
+
* `compact` the avatar alone.
|
|
411
409
|
*/
|
|
412
410
|
export function AppAccountButton({ avatar, name, detail, trailing, compact = false, className, ...props }) {
|
|
413
411
|
if (compact) {
|
|
414
412
|
return (_jsx("button", { type: "button", ...props, className: cx(accountAvatarOnly, className), children: avatar }));
|
|
415
413
|
}
|
|
416
|
-
return (_jsxs("button", { type: "button", ...props, className: cx(account, className), children: [avatar, _jsxs("span", { className: accountCopy, children: [_jsx("strong", { children: name }), _jsx("span", { children: detail })] }), trailing] }));
|
|
414
|
+
return (_jsxs("button", { type: "button", ...props, className: cx(account, className), children: [avatar, _jsxs("span", { className: accountCopy, children: [_jsx("strong", { className: singleLineTextClass, children: name }), detail && _jsx("span", { className: singleLineTextClass, children: detail })] }), trailing] }));
|
|
417
415
|
}
|
|
@@ -2,6 +2,8 @@ import { useRender } from "@base-ui/react/use-render";
|
|
|
2
2
|
import type { ComponentProps, ReactNode } from "react";
|
|
3
3
|
export declare function SidebarNavigation({ className, ...props }: ComponentProps<"nav">): import("react").JSX.Element;
|
|
4
4
|
export declare function SidebarDivider({ className, ...props }: ComponentProps<"hr">): import("react").JSX.Element;
|
|
5
|
+
/** Opens a labelled section in the rail, as its label does in the expanded sidebar. */
|
|
6
|
+
export declare function SidebarRailRule({ className, ...props }: ComponentProps<"hr">): import("react").JSX.Element;
|
|
5
7
|
export declare function SidebarPanel({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
6
8
|
export declare function SidebarSection({ label, action, iconTone, className, children, ...props }: ComponentProps<"div"> & {
|
|
7
9
|
label?: ReactNode;
|
|
@@ -29,7 +31,10 @@ export type SidebarItemProps = useRender.ComponentProps<"button"> & {
|
|
|
29
31
|
active?: boolean;
|
|
30
32
|
/** Tint the leading icon bronze while inactive, as the Projects hub sidebar does. */
|
|
31
33
|
iconTone?: "bronze";
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* `compact` is a secondary list's row, such as recently opened records; `short` a shorter row
|
|
36
|
+
* in the body type, such as the settings sidebar's Back to app.
|
|
37
|
+
*/
|
|
38
|
+
size?: "regular" | "compact" | "short";
|
|
34
39
|
};
|
|
35
40
|
export declare function SidebarItem({ icon, trailing, action, active, iconTone, size, href, render, className, children, ...props }: SidebarItemProps): import("react").JSX.Element;
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useRender } from "@base-ui/react/use-render";
|
|
3
3
|
import { css, cx } from "#primitives/css";
|
|
4
4
|
import { IconButtonSizeContext } from "./button.js";
|
|
5
|
+
import { singleLineText } from "./single-line-text.js";
|
|
5
6
|
// Navigation sits in the shell's sidebar; it is not a panel of its own.
|
|
6
7
|
const navigation = css({
|
|
7
8
|
display: "flex",
|
|
@@ -33,6 +34,17 @@ const sectionLabel = css({
|
|
|
33
34
|
"&[data-icon-tone=bronze] > svg": { color: "accent.bronze" },
|
|
34
35
|
});
|
|
35
36
|
const sectionAction = css({ display: "inline-flex", marginInlineStart: "auto" });
|
|
37
|
+
// A labelled section's mark in the rail, where there is no room for its label: a short rule.
|
|
38
|
+
const railRule = css({
|
|
39
|
+
flexShrink: "0",
|
|
40
|
+
width: "sidebar.railRule",
|
|
41
|
+
height: "border.hairline",
|
|
42
|
+
marginTop: "none",
|
|
43
|
+
marginInline: "auto",
|
|
44
|
+
marginBottom: "panel.default",
|
|
45
|
+
border: "0",
|
|
46
|
+
background: "border.divider",
|
|
47
|
+
});
|
|
36
48
|
const divider = css({
|
|
37
49
|
width: "100%",
|
|
38
50
|
height: "border.hairline",
|
|
@@ -40,15 +52,20 @@ const divider = css({
|
|
|
40
52
|
border: "0",
|
|
41
53
|
background: "border.hairline",
|
|
42
54
|
});
|
|
55
|
+
/*
|
|
56
|
+
* A row is square-cornered at rest; hovered, open or focused it rounds into a pill. The open page
|
|
57
|
+
* sits on the canvas's field face inside its edge; a hover is a faint wash in light and the
|
|
58
|
+
* selected glass in dark.
|
|
59
|
+
*/
|
|
43
60
|
const item = css({
|
|
44
61
|
display: "flex",
|
|
45
62
|
alignItems: "center",
|
|
46
63
|
gap: "layout.controlGap",
|
|
47
64
|
width: "100%",
|
|
48
|
-
height: "control.
|
|
65
|
+
height: "control.row",
|
|
49
66
|
paddingInline: "control.compactInline",
|
|
50
67
|
border: "0",
|
|
51
|
-
borderRadius: "
|
|
68
|
+
borderRadius: "nav",
|
|
52
69
|
background: "transparent",
|
|
53
70
|
// Muted against the dark canvas; light keeps every item at full contrast, as Round 2 does.
|
|
54
71
|
color: "fg.muted",
|
|
@@ -60,24 +77,30 @@ const item = css({
|
|
|
60
77
|
lineHeight: "tight",
|
|
61
78
|
textAlign: "start",
|
|
62
79
|
cursor: "pointer",
|
|
63
|
-
transitionProperty: "background, color",
|
|
80
|
+
transitionProperty: "background, color, border-radius",
|
|
64
81
|
transitionDuration: "fast",
|
|
65
82
|
"& > svg:first-child": { opacity: ".7" },
|
|
66
83
|
"&[data-icon-tone=bronze] > svg:first-child": { color: "accent.bronze" },
|
|
67
84
|
"&:hover, &[aria-pressed=true]": {
|
|
68
|
-
|
|
85
|
+
borderRadius: "shell",
|
|
86
|
+
background: "token(gradients.selected)",
|
|
87
|
+
_light: { background: "bg.rowHover" },
|
|
69
88
|
color: "fg.primary",
|
|
70
89
|
"& > svg:first-child": { color: "inherit" },
|
|
71
90
|
},
|
|
72
|
-
// The open page keeps the hover shape and size
|
|
73
|
-
//
|
|
91
|
+
// The open page keeps the hover shape and size; the field face and the canvas's edge mark it.
|
|
92
|
+
// The design counts that edge inside the row, so its content sits a hairline further in.
|
|
74
93
|
"&[aria-current=page]": {
|
|
75
|
-
|
|
76
|
-
|
|
94
|
+
borderRadius: "shell",
|
|
95
|
+
background: "bg.field",
|
|
96
|
+
boxShadow: "inset 0 0 0 1px token(colors.border.canvas)",
|
|
77
97
|
color: "fg.primary",
|
|
78
98
|
"& > svg:first-child": { color: "inherit", opacity: "1" },
|
|
99
|
+
"&:not([data-icon-only])": {
|
|
100
|
+
paddingInline: "calc(token(spacing.control.compactInline) + token(sizes.border.hairline))",
|
|
101
|
+
},
|
|
79
102
|
},
|
|
80
|
-
_focusVisible: { focusRing: "
|
|
103
|
+
_focusVisible: { borderRadius: "shell", focusRing: "outer" },
|
|
81
104
|
// A secondary list under the navigation, such as recently opened records: a shorter row in
|
|
82
105
|
// smaller, quieter text, so it reads apart from the pages above it.
|
|
83
106
|
"&[data-size=compact]": {
|
|
@@ -85,23 +108,19 @@ const item = css({
|
|
|
85
108
|
color: "fg.secondary",
|
|
86
109
|
fontSize: "caption",
|
|
87
110
|
},
|
|
88
|
-
//
|
|
111
|
+
// A shorter row in the body type, such as the settings sidebar's way back to the app.
|
|
112
|
+
"&[data-size=short]": { height: "sidebar.shortRow" },
|
|
113
|
+
// With no label it is the rail's round button: the same hover, open-page face and edge, icon only.
|
|
89
114
|
"&[data-icon-only]": {
|
|
90
115
|
justifyContent: "center",
|
|
91
|
-
width: "control.
|
|
92
|
-
height: "control.
|
|
116
|
+
width: "control.compact",
|
|
117
|
+
height: "control.compact",
|
|
93
118
|
paddingInline: "none",
|
|
94
|
-
|
|
119
|
+
borderRadius: "round",
|
|
120
|
+
"& > svg:first-child": { opacity: "1", fontSize: "icon.small" },
|
|
95
121
|
},
|
|
96
122
|
});
|
|
97
|
-
const label = css({
|
|
98
|
-
minWidth: "0",
|
|
99
|
-
flex: "1",
|
|
100
|
-
overflow: "hidden",
|
|
101
|
-
textOverflow: "ellipsis",
|
|
102
|
-
whiteSpace: "nowrap",
|
|
103
|
-
lineHeight: "compact",
|
|
104
|
-
});
|
|
123
|
+
const label = css(singleLineText, { flex: "1" });
|
|
105
124
|
const trailingStyle = css({ display: "inline-flex", flexShrink: "0", color: "fg.subtle" });
|
|
106
125
|
// A row with an action: the group draws the row's hover, open-page fill and edge, so they span the
|
|
107
126
|
// action too, and the row inside it stays transparent.
|
|
@@ -110,21 +129,26 @@ const itemGroup = css({
|
|
|
110
129
|
alignItems: "center",
|
|
111
130
|
width: "100%",
|
|
112
131
|
minWidth: "0",
|
|
113
|
-
borderRadius: "
|
|
114
|
-
transitionProperty: "background",
|
|
132
|
+
borderRadius: "nav",
|
|
133
|
+
transitionProperty: "background, border-radius",
|
|
115
134
|
transitionDuration: "fast",
|
|
116
|
-
"&:hover": {
|
|
135
|
+
"&:hover": {
|
|
136
|
+
borderRadius: "shell",
|
|
137
|
+
background: "token(gradients.selected)",
|
|
138
|
+
_light: { background: "bg.rowHover" },
|
|
139
|
+
},
|
|
117
140
|
"&:hover > [data-sidebar-row]": { color: "fg.primary" },
|
|
118
141
|
"&:has(> [data-sidebar-row][aria-current=page])": {
|
|
119
|
-
|
|
120
|
-
|
|
142
|
+
borderRadius: "shell",
|
|
143
|
+
background: "bg.field",
|
|
144
|
+
boxShadow: "inset 0 0 0 1px token(colors.border.canvas)",
|
|
121
145
|
},
|
|
122
146
|
// The group draws the one wash; the row inside never adds its own on hover or when current.
|
|
123
147
|
"& > [data-sidebar-row]": { minWidth: "0" },
|
|
124
148
|
"& > [data-sidebar-row], & > [data-sidebar-row]:is(:hover, [aria-current=page], [aria-pressed=true])": { background: "transparent", boxShadow: "none" },
|
|
125
149
|
// Focus rings the whole row, action included, not just the link inside it.
|
|
126
150
|
"& > [data-sidebar-row]:focus-visible": { outline: "none" },
|
|
127
|
-
"&:has(> [data-sidebar-row]:focus-visible)": { focusRing: "
|
|
151
|
+
"&:has(> [data-sidebar-row]:focus-visible)": { borderRadius: "shell", focusRing: "outer" },
|
|
128
152
|
"&:hover > [data-sidebar-action], & > [data-sidebar-action]:focus-within": { opacity: "1" },
|
|
129
153
|
});
|
|
130
154
|
// Revealed on hover or focus; always shown where there is no hover to reveal it.
|
|
@@ -171,6 +195,10 @@ export function SidebarNavigation({ className, ...props }) {
|
|
|
171
195
|
export function SidebarDivider({ className, ...props }) {
|
|
172
196
|
return _jsx("hr", { ...props, className: cx(divider, className), "data-ciridae-ui": "" });
|
|
173
197
|
}
|
|
198
|
+
/** Opens a labelled section in the rail, as its label does in the expanded sidebar. */
|
|
199
|
+
export function SidebarRailRule({ className, ...props }) {
|
|
200
|
+
return _jsx("hr", { ...props, className: cx(railRule, className), "data-ciridae-ui": "" });
|
|
201
|
+
}
|
|
174
202
|
export function SidebarPanel({ className, ...props }) {
|
|
175
203
|
return _jsx("div", { ...props, className: cx(panel, className), "data-ciridae-ui": "" });
|
|
176
204
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { css } from "#primitives/css";
|
|
2
|
+
/*
|
|
3
|
+
* One line of text at the type's own height, as the design sets every single-line label, cut
|
|
4
|
+
* with an ellipsis when it runs out of room. It clips sideways only, so the descenders that reach
|
|
5
|
+
* below a line box that tight stay whole. Compose it at the top level of a `css()` call, or as the
|
|
6
|
+
* class `singleLineTextClass`: Panda does not extract it from under a nested selector.
|
|
7
|
+
*/
|
|
8
|
+
export const singleLineText = css.raw({
|
|
9
|
+
minWidth: "0",
|
|
10
|
+
overflowX: "clip",
|
|
11
|
+
overflowY: "visible",
|
|
12
|
+
textOverflow: "ellipsis",
|
|
13
|
+
whiteSpace: "nowrap",
|
|
14
|
+
lineHeight: "tight",
|
|
15
|
+
});
|
|
16
|
+
export const singleLineTextClass = css(singleLineText);
|
|
@@ -19,7 +19,10 @@ declare const banner: import("../styled-system/types/index.js").RecipeRuntimeFn<
|
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
21
|
}>;
|
|
22
|
-
export type SiteBannerProps = ComponentProps<"div"> & RecipeVariantProps<typeof banner
|
|
22
|
+
export type SiteBannerProps = ComponentProps<"div"> & RecipeVariantProps<typeof banner> & {
|
|
23
|
+
/** Adds a close button at the strip's end. */
|
|
24
|
+
onDismiss?: () => void;
|
|
25
|
+
};
|
|
23
26
|
/** A quiet, full-width site notice, separate from page-level status banners. */
|
|
24
|
-
export declare function SiteBanner({ tone, className, ...props }: SiteBannerProps): import("react").JSX.Element;
|
|
27
|
+
export declare function SiteBanner({ tone, onDismiss, className, children, ...props }: SiteBannerProps): import("react").JSX.Element;
|
|
25
28
|
export {};
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { XIcon } from "@phosphor-icons/react";
|
|
3
|
+
import { css, cva, cx } from "#primitives/css";
|
|
4
|
+
import { IconButton } from "./button.js";
|
|
5
|
+
import { icon } from "./icon.js";
|
|
6
|
+
import { useCiridaeLocale } from "./locale.js";
|
|
3
7
|
const banner = cva({
|
|
4
8
|
base: {
|
|
9
|
+
display: "flex",
|
|
10
|
+
alignItems: "center",
|
|
11
|
+
gap: "layout.controlGap",
|
|
5
12
|
flexShrink: "0",
|
|
6
13
|
width: "100%",
|
|
7
14
|
boxSizing: "border-box",
|
|
8
|
-
paddingBlock: "
|
|
9
|
-
paddingInline: "
|
|
15
|
+
paddingBlock: "control.trackInset",
|
|
16
|
+
paddingInline: "control.inline",
|
|
10
17
|
textAlign: "start",
|
|
11
18
|
fontSize: "11px",
|
|
12
19
|
fontWeight: "medium",
|
|
@@ -24,7 +31,11 @@ const banner = cva({
|
|
|
24
31
|
},
|
|
25
32
|
defaultVariants: { tone: "info" },
|
|
26
33
|
});
|
|
34
|
+
const message = css({ flex: "1", minWidth: "0" });
|
|
35
|
+
// The strip keeps its height: the button reaches past the line by as much as it is taller.
|
|
36
|
+
const dismissButton = css({ marginBlock: "calc((1lh - token(sizes.control.shortcut)) / 2)" });
|
|
27
37
|
/** A quiet, full-width site notice, separate from page-level status banners. */
|
|
28
|
-
export function SiteBanner({ tone, className, ...props }) {
|
|
29
|
-
|
|
38
|
+
export function SiteBanner({ tone, onDismiss, className, children, ...props }) {
|
|
39
|
+
const { labels } = useCiridaeLocale();
|
|
40
|
+
return (_jsxs("div", { ...props, className: cx(banner({ tone }), className), children: [_jsx("span", { className: message, children: children }), onDismiss && (_jsx(IconButton, { "aria-label": labels.common.dismiss, variant: "ghost", size: "compact", className: dismissButton, onClick: onDismiss, children: _jsx(XIcon, { className: icon({ size: "compact" }) }) }))] }));
|
|
30
41
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { ComponentProps } from "react";
|
|
2
2
|
export type SkeletonWidth = "short" | "medium" | "long" | "full" | `${number}%`;
|
|
3
|
-
export type SkeletonHeight = "text" | "caption" | "control" | "row" | "block" | "chart" | "chart.small" | "chart.medium" | "chart.large";
|
|
3
|
+
export type SkeletonHeight = "text" | "caption" | "line" | "smallLine" | "bar" | "badge" | "control" | "row" | "block" | "chart" | "chart.small" | "chart.medium" | "chart.large";
|
|
4
4
|
/**
|
|
5
|
-
* Loading placeholder
|
|
6
|
-
*
|
|
7
|
-
* length, `full`, or a percentage of its box) and `height` (a line of text
|
|
8
|
-
*
|
|
5
|
+
* Loading placeholder. `block` fills its box, `text` takes one line of the surrounding text,
|
|
6
|
+
* `circle` stands in for an avatar, `square` for a checkbox, and `pill` for a status chip. Size it
|
|
7
|
+
* with `width` (a token length, `full`, or a percentage of its box) and `height` (a line of text
|
|
8
|
+
* or small print, the design's fixed line or small line, a bar, a small badge, a control, a list
|
|
9
|
+
* row, the whole box, or a chart's height).
|
|
9
10
|
*/
|
|
10
11
|
export declare function Skeleton({ shape, width, height, className, style, ...props }: ComponentProps<"span"> & {
|
|
11
|
-
shape?: "block" | "text" | "circle" | "square";
|
|
12
|
+
shape?: "block" | "text" | "circle" | "square" | "pill";
|
|
12
13
|
/** A token width, for a value of roughly known length, or a share of the box such as `"60%"`. */
|
|
13
14
|
width?: SkeletonWidth;
|
|
14
15
|
height?: SkeletonHeight;
|
|
@@ -1,43 +1,54 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { css, cx } from "#primitives/css";
|
|
3
|
+
// The design draws placeholders flat, with no shimmer: the canvas's gradient in light, a white
|
|
4
|
+
// wash in dark. Every bar is fully rounded except the block, the box and the bar.
|
|
3
5
|
const skeleton = css({
|
|
4
6
|
display: "block",
|
|
5
7
|
flexShrink: "0",
|
|
6
|
-
background: "token(gradients.
|
|
7
|
-
|
|
8
|
-
animation: "skeletonShimmer 1.6s ease-in-out infinite",
|
|
9
|
-
_motionReduce: { animation: "none" },
|
|
10
|
-
"&[data-shape=block]": { minHeight: "skeleton.line", borderRadius: "action" },
|
|
8
|
+
background: "token(gradients.skeletonFill)",
|
|
9
|
+
"&[data-shape=block]": { minHeight: "skeleton.line", borderRadius: "control" },
|
|
11
10
|
// One line of the surrounding text: the bar is shorter than the line box and centered in it.
|
|
12
11
|
"&[data-shape=text]": {
|
|
13
12
|
width: "100%",
|
|
14
13
|
height: "0.75em",
|
|
15
14
|
marginBlock: "calc((1lh - 0.75em) / 2)",
|
|
16
|
-
borderRadius: "
|
|
15
|
+
borderRadius: "round",
|
|
17
16
|
},
|
|
18
17
|
"&[data-shape=circle]": {
|
|
19
|
-
width: "
|
|
18
|
+
width: "avatar.menu",
|
|
20
19
|
aspectRatio: "1",
|
|
21
20
|
borderRadius: "round",
|
|
22
21
|
},
|
|
23
22
|
"&[data-shape=square]": {
|
|
24
|
-
width: "control.
|
|
23
|
+
width: "control.checkbox",
|
|
25
24
|
aspectRatio: "1",
|
|
26
|
-
borderRadius: "
|
|
25
|
+
borderRadius: "control",
|
|
26
|
+
},
|
|
27
|
+
// A status chip's or a badge's placeholder.
|
|
28
|
+
"&[data-shape=pill]": {
|
|
29
|
+
width: "skeleton.pill",
|
|
30
|
+
height: "skeleton.bar",
|
|
31
|
+
borderRadius: "round",
|
|
27
32
|
},
|
|
28
33
|
"&[data-shape][data-width=short]": { width: "skeleton.short" },
|
|
29
34
|
"&[data-shape][data-width=medium]": { width: "skeleton.medium" },
|
|
30
35
|
"&[data-shape][data-width=long]": { width: "skeleton.long" },
|
|
31
36
|
"&[data-shape][data-width=full]": { width: "100%" },
|
|
32
|
-
// A line of
|
|
37
|
+
// A line of small print, such as a row's meta line, under a line of text.
|
|
33
38
|
"&[data-shape][data-height=caption]": {
|
|
34
|
-
height: "
|
|
35
|
-
marginBlock: "calc((1lh - token(
|
|
39
|
+
height: "skeleton.caption",
|
|
40
|
+
marginBlock: "calc((1lh - token(sizes.skeleton.caption)) / 2)",
|
|
36
41
|
},
|
|
37
42
|
"&[data-shape][data-height=text]": {
|
|
38
43
|
height: "0.75em",
|
|
39
44
|
marginBlock: "calc((1lh - 0.75em) / 2)",
|
|
40
45
|
},
|
|
46
|
+
// The design's fixed text bars, with no line box round them: a line, and a small one.
|
|
47
|
+
"&[data-shape][data-height=line]": { height: "skeleton.textLine", marginBlock: "0" },
|
|
48
|
+
"&[data-shape][data-height=smallLine]": { height: "skeleton.caption", marginBlock: "0" },
|
|
49
|
+
// A bar in a chart's or a breakdown's placeholder, and a small badge's.
|
|
50
|
+
"&[data-shape][data-height=bar]": { height: "skeleton.bar", marginBlock: "0" },
|
|
51
|
+
"&[data-shape][data-height=badge]": { height: "skeleton.badge", marginBlock: "0" },
|
|
41
52
|
"&[data-shape][data-height=control]": { height: "control.default", marginBlock: "0" },
|
|
42
53
|
"&[data-shape][data-height=row]": { height: "control.field", marginBlock: "0" },
|
|
43
54
|
"&[data-shape][data-height=block]": { height: "100%", marginBlock: "0" },
|
|
@@ -49,10 +60,11 @@ const skeleton = css({
|
|
|
49
60
|
"&[data-shape][data-height='chart.large']": { height: "chart.large", marginBlock: "0" },
|
|
50
61
|
});
|
|
51
62
|
/**
|
|
52
|
-
* Loading placeholder
|
|
53
|
-
*
|
|
54
|
-
* length, `full`, or a percentage of its box) and `height` (a line of text
|
|
55
|
-
*
|
|
63
|
+
* Loading placeholder. `block` fills its box, `text` takes one line of the surrounding text,
|
|
64
|
+
* `circle` stands in for an avatar, `square` for a checkbox, and `pill` for a status chip. Size it
|
|
65
|
+
* with `width` (a token length, `full`, or a percentage of its box) and `height` (a line of text
|
|
66
|
+
* or small print, the design's fixed line or small line, a bar, a small badge, a control, a list
|
|
67
|
+
* row, the whole box, or a chart's height).
|
|
56
68
|
*/
|
|
57
69
|
export function Skeleton({ shape = "block", width, height, className, style, ...props }) {
|
|
58
70
|
const percent = width?.endsWith("%") ? width : undefined;
|
|
@@ -13,6 +13,18 @@ export declare function PageHeaderSkeleton({ avatar, actions, }: {
|
|
|
13
13
|
export declare function PanelSkeleton({ rows }: {
|
|
14
14
|
rows?: number;
|
|
15
15
|
}): import("react").JSX.Element;
|
|
16
|
+
/** Stands in for list rows: a line of text over a line of small print, then a status chip. */
|
|
17
|
+
export declare function ListRowsSkeleton({ rows }: {
|
|
18
|
+
rows?: number;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
20
|
+
/** Stands in for a stat tile: its label, a small badge for the figure, and a line of small print. */
|
|
21
|
+
export declare function StatTileSkeleton({ className }: {
|
|
22
|
+
className?: string;
|
|
23
|
+
}): import("react").JSX.Element;
|
|
24
|
+
/** Stands in for a card: a title and its meta line, labelled bars, and a takeaway under a rule. */
|
|
25
|
+
export declare function CardSkeleton({ bars }: {
|
|
26
|
+
bars?: number;
|
|
27
|
+
}): import("react").JSX.Element;
|
|
16
28
|
/** Placeholder for a row's compact edit and delete icon buttons. */
|
|
17
29
|
export declare function RowActionsSkeleton(): import("react").JSX.Element;
|
|
18
30
|
/**
|