@cl-light-ds/ui 0.4.0 → 0.6.0
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 +19 -17
- package/src/components/accordion/AccordionTrigger.astro +5 -1
- package/src/components/accordion/CHANGELOG.md +9 -0
- package/src/components/alert/Alert.astro +42 -3
- package/src/components/alert/CHANGELOG.md +19 -0
- package/src/components/button/Button.astro +78 -19
- package/src/components/button/CHANGELOG.md +22 -0
- package/src/components/button-group/ButtonGroup.astro +14 -3
- package/src/components/button-group/CHANGELOG.md +17 -0
- package/src/components/card/CHANGELOG.md +9 -0
- package/src/components/card/Card.astro +22 -0
- package/src/components/collapsible/CHANGELOG.md +9 -0
- package/src/components/collapsible/CollapsibleTrigger.astro +5 -1
- package/src/components/combobox/CHANGELOG.md +27 -0
- package/src/components/combobox/Combobox.astro +18 -1
- package/src/components/combobox/ComboboxTrigger.astro +32 -2
- package/src/components/command-search/CHANGELOG.md +57 -0
- package/src/components/command-search/CommandSearch.astro +594 -0
- package/src/components/command-search/CommandSearchGroup.astro +43 -0
- package/src/components/command-search/CommandSearchItem.astro +64 -0
- package/src/components/command-search/classes.ts +18 -0
- package/src/components/command-search/index.ts +12 -0
- package/src/components/command-search/nothing-matches.svg +42 -0
- package/src/components/dialog/CHANGELOG.md +50 -0
- package/src/components/dialog/Dialog.astro +14 -3
- package/src/components/dialog/DialogClose.astro +28 -12
- package/src/components/dialog/DialogContent.astro +19 -1
- package/src/components/dialog/DialogTrigger.astro +5 -1
- package/src/components/dropdown-menu/CHANGELOG.md +32 -0
- package/src/components/dropdown-menu/DropdownMenu.astro +13 -3
- package/src/components/dropdown-menu/DropdownMenuRadioGroup.astro +17 -2
- package/src/components/dropdown-menu/DropdownMenuTrigger.astro +7 -1
- package/src/components/dropdown-menu/dropdown-menu-item-variants.ts +1 -1
- package/src/components/empty-state/CHANGELOG.md +18 -0
- package/src/components/empty-state/EmptyState.astro +157 -0
- package/src/components/empty-state/illustrations/AllCaughtUp.astro +52 -0
- package/src/components/empty-state/illustrations/EmptyWorkspaces.astro +56 -0
- package/src/components/empty-state/illustrations/LoadError.astro +61 -0
- package/src/components/empty-state/illustrations/NoResults.astro +60 -0
- package/src/components/empty-state/illustrations/NothingMatches.astro +66 -0
- package/src/components/empty-state/illustrations/index.ts +27 -0
- package/src/components/empty-state/index.ts +7 -0
- package/src/components/favorite-toggle/CHANGELOG.md +13 -0
- package/src/components/favorite-toggle/FavoriteToggle.astro +94 -0
- package/src/components/favorite-toggle/index.ts +1 -0
- package/src/components/field/CHANGELOG.md +18 -0
- package/src/components/field/Field.astro +18 -0
- package/src/components/field/FieldError.astro +13 -1
- package/src/components/field/FieldGroup.astro +12 -3
- package/src/components/hover-card/CHANGELOG.md +9 -0
- package/src/components/hover-card/HoverCardTrigger.astro +5 -1
- package/src/components/input-group/CHANGELOG.md +7 -0
- package/src/components/input-group/InputGroup.astro +2 -0
- package/src/components/loading-overlay/CHANGELOG.md +25 -0
- package/src/components/loading-overlay/LoadingOverlay.astro +179 -0
- package/src/components/loading-overlay/index.ts +8 -0
- package/src/components/notifications-menu/CHANGELOG.md +29 -0
- package/src/components/notifications-menu/NotificationsMenu.astro +375 -0
- package/src/components/notifications-menu/NotificationsMenuItem.astro +130 -0
- package/src/components/notifications-menu/all-caught-up.svg +28 -0
- package/src/components/notifications-menu/index.ts +3 -0
- package/src/components/notifications-menu/types.ts +32 -0
- package/src/components/option-card/CHANGELOG.md +26 -0
- package/src/components/option-card/OptionCard.astro +143 -0
- package/src/components/option-card/index.ts +1 -0
- package/src/components/organisms/top-bar/CHANGELOG.md +27 -0
- package/src/components/organisms/top-bar/TopBar.astro +257 -0
- package/src/components/organisms/top-bar/index.ts +2 -0
- package/src/components/organisms/top-bar/types.ts +30 -0
- package/src/components/organisms/workspace/CHANGELOG.md +80 -0
- package/src/components/organisms/workspace/OrganisationOverview.astro +62 -0
- package/src/components/organisms/workspace/RecentWorkspaceCard.astro +235 -0
- package/src/components/organisms/workspace/RecentWorkspaces.astro +93 -0
- package/src/components/organisms/workspace/WorkspaceAvatar.astro +144 -0
- package/src/components/organisms/workspace/WorkspaceCard.astro +172 -0
- package/src/components/organisms/workspace/WorkspaceGlyph.astro +62 -0
- package/src/components/organisms/workspace/WorkspaceIcon.astro +42 -0
- package/src/components/organisms/workspace/WorkspaceIconPicker.astro +288 -0
- package/src/components/organisms/workspace/WorkspaceIconPickerGlyph.astro +44 -0
- package/src/components/organisms/workspace/icons.ts +98 -0
- package/src/components/organisms/workspace/index.ts +35 -0
- package/src/components/organisms/workspace/labels.ts +54 -0
- package/src/components/organisms/workspace/recent-card-rings-strong.png +0 -0
- package/src/components/organisms/workspace/types.ts +30 -0
- package/src/components/popover/CHANGELOG.md +14 -0
- package/src/components/popover/PopoverClose.astro +2 -1
- package/src/components/popover/PopoverTrigger.astro +7 -1
- package/src/components/profile-menu/CHANGELOG.md +22 -0
- package/src/components/profile-menu/ProfileMenu.astro +236 -0
- package/src/components/profile-menu/index.ts +2 -0
- package/src/components/profile-menu/types.ts +27 -0
- package/src/components/search-field/CHANGELOG.md +14 -0
- package/src/components/search-field/SearchField.astro +163 -0
- package/src/components/search-field/index.ts +1 -0
- package/src/components/select/CHANGELOG.md +8 -0
- package/src/components/select/SelectTrigger.astro +1 -1
- package/src/components/table/CHANGELOG.md +15 -0
- package/src/components/table/TableCell.astro +6 -0
- package/src/components/table/TableEditableCell.astro +2 -2
- package/src/components/table/TableHead.astro +5 -1
- package/src/components/table/TablePagination.astro +4 -4
- package/src/components/table/TableRow.astro +3 -1
- package/src/components/table/table-cell-variants.ts +2 -0
- package/src/components/tabs/CHANGELOG.md +16 -0
- package/src/components/tabs/Tabs.astro +26 -0
- package/src/components/tabs/TabsList.astro +30 -3
- package/src/components/toast/CHANGELOG.md +32 -0
- package/src/components/toast/Toast.astro +145 -0
- package/src/components/toast/Toaster.astro +322 -0
- package/src/components/toast/index.ts +9 -0
- package/src/components/toggle/CHANGELOG.md +7 -0
- package/src/components/toggle-group/CHANGELOG.md +11 -0
- package/src/components/toggle-group/ToggleGroup.astro +19 -2
- package/src/components/toggle-group/ToggleGroupItem.astro +10 -0
- package/src/components/tooltip/CHANGELOG.md +26 -0
- package/src/components/tooltip/Tooltip.astro +31 -3
- package/src/components/tooltip/TooltipTrigger.astro +5 -1
- package/src/lib/command-search.ts +78 -0
- package/src/lib/dialog-focus.ts +73 -0
- package/src/lib/dropdown-menu-radio-groups.ts +79 -0
- package/src/lib/loading-overlay.ts +174 -0
- package/src/lib/scroll-lock.ts +97 -0
- package/src/lib/toast.ts +127 -0
- package/src/lib/toggle-shared.ts +9 -1
- package/src/lib/workspace-palette.ts +119 -0
- package/src/styles/CHANGELOG.md +35 -0
- package/src/styles/globals.css +109 -0
package/src/lib/toast.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imperative API for the `Toaster` component (`@cl-light-ds/ui/components/toast`).
|
|
3
|
+
*
|
|
4
|
+
* `Toaster` binds `@data-slot/toast` to its root; this module talks to that
|
|
5
|
+
* root through the runtime's inbound events (`toast:show`, `toast:update`,
|
|
6
|
+
* `toast:dismiss`, `toast:clear`), so it never needs the controller itself and
|
|
7
|
+
* works from any bundled script on the page.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { toast } from "@cl-light-ds/ui/lib/toast";
|
|
11
|
+
*
|
|
12
|
+
* const id = toast({ kind: "success", title: "Export ready", description: "Acme.zip", action: { label: "Download", href: "/acme.zip", download: true } });
|
|
13
|
+
* toast.dismiss(id);
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Calls made before the Toaster's script has run are queued and replayed once
|
|
17
|
+
* it is ready (`toaster:ready`).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export type ToastKind = "info" | "success" | "error";
|
|
21
|
+
|
|
22
|
+
export interface ToastActionOptions {
|
|
23
|
+
/** The action button's label, e.g. "Download". */
|
|
24
|
+
label: string;
|
|
25
|
+
/** Runs on click. Call `event.preventDefault()` to keep the toast open. */
|
|
26
|
+
onClick?: (event: { readonly defaultPrevented: boolean; preventDefault(): void }) => void;
|
|
27
|
+
/** Sent with the root's `toast:action` event. */
|
|
28
|
+
value?: string;
|
|
29
|
+
/** Opens (or downloads) this URL on click. */
|
|
30
|
+
href?: string;
|
|
31
|
+
/** With `href`: download the file; a string names the saved file. */
|
|
32
|
+
download?: boolean | string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ToastShowOptions {
|
|
36
|
+
/** Reuse an id to replace a toast in place. Generated when left out. */
|
|
37
|
+
id?: string;
|
|
38
|
+
/** `info` (blue icon, default), `success` (green), `error` (red tint, shakes). */
|
|
39
|
+
kind?: ToastKind;
|
|
40
|
+
title: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
/** ms before it closes by itself; `0` = stays until closed. Defaults to the Toaster's `duration`. */
|
|
43
|
+
duration?: number;
|
|
44
|
+
action?: ToastActionOptions;
|
|
45
|
+
/** `false` hides nothing but disables swipe-to-dismiss. */
|
|
46
|
+
dismissible?: boolean;
|
|
47
|
+
/** Accessible name of the ✕ (default "Close"). */
|
|
48
|
+
closeLabel?: string;
|
|
49
|
+
/** Which Toaster: its id or element. Defaults to the first on the page. */
|
|
50
|
+
toaster?: string | HTMLElement;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type ToastUpdateOptions = Partial<Omit<ToastShowOptions, "id" | "toaster">> & {
|
|
54
|
+
toaster?: string | HTMLElement;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const ROOT = '[data-slot="toast"]';
|
|
58
|
+
const KINDS: readonly ToastKind[] = ["info", "success", "error"];
|
|
59
|
+
let counter = 0;
|
|
60
|
+
|
|
61
|
+
const findRoot = (toaster?: string | HTMLElement): HTMLElement | null => {
|
|
62
|
+
if (typeof document === "undefined") return null;
|
|
63
|
+
if (toaster instanceof HTMLElement) return toaster;
|
|
64
|
+
if (typeof toaster === "string") return document.getElementById(toaster);
|
|
65
|
+
return document.querySelector<HTMLElement>(ROOT);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** Send an inbound event, waiting for the Toaster to be bound if needed. */
|
|
69
|
+
const send = (root: HTMLElement | null, name: string, detail?: unknown) => {
|
|
70
|
+
if (!root) {
|
|
71
|
+
console.warn(`[toast] No <Toaster /> found on the page for "${name}".`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const fire = () => root.dispatchEvent(new CustomEvent(name, { detail }));
|
|
75
|
+
if (root.dataset.toasterReady === "true") fire();
|
|
76
|
+
else root.addEventListener("toaster:ready", fire, { once: true });
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const toRuntimeAction = (action: ToastActionOptions) => ({
|
|
80
|
+
label: action.label,
|
|
81
|
+
value: action.value,
|
|
82
|
+
onClick: (event: { readonly defaultPrevented: boolean; preventDefault(): void }) => {
|
|
83
|
+
if (action.href) {
|
|
84
|
+
const link = document.createElement("a");
|
|
85
|
+
link.href = action.href;
|
|
86
|
+
if (action.download)
|
|
87
|
+
link.download = typeof action.download === "string" ? action.download : "";
|
|
88
|
+
link.rel = "noopener";
|
|
89
|
+
link.click();
|
|
90
|
+
}
|
|
91
|
+
action.onClick?.(event);
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const toRuntime = (options: Partial<ToastShowOptions>) => {
|
|
96
|
+
const detail: Record<string, unknown> = {};
|
|
97
|
+
if (options.title !== undefined) detail.title = options.title;
|
|
98
|
+
if (options.description !== undefined) detail.description = options.description;
|
|
99
|
+
if (options.kind !== undefined)
|
|
100
|
+
detail.type = KINDS.includes(options.kind) ? options.kind : "info";
|
|
101
|
+
if (options.duration !== undefined) detail.duration = options.duration;
|
|
102
|
+
if (options.dismissible !== undefined) detail.dismissible = options.dismissible;
|
|
103
|
+
if (options.closeLabel !== undefined) detail.closeButtonAriaLabel = options.closeLabel;
|
|
104
|
+
if (options.action !== undefined) detail.action = toRuntimeAction(options.action);
|
|
105
|
+
return detail;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/** Show a toast; returns its id. */
|
|
109
|
+
export function toast(options: ToastShowOptions): string {
|
|
110
|
+
const id = options.id ?? `toast-${Date.now().toString(36)}-${(counter += 1)}`;
|
|
111
|
+
send(findRoot(options.toaster), "toast:show", {
|
|
112
|
+
...toRuntime({ kind: "info", ...options }),
|
|
113
|
+
id,
|
|
114
|
+
});
|
|
115
|
+
return id;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Change a toast that is still showing. */
|
|
119
|
+
toast.update = (id: string, patch: ToastUpdateOptions) =>
|
|
120
|
+
send(findRoot(patch.toaster), "toast:update", { ...toRuntime(patch), id });
|
|
121
|
+
|
|
122
|
+
/** Close one toast. */
|
|
123
|
+
toast.dismiss = (id: string, toaster?: string | HTMLElement) =>
|
|
124
|
+
send(findRoot(toaster), "toast:dismiss", { id });
|
|
125
|
+
|
|
126
|
+
/** Close every toast (what "Clear all" does). */
|
|
127
|
+
toast.clear = (toaster?: string | HTMLElement) => send(findRoot(toaster), "toast:clear");
|
package/src/lib/toggle-shared.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
2
|
|
|
3
|
-
export const TOGGLE_VARIANTS = ["default", "outline"] as const;
|
|
3
|
+
export const TOGGLE_VARIANTS = ["default", "outline", "ghost", "segmented"] as const;
|
|
4
4
|
export const TOGGLE_SIZES = ["xs", "default", "sm", "lg"] as const;
|
|
5
5
|
|
|
6
6
|
export type ToggleVariant = (typeof TOGGLE_VARIANTS)[number];
|
|
@@ -13,6 +13,14 @@ export const toggleVariants = cva(
|
|
|
13
13
|
variant: {
|
|
14
14
|
default: "bg-transparent",
|
|
15
15
|
outline: "border-input hover:bg-background-hover border bg-transparent shadow-xs",
|
|
16
|
+
// Pressed shows in the content only (e.g. a filled star): no pressed
|
|
17
|
+
// background, the normal hover background on hover.
|
|
18
|
+
ghost: "bg-transparent aria-pressed:bg-transparent aria-pressed:hover:bg-background-hover",
|
|
19
|
+
// C26 — outline, with the pressed item `muted` and in `foreground` text
|
|
20
|
+
// (a view switcher). Made for ToggleGroup, which also keeps it `muted`
|
|
21
|
+
// on hover; follows the runtime's `aria-pressed`.
|
|
22
|
+
segmented:
|
|
23
|
+
"border-input hover:bg-background-hover border bg-transparent shadow-xs aria-pressed:bg-muted aria-pressed:text-foreground",
|
|
16
24
|
},
|
|
17
25
|
size: {
|
|
18
26
|
xs: "h-7 min-w-7 px-1",
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace palette: the 12 decorative hues a workspace can be given, mapped to
|
|
3
|
+
* the Tailwind classes each coloured part uses. Backed by the `--workspace-*`
|
|
4
|
+
* tokens in globals.css.
|
|
5
|
+
*
|
|
6
|
+
* Literal class strings, so Tailwind generates them.
|
|
7
|
+
*
|
|
8
|
+
* - `solid` avatar background (white icon on it)
|
|
9
|
+
* - `text` the icon colour on a white or tinted avatar
|
|
10
|
+
* - `tint` the soft avatar background
|
|
11
|
+
* - `gradient` the large recent card: the hue at 50% to its deep shade at 50%,
|
|
12
|
+
* over a neutral grey, so it reads washed out rather than vivid.
|
|
13
|
+
* Add a direction yourself, e.g. `bg-linear-to-br`.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const WORKSPACE_COLORS = [
|
|
17
|
+
"purple",
|
|
18
|
+
"red",
|
|
19
|
+
"blue",
|
|
20
|
+
"emerald",
|
|
21
|
+
"orange",
|
|
22
|
+
"teal",
|
|
23
|
+
"indigo",
|
|
24
|
+
"amber",
|
|
25
|
+
"pink",
|
|
26
|
+
"sky",
|
|
27
|
+
"lime",
|
|
28
|
+
"slate",
|
|
29
|
+
] as const;
|
|
30
|
+
|
|
31
|
+
export type WorkspaceColor = (typeof WORKSPACE_COLORS)[number];
|
|
32
|
+
|
|
33
|
+
/** The colour a new workspace starts with. */
|
|
34
|
+
export const DEFAULT_WORKSPACE_COLOR: WorkspaceColor = "blue";
|
|
35
|
+
|
|
36
|
+
export interface WorkspaceSwatch {
|
|
37
|
+
solid: string;
|
|
38
|
+
text: string;
|
|
39
|
+
tint: string;
|
|
40
|
+
gradient: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const workspacePalette: Record<WorkspaceColor, WorkspaceSwatch> = {
|
|
44
|
+
purple: {
|
|
45
|
+
solid: "bg-workspace-purple",
|
|
46
|
+
text: "text-workspace-purple",
|
|
47
|
+
tint: "bg-workspace-purple-tint",
|
|
48
|
+
gradient: "bg-workspace-gradient-base from-workspace-purple/50 to-workspace-purple-deep/50",
|
|
49
|
+
},
|
|
50
|
+
red: {
|
|
51
|
+
solid: "bg-workspace-red",
|
|
52
|
+
text: "text-workspace-red",
|
|
53
|
+
tint: "bg-workspace-red-tint",
|
|
54
|
+
gradient: "bg-workspace-gradient-base from-workspace-red/50 to-workspace-red-deep/50",
|
|
55
|
+
},
|
|
56
|
+
blue: {
|
|
57
|
+
solid: "bg-workspace-blue",
|
|
58
|
+
text: "text-workspace-blue",
|
|
59
|
+
tint: "bg-workspace-blue-tint",
|
|
60
|
+
gradient: "bg-workspace-gradient-base from-workspace-blue/50 to-workspace-blue-deep/50",
|
|
61
|
+
},
|
|
62
|
+
emerald: {
|
|
63
|
+
solid: "bg-workspace-emerald",
|
|
64
|
+
text: "text-workspace-emerald",
|
|
65
|
+
tint: "bg-workspace-emerald-tint",
|
|
66
|
+
gradient: "bg-workspace-gradient-base from-workspace-emerald/50 to-workspace-emerald-deep/50",
|
|
67
|
+
},
|
|
68
|
+
orange: {
|
|
69
|
+
solid: "bg-workspace-orange",
|
|
70
|
+
text: "text-workspace-orange",
|
|
71
|
+
tint: "bg-workspace-orange-tint",
|
|
72
|
+
gradient: "bg-workspace-gradient-base from-workspace-orange/50 to-workspace-orange-deep/50",
|
|
73
|
+
},
|
|
74
|
+
teal: {
|
|
75
|
+
solid: "bg-workspace-teal",
|
|
76
|
+
text: "text-workspace-teal",
|
|
77
|
+
tint: "bg-workspace-teal-tint",
|
|
78
|
+
gradient: "bg-workspace-gradient-base from-workspace-teal/50 to-workspace-teal-deep/50",
|
|
79
|
+
},
|
|
80
|
+
indigo: {
|
|
81
|
+
solid: "bg-workspace-indigo",
|
|
82
|
+
text: "text-workspace-indigo",
|
|
83
|
+
tint: "bg-workspace-indigo-tint",
|
|
84
|
+
gradient: "bg-workspace-gradient-base from-workspace-indigo/50 to-workspace-indigo-deep/50",
|
|
85
|
+
},
|
|
86
|
+
amber: {
|
|
87
|
+
solid: "bg-workspace-amber",
|
|
88
|
+
text: "text-workspace-amber",
|
|
89
|
+
tint: "bg-workspace-amber-tint",
|
|
90
|
+
gradient: "bg-workspace-gradient-base from-workspace-amber/50 to-workspace-amber-deep/50",
|
|
91
|
+
},
|
|
92
|
+
pink: {
|
|
93
|
+
solid: "bg-workspace-pink",
|
|
94
|
+
text: "text-workspace-pink",
|
|
95
|
+
tint: "bg-workspace-pink-tint",
|
|
96
|
+
gradient: "bg-workspace-gradient-base from-workspace-pink/50 to-workspace-pink-deep/50",
|
|
97
|
+
},
|
|
98
|
+
sky: {
|
|
99
|
+
solid: "bg-workspace-sky",
|
|
100
|
+
text: "text-workspace-sky",
|
|
101
|
+
tint: "bg-workspace-sky-tint",
|
|
102
|
+
gradient: "bg-workspace-gradient-base from-workspace-sky/50 to-workspace-sky-deep/50",
|
|
103
|
+
},
|
|
104
|
+
lime: {
|
|
105
|
+
solid: "bg-workspace-lime",
|
|
106
|
+
text: "text-workspace-lime",
|
|
107
|
+
tint: "bg-workspace-lime-tint",
|
|
108
|
+
gradient: "bg-workspace-gradient-base from-workspace-lime/50 to-workspace-lime-deep/50",
|
|
109
|
+
},
|
|
110
|
+
slate: {
|
|
111
|
+
solid: "bg-workspace-slate",
|
|
112
|
+
text: "text-workspace-slate",
|
|
113
|
+
tint: "bg-workspace-slate-tint",
|
|
114
|
+
gradient: "bg-workspace-gradient-base from-workspace-slate/50 to-workspace-slate-deep/50",
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/** The brand gradient (primary to its deep blue), for brand-toned surfaces. Add a direction yourself. */
|
|
119
|
+
export const brandGradient = "from-primary to-chart-4";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the design tokens in `globals.css` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## Date 15th Oct 2026
|
|
6
|
+
## Workspace selection handover (C27)
|
|
7
|
+
|
|
8
|
+
### Type styles
|
|
9
|
+
|
|
10
|
+
- Three utilities (`@utility`) for page and section headings (D98–D101), so screens don't repeat the size, weight and colour:
|
|
11
|
+
- `type-page-greeting`: the page title as a greeting ("Good morning, …"), `font-heading` 24/32 (`text-2xl`), semibold, `tracking-tight`, `foreground`.
|
|
12
|
+
- `type-section-title`: a section heading ("Recents", "All workspaces"), 16/24 (`text-base`) semibold, `foreground`.
|
|
13
|
+
- `type-section-meta`: the small muted text beside a section heading (a subtext, a count), 14/20 (`text-sm`) regular, `muted-foreground`; resets weight and tracking, so it can sit inside the heading (on its baseline: `flex items-baseline gap-2` on the heading).
|
|
14
|
+
- Named `type-*` rather than `text-*`, so tailwind-merge (`cn()`) doesn't read them as a text colour or size and drop them next to one. Layout (baseline row, gaps) stays with the screen.
|
|
15
|
+
- Replaces the workspace-selection screen's `sectionHeading` / `besideHeading` class strings and the greeting's classes. **Not in Figma yet.**
|
|
16
|
+
- Storybook: a "Type styles" section on Foundations › Fonts.
|
|
17
|
+
|
|
18
|
+
## Date 15th Oct 2026
|
|
19
|
+
## Workspace selection handover (N1, N8, N19, C17)
|
|
20
|
+
|
|
21
|
+
### Feedback colours (gaps G7, G13)
|
|
22
|
+
|
|
23
|
+
- Uses the existing `--warning`, `--warning-foreground` and `--callout-background-*` tokens (utilities `*-warning`, `*-callout-info/-warning/-error`).
|
|
24
|
+
- Added `--callout-foreground-warning` (Yellow/800) and `--callout-foreground-error` (Red/700); Yellow/300 and Red/300 in dark mode: darker text that reads on the callout backgrounds. **Not in Figma yet.**
|
|
25
|
+
|
|
26
|
+
### Favourite (gap G3)
|
|
27
|
+
|
|
28
|
+
- `--favorite` (Yellow/500, utility `*-favorite`): the starred colour. Separate from `badge-warning` and `warning`, which were being borrowed for it. **Not in Figma yet.**
|
|
29
|
+
|
|
30
|
+
### Workspace palette (gap G4)
|
|
31
|
+
|
|
32
|
+
- 12 decorative hues for workspace avatars and cards: purple, red, blue, emerald, orange, teal, indigo, amber, pink, sky, lime, slate. Each has `--workspace-{hue}` (600: solid background and icon colour), `--workspace-{hue}-tint` (100: soft background) and `--workspace-{hue}-deep` (800: gradient end). `--workspace-gradient-base` (Zinc/600) sits under the large card's gradient. **Not in Figma yet.**
|
|
33
|
+
- `lib/workspace-palette.ts` maps each hue to its class strings (`solid`, `text`, `tint`, `gradient`), plus `WORKSPACE_COLORS`, `DEFAULT_WORKSPACE_COLOR` (`blue`) and `brandGradient` (`from-primary to-chart-4`). It's a drop-in replacement for the screen's `palette.ts`.
|
|
34
|
+
- No dark-mode values for the palette yet.
|
|
35
|
+
- Storybook: a "Workspace palette" section on Foundations › Colors.
|
package/src/styles/globals.css
CHANGED
|
@@ -42,6 +42,46 @@
|
|
|
42
42
|
--color-callout-info: var(--callout-background-info);
|
|
43
43
|
--color-callout-warning: var(--callout-background-warning);
|
|
44
44
|
--color-callout-error: var(--callout-background-error);
|
|
45
|
+
--color-callout-foreground-warning: var(--callout-foreground-warning);
|
|
46
|
+
--color-callout-foreground-error: var(--callout-foreground-error);
|
|
47
|
+
--color-favorite: var(--favorite);
|
|
48
|
+
--color-workspace-gradient-base: var(--workspace-gradient-base);
|
|
49
|
+
--color-workspace-purple: var(--workspace-purple);
|
|
50
|
+
--color-workspace-purple-tint: var(--workspace-purple-tint);
|
|
51
|
+
--color-workspace-purple-deep: var(--workspace-purple-deep);
|
|
52
|
+
--color-workspace-red: var(--workspace-red);
|
|
53
|
+
--color-workspace-red-tint: var(--workspace-red-tint);
|
|
54
|
+
--color-workspace-red-deep: var(--workspace-red-deep);
|
|
55
|
+
--color-workspace-blue: var(--workspace-blue);
|
|
56
|
+
--color-workspace-blue-tint: var(--workspace-blue-tint);
|
|
57
|
+
--color-workspace-blue-deep: var(--workspace-blue-deep);
|
|
58
|
+
--color-workspace-emerald: var(--workspace-emerald);
|
|
59
|
+
--color-workspace-emerald-tint: var(--workspace-emerald-tint);
|
|
60
|
+
--color-workspace-emerald-deep: var(--workspace-emerald-deep);
|
|
61
|
+
--color-workspace-orange: var(--workspace-orange);
|
|
62
|
+
--color-workspace-orange-tint: var(--workspace-orange-tint);
|
|
63
|
+
--color-workspace-orange-deep: var(--workspace-orange-deep);
|
|
64
|
+
--color-workspace-teal: var(--workspace-teal);
|
|
65
|
+
--color-workspace-teal-tint: var(--workspace-teal-tint);
|
|
66
|
+
--color-workspace-teal-deep: var(--workspace-teal-deep);
|
|
67
|
+
--color-workspace-indigo: var(--workspace-indigo);
|
|
68
|
+
--color-workspace-indigo-tint: var(--workspace-indigo-tint);
|
|
69
|
+
--color-workspace-indigo-deep: var(--workspace-indigo-deep);
|
|
70
|
+
--color-workspace-amber: var(--workspace-amber);
|
|
71
|
+
--color-workspace-amber-tint: var(--workspace-amber-tint);
|
|
72
|
+
--color-workspace-amber-deep: var(--workspace-amber-deep);
|
|
73
|
+
--color-workspace-pink: var(--workspace-pink);
|
|
74
|
+
--color-workspace-pink-tint: var(--workspace-pink-tint);
|
|
75
|
+
--color-workspace-pink-deep: var(--workspace-pink-deep);
|
|
76
|
+
--color-workspace-sky: var(--workspace-sky);
|
|
77
|
+
--color-workspace-sky-tint: var(--workspace-sky-tint);
|
|
78
|
+
--color-workspace-sky-deep: var(--workspace-sky-deep);
|
|
79
|
+
--color-workspace-lime: var(--workspace-lime);
|
|
80
|
+
--color-workspace-lime-tint: var(--workspace-lime-tint);
|
|
81
|
+
--color-workspace-lime-deep: var(--workspace-lime-deep);
|
|
82
|
+
--color-workspace-slate: var(--workspace-slate);
|
|
83
|
+
--color-workspace-slate-tint: var(--workspace-slate-tint);
|
|
84
|
+
--color-workspace-slate-deep: var(--workspace-slate-deep);
|
|
45
85
|
--color-badge-success: var(--badge-success);
|
|
46
86
|
--color-badge-success-foreground: var(--badge-success-foreground);
|
|
47
87
|
--color-badge-warning: var(--badge-warning);
|
|
@@ -114,6 +154,51 @@
|
|
|
114
154
|
--callout-background-info: var(--primary-50);
|
|
115
155
|
--callout-background-warning: #fefce8;
|
|
116
156
|
--callout-background-error: #fef2f2;
|
|
157
|
+
/* Darker text that reads on the callout backgrounds. */
|
|
158
|
+
--callout-foreground-warning: var(--color-yellow-800);
|
|
159
|
+
--callout-foreground-error: var(--color-red-700);
|
|
160
|
+
/* Favourite / starred state. Separate from the badge and warning yellows so they can change independently. */
|
|
161
|
+
--favorite: var(--color-yellow-500);
|
|
162
|
+
/* Workspace palette: 12 decorative hues for workspace avatars and cards.
|
|
163
|
+
{hue} = solid background / icon colour, {hue}-tint = soft background, {hue}-deep = gradient end.
|
|
164
|
+
The large card gradient is `{hue}/50 -> {hue}-deep/50` over `workspace-gradient-base`. */
|
|
165
|
+
--workspace-gradient-base: var(--color-zinc-600);
|
|
166
|
+
--workspace-purple: var(--color-purple-600);
|
|
167
|
+
--workspace-purple-tint: var(--color-purple-100);
|
|
168
|
+
--workspace-purple-deep: var(--color-purple-800);
|
|
169
|
+
--workspace-red: var(--color-red-600);
|
|
170
|
+
--workspace-red-tint: var(--color-red-100);
|
|
171
|
+
--workspace-red-deep: var(--color-red-800);
|
|
172
|
+
--workspace-blue: var(--color-blue-600);
|
|
173
|
+
--workspace-blue-tint: var(--color-blue-100);
|
|
174
|
+
--workspace-blue-deep: var(--color-blue-800);
|
|
175
|
+
--workspace-emerald: var(--color-emerald-600);
|
|
176
|
+
--workspace-emerald-tint: var(--color-emerald-100);
|
|
177
|
+
--workspace-emerald-deep: var(--color-emerald-800);
|
|
178
|
+
--workspace-orange: var(--color-orange-600);
|
|
179
|
+
--workspace-orange-tint: var(--color-orange-100);
|
|
180
|
+
--workspace-orange-deep: var(--color-orange-800);
|
|
181
|
+
--workspace-teal: var(--color-teal-600);
|
|
182
|
+
--workspace-teal-tint: var(--color-teal-100);
|
|
183
|
+
--workspace-teal-deep: var(--color-teal-800);
|
|
184
|
+
--workspace-indigo: var(--color-indigo-600);
|
|
185
|
+
--workspace-indigo-tint: var(--color-indigo-100);
|
|
186
|
+
--workspace-indigo-deep: var(--color-indigo-800);
|
|
187
|
+
--workspace-amber: var(--color-amber-600);
|
|
188
|
+
--workspace-amber-tint: var(--color-amber-100);
|
|
189
|
+
--workspace-amber-deep: var(--color-amber-800);
|
|
190
|
+
--workspace-pink: var(--color-pink-600);
|
|
191
|
+
--workspace-pink-tint: var(--color-pink-100);
|
|
192
|
+
--workspace-pink-deep: var(--color-pink-800);
|
|
193
|
+
--workspace-sky: var(--color-sky-600);
|
|
194
|
+
--workspace-sky-tint: var(--color-sky-100);
|
|
195
|
+
--workspace-sky-deep: var(--color-sky-800);
|
|
196
|
+
--workspace-lime: var(--color-lime-600);
|
|
197
|
+
--workspace-lime-tint: var(--color-lime-100);
|
|
198
|
+
--workspace-lime-deep: var(--color-lime-800);
|
|
199
|
+
--workspace-slate: var(--color-slate-600);
|
|
200
|
+
--workspace-slate-tint: var(--color-slate-100);
|
|
201
|
+
--workspace-slate-deep: var(--color-slate-800);
|
|
117
202
|
--badge-success: var(--color-green-700);
|
|
118
203
|
--badge-success-foreground: var(--color-white);
|
|
119
204
|
--badge-warning: var(--color-yellow-500);
|
|
@@ -173,6 +258,8 @@
|
|
|
173
258
|
--callout-background-info: color-mix(in oklab, var(--primary-500) 15%, var(--background));
|
|
174
259
|
--callout-background-warning: color-mix(in oklab, #eab308 12%, var(--background));
|
|
175
260
|
--callout-background-error: color-mix(in oklab, var(--color-red-600) 15%, var(--background));
|
|
261
|
+
--callout-foreground-warning: var(--color-yellow-300);
|
|
262
|
+
--callout-foreground-error: var(--color-red-300);
|
|
176
263
|
--border: oklch(1 0 0 / 10%);
|
|
177
264
|
--input: oklch(1 0 0 / 15%);
|
|
178
265
|
--ring: oklch(0.556 0 0);
|
|
@@ -193,6 +280,28 @@
|
|
|
193
280
|
--table-row-selected: color-mix(in oklab, var(--primary-500) 20%, var(--background));
|
|
194
281
|
}
|
|
195
282
|
|
|
283
|
+
/*
|
|
284
|
+
* Type styles (C27, D98–D101): page and section headings in one class each,
|
|
285
|
+
* so screens don't repeat the size, weight and colour.
|
|
286
|
+
* - type-page-greeting: the page title as a greeting, 24/32 heading font, semibold.
|
|
287
|
+
* - type-section-title: a section heading ("Recents", "All workspaces"), 16/24 semibold.
|
|
288
|
+
* - type-section-meta: the small muted text beside a section heading (a subtext,
|
|
289
|
+
* a count), 14/20 regular; resets weight and tracking when nested in the title.
|
|
290
|
+
* Named type-* rather than text-*, so tailwind-merge doesn't read them as a
|
|
291
|
+
* text colour or size and drop them next to one in cn().
|
|
292
|
+
*/
|
|
293
|
+
@utility type-page-greeting {
|
|
294
|
+
@apply font-heading text-2xl font-semibold tracking-tight text-foreground;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@utility type-section-title {
|
|
298
|
+
@apply text-base font-semibold text-foreground;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
@utility type-section-meta {
|
|
302
|
+
@apply text-sm font-normal tracking-normal text-muted-foreground;
|
|
303
|
+
}
|
|
304
|
+
|
|
196
305
|
@layer base {
|
|
197
306
|
* {
|
|
198
307
|
@apply border-border outline-ring/50;
|