@cl-light-ds/ui 0.3.0 → 0.5.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 +20 -18
- package/src/components/alert/Alert.astro +8 -2
- package/src/components/alert/CHANGELOG.md +9 -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/callout/CHANGELOG.md +32 -0
- package/src/components/callout/Callout.astro +147 -0
- package/src/components/callout/CalloutDescription.astro +16 -0
- package/src/components/callout/CalloutTitle.astro +16 -0
- package/src/components/callout/index.ts +3 -0
- package/src/components/card/CHANGELOG.md +9 -0
- package/src/components/card/Card.astro +22 -0
- package/src/components/combobox/CHANGELOG.md +14 -0
- package/src/components/combobox/ComboboxTrigger.astro +31 -1
- package/src/components/command-search/CHANGELOG.md +27 -0
- package/src/components/command-search/CommandSearch.astro +515 -0
- package/src/components/command-search/CommandSearchGroup.astro +32 -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 +13 -0
- package/src/components/dialog/DialogClose.astro +26 -12
- package/src/components/dropdown-menu/CHANGELOG.md +7 -0
- 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/input/CHANGELOG.md +15 -0
- package/src/components/input/InputOTP.astro +211 -0
- package/src/components/input/index.ts +1 -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/logo/CHANGELOG.md +17 -0
- package/src/components/logo/Logo.astro +90 -0
- package/src/components/logo/index.ts +3 -0
- package/src/components/logo/logo-paths.ts +57 -0
- package/src/components/notifications-menu/CHANGELOG.md +22 -0
- package/src/components/notifications-menu/NotificationsMenu.astro +374 -0
- package/src/components/notifications-menu/NotificationsMenuItem.astro +129 -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 +16 -0
- package/src/components/option-card/OptionCard.astro +135 -0
- package/src/components/option-card/index.ts +1 -0
- package/src/components/organisms/top-bar/CHANGELOG.md +21 -0
- package/src/components/organisms/top-bar/TopBar.astro +264 -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 +73 -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/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/table/CHANGELOG.md +9 -0
- package/src/components/table/TableCell.astro +6 -0
- package/src/components/table/TableHead.astro +5 -1
- package/src/components/table/TableRow.astro +3 -1
- package/src/components/table/table-cell-variants.ts +2 -0
- 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/lib/command-search.ts +73 -0
- package/src/lib/loading-overlay.ts +174 -0
- package/src/lib/toast.ts +127 -0
- package/src/lib/toggle-shared.ts +4 -1
- package/src/lib/workspace-palette.ts +119 -0
- package/src/styles/CHANGELOG.md +22 -0
- package/src/styles/globals.css +100 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* One result row in a `CommandSearch`: optional media (an icon or avatar), the
|
|
4
|
+
* label, and optional muted text on the right (`meta` slot, e.g. "in Acme
|
|
5
|
+
* Finance"). Highlighted while active (arrow keys or hover); Enter or a click
|
|
6
|
+
* chooses it.
|
|
7
|
+
*
|
|
8
|
+
* Searching matches `label` and `keywords` (case-insensitive, anywhere in the
|
|
9
|
+
* text), so give every item a `label`. `value` identifies it in
|
|
10
|
+
* `command-search:select`; it defaults to the label, so pass one when two items
|
|
11
|
+
* can share a name.
|
|
12
|
+
*/
|
|
13
|
+
import { cn } from "@cl-light-ds/ui/lib/utils";
|
|
14
|
+
import type { HTMLAttributes } from "astro/types";
|
|
15
|
+
|
|
16
|
+
import { commandSearchItemClasses, commandSearchLabelClasses, commandSearchMetaClasses } from "./classes";
|
|
17
|
+
|
|
18
|
+
interface Props extends HTMLAttributes<"div"> {
|
|
19
|
+
/** The text searched and shown (the default slot can replace what is shown). */
|
|
20
|
+
label: string;
|
|
21
|
+
/** Unique value, sent with `command-search:select`. Defaults to `label`. */
|
|
22
|
+
value?: string;
|
|
23
|
+
/** More terms that find this item. */
|
|
24
|
+
keywords?: string[];
|
|
25
|
+
/** Navigate here when chosen. */
|
|
26
|
+
href?: string;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
class?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
label,
|
|
33
|
+
value = label,
|
|
34
|
+
keywords = [],
|
|
35
|
+
href,
|
|
36
|
+
disabled = false,
|
|
37
|
+
class: className = "",
|
|
38
|
+
...rest
|
|
39
|
+
} = Astro.props as Props;
|
|
40
|
+
|
|
41
|
+
const hasMedia = Astro.slots.has("media");
|
|
42
|
+
const hasMeta = Astro.slots.has("meta");
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
<div
|
|
46
|
+
data-slot="command-item"
|
|
47
|
+
data-value={value}
|
|
48
|
+
data-label={label}
|
|
49
|
+
data-keywords={keywords.length ? keywords.join(",") : undefined}
|
|
50
|
+
data-href={href}
|
|
51
|
+
data-disabled={disabled ? "true" : undefined}
|
|
52
|
+
class={cn(commandSearchItemClasses, className)}
|
|
53
|
+
{...rest}
|
|
54
|
+
>
|
|
55
|
+
{hasMedia && <slot name="media" />}
|
|
56
|
+
<span class={commandSearchLabelClasses}><slot>{label}</slot></span>
|
|
57
|
+
{
|
|
58
|
+
hasMeta && (
|
|
59
|
+
<span class={commandSearchMetaClasses}>
|
|
60
|
+
<slot name="meta" />
|
|
61
|
+
</span>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class strings shared by the Astro parts and the results the script renders
|
|
3
|
+
* from `setCommandSearchResults()`, so both look the same.
|
|
4
|
+
*/
|
|
5
|
+
export const commandSearchGroupClasses = "flex flex-col gap-1";
|
|
6
|
+
|
|
7
|
+
export const commandSearchHeadingClasses =
|
|
8
|
+
"text-muted-foreground flex items-baseline gap-2 px-2 pt-1 text-xs font-semibold tracking-wide uppercase";
|
|
9
|
+
|
|
10
|
+
export const commandSearchCountClasses = "font-normal tabular-nums";
|
|
11
|
+
|
|
12
|
+
export const commandSearchItemClasses =
|
|
13
|
+
"hover:bg-background-hover data-[selected=true]:bg-background-hover aria-disabled:pointer-events-none aria-disabled:opacity-50 flex cursor-pointer items-center gap-3 rounded-md px-2 py-2 text-sm transition-colors outline-none";
|
|
14
|
+
|
|
15
|
+
export const commandSearchLabelClasses = "min-w-0 flex-1 truncate";
|
|
16
|
+
|
|
17
|
+
export const commandSearchMetaClasses =
|
|
18
|
+
"text-muted-foreground flex max-w-56 min-w-0 shrink-0 items-center gap-1.5 truncate text-xs";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as CommandSearch } from "./CommandSearch.astro";
|
|
2
|
+
export { default as CommandSearchGroup } from "./CommandSearchGroup.astro";
|
|
3
|
+
export { default as CommandSearchItem } from "./CommandSearchItem.astro";
|
|
4
|
+
export {
|
|
5
|
+
openCommandSearch,
|
|
6
|
+
closeCommandSearch,
|
|
7
|
+
setCommandSearchResults,
|
|
8
|
+
} from "../../lib/command-search";
|
|
9
|
+
export type {
|
|
10
|
+
CommandSearchResultGroup,
|
|
11
|
+
CommandSearchResultItem,
|
|
12
|
+
} from "../../lib/command-search";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="184" height="124" viewBox="-12 -12 184 124" fill="none" xmlns:c2pa="http://c2pa.org/manifest"><metadata><c2pa:manifest>AAAWgmp1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAABZcanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46YzJwYTplODIyOThlNC1jNGQ2LTQwYTQtOGU3Ny1hYWY2OTcxYjM2OTIAAAADl2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAALxqdW1iAAAARGp1bWRjYm9yABEAEIAAAKoAOJtxE2MycGEuaW5ncmVkaWVudC52MwAAAAAYYzJzaKqugmJMsqYC8viyOBbRbhIAAABwY2JvcqNpZGM6Zm9ybWF0bWltYWdlL3N2Zyt4bWxqaW5zdGFuY2VJRHgseG1wOmlpZDo0MWIxMTE5NC02ZTQ0LTRlMzUtOTU5MS0xYjY1M2ViNWUyNTJscmVsYXRpb25zaGlwaHBhcmVudE9mAAAB4mp1bWIAAABBanVtZGNib3IAEQAQgAAAqgA4m3ETYzJwYS5hY3Rpb25zLnYyAAAAABhjMnNouXZVAYt+XHRTFpV6GfvZOgAAAZljYm9yomdhY3Rpb25zgqJmYWN0aW9ua2MycGEub3BlbmVkanBhcmFtZXRlcnOha2luZ3JlZGllbnRzgaJjdXJseC1zZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmluZ3JlZGllbnQudjNkaGFzaFggVgKr/4T9xsUXed1EvB+dGw4hkEVHK5LpA88frFSdO46kZmFjdGlvbngdY29tLmFudGhyb3BpYy5jbGF1ZGUucHJvdmlkZWRqcGFyYW1ldGVyc6F4H2NvbS5hbnRocm9waWMub3JpZ2luLWNvbmZpZGVuY2VndW5rbm93bmtkZXNjcmlwdGlvbnhmQ2xhdWRlIHByb3ZpZGVkIHRoaXMgZmlsZSBhdCB0aGUgcmVxdWVzdCBvZiBhIHVzZXIgYW5kIG1heSBoYXZlIGNyZWF0ZWQgb3IgbW9kaWZpZWQgdGhlIGZpbGUgY29udGVudHMubXNvZnR3YXJlQWdlbnShZG5hbWVmQ2xhdWRlcmFsbEFjdGlvbnNJbmNsdWRlZPUAAADIanVtYgAAAEBqdW1kY2JvcgARABCAAACqADibcRNjMnBhLmhhc2guZGF0YQAAAAAYYzJzaNb7nH0x+zMDR8g/a81tYxUAAACAY2JvcqVjYWxnZnNoYTI1NmNwYWRNAAAAAAAAAAAAAAAAAGRoYXNoWCB8IybuiUW/D1GR1OoeQ940FnLg0RBFnD1vqhoG+GGrd2RuYW1lbmp1bWJmIG1hbmlmZXN0amV4Y2x1c2lvbnOBomVzdGFydBimZmxlbmd0aBkeBAAAAj5qdW1iAAAAJ2p1bWRjMmNsABEAEIAAAKoAOJtxA2MycGEuY2xhaW0udjIAAAACD2Nib3KlY2FsZ2ZzaGEyNTZpc2lnbmF0dXJleE1zZWxmI2p1bWJmPS9jMnBhL3VybjpjMnBhOmU4MjI5OGU0LWM0ZDYtNDBhNC04ZTc3LWFhZjY5NzFiMzY5Mi9jMnBhLnNpZ25hdHVyZWppbnN0YW5jZUlEeCx4bXA6aWlkOjExNmJiZmVjLWQxNjEtNDM1YS1iNzkxLTM1YjRlNTM4MzljYXJjcmVhdGVkX2Fzc2VydGlvbnODomN1cmx4LXNlbGYjanVtYmY9YzJwYS5hc3NlcnRpb25zL2MycGEuaW5ncmVkaWVudC52M2RoYXNoWCBWAqv/hP3GxRd53US8H50bDiGQRUcrkukDzx+sVJ07jqJjdXJseCpzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnMudjJkaGFzaFggWNJwmATXeq3w/IjLwhFkIQQ1fvC8gXIQ/CRzxbJAz4aiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFgg3x7o2h9I/3508c0ufWUiNo2ld5HoEd8e5vBDPLAJa0t0Y2xhaW1fZ2VuZXJhdG9yX2luZm+jZG5hbWVvQW50aHJvcGljIEZpbGVzZ3ZlcnNpb25lMS4wLjBrc3BlY1ZlcnNpb25lMi40LjAAABA4anVtYgAAAChqdW1kYzJjcwARABCAAACqADibcQNjMnBhLnNpZ25hdHVyZQAAABAIY2JvctKEWQISogEmGCFZAgowggIGMIIBjaADAgECAhRA5aAK7sI50L64g/oGQgU9Z1UTADAKBggqhkjOPQQDAzBJMRcwFQYDVQQKEw5BbnRocm9waWMsIFBCQzEuMCwGA1UEAxMlQW50aHJvcGljIENvbnRlbnQgQ3JlZGVudGlhbHMgUm9vdCBDQTAeFw0yNjA4MDcxODQzNTZaFw0yODA4MDYxOTQzNTZaMEQxFzAVBgNVBAoTDkFudGhyb3BpYywgUEJDMSkwJwYDVQQDEyBBbnRocm9waWMgQ2xhdWRlIENvbnRlbnQgU2lnbmluZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJh6CmvLUBgFFNU0vUKlOVtE6djd17L5SuwX0LemFisBM3dkd/3cyjxFA3Qo5S46fX0/ihY0VZ7mfb9KF703t5OjWDBWMA4GA1UdDwEB/wQEAwIHgDAVBgNVHSUEDjAMBgorBgEEAYPoXgIBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUzlHiBIFOZFsj+OPEz5o+nMHXXMIwCgYIKoZIzj0EAwMDZwAwZAIwMXMdFJ4BetLLVY7ORuE9noqbbAZOZn/aArXyTwFAZfKrPzxF2vPoJNf1+UCdg1XGAjBwX1zd9WGqYkqmL5SFqw1QySjr1zJfpJM9+1rdDwSPLMOPOjKuiXjoU/pUUeG9RwmhY3BhZFkNngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZYQBQ6fFVaIySaTkZAvfiIN0Vu6miBN8tscscJnyxn5eEUXN2x49nEHZ+/F/hQydOi3j5/kryWAn8JzV93uuuUbDg=</c2pa:manifest></metadata>
|
|
2
|
+
<defs>
|
|
3
|
+
<filter id="sBack" x="-30%" y="-30%" width="160%" height="160%" color-interpolation-filters="sRGB">
|
|
4
|
+
<feDropShadow dx="0" dy="1.5" stdDeviation="2" flood-color="#051729" flood-opacity="0.05"></feDropShadow>
|
|
5
|
+
</filter>
|
|
6
|
+
<filter id="sFront" x="-40%" y="-30%" width="180%" height="170%" color-interpolation-filters="sRGB">
|
|
7
|
+
<feDropShadow dx="0" dy="5" stdDeviation="6" flood-color="#051729" flood-opacity="0.10"></feDropShadow>
|
|
8
|
+
</filter>
|
|
9
|
+
<filter id="sLens" x="-60%" y="-60%" width="220%" height="220%" color-interpolation-filters="sRGB">
|
|
10
|
+
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#3785E0" flood-opacity="0.28"></feDropShadow>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<circle cx="80" cy="50" r="44" stroke="#F5F9FE" stroke-width="12"></circle>
|
|
14
|
+
<circle cx="80" cy="50" r="24" stroke="#EBF3FC" stroke-width="10"></circle>
|
|
15
|
+
<g transform="rotate(-12 44 52)">
|
|
16
|
+
<g filter="url(#sBack)"><rect x="22" y="26" width="44" height="52" rx="8" fill="#FFFFFF"></rect></g>
|
|
17
|
+
<rect x="22.5" y="26.5" width="43" height="51" rx="7.5" stroke="#09090B" stroke-opacity="0.06"></rect>
|
|
18
|
+
<rect x="28" y="32" width="14" height="14" rx="4" fill="#D7E7F9"></rect>
|
|
19
|
+
<rect x="28" y="54" width="24" height="4" rx="2" fill="#E4E4E7"></rect>
|
|
20
|
+
<rect x="28" y="62" width="16" height="4" rx="2" fill="#F4F4F5"></rect>
|
|
21
|
+
</g>
|
|
22
|
+
<g transform="rotate(12 116 52)">
|
|
23
|
+
<g filter="url(#sBack)"><rect x="94" y="26" width="44" height="52" rx="8" fill="#FFFFFF"></rect></g>
|
|
24
|
+
<rect x="94.5" y="26.5" width="43" height="51" rx="7.5" stroke="#09090B" stroke-opacity="0.06"></rect>
|
|
25
|
+
<rect x="100" y="34" width="28" height="4" rx="2" fill="#E4E4E7"></rect>
|
|
26
|
+
<rect x="100" y="42" width="32" height="4" rx="2" fill="#F4F4F5"></rect>
|
|
27
|
+
<rect x="100" y="50" width="22" height="4" rx="2" fill="#F4F4F5"></rect>
|
|
28
|
+
<rect x="100" y="58" width="28" height="4" rx="2" fill="#F4F4F5"></rect>
|
|
29
|
+
</g>
|
|
30
|
+
<g filter="url(#sFront)"><rect x="56" y="18" width="48" height="58" rx="9" fill="#FFFFFF"></rect></g>
|
|
31
|
+
<rect x="56.5" y="18.5" width="47" height="57" rx="8.5" stroke="#09090B" stroke-opacity="0.06"></rect>
|
|
32
|
+
<rect x="62" y="24" width="36" height="22" rx="5" fill="#EBF3FC"></rect>
|
|
33
|
+
<path d="M77 30.5 L84.5 35 L77 39.5 Z" fill="#87B6EC" stroke="#87B6EC" stroke-width="1.5" stroke-linejoin="round"></path>
|
|
34
|
+
<rect x="62" y="53" width="28" height="4" rx="2" fill="#E4E4E7"></rect>
|
|
35
|
+
<rect x="62" y="61" width="18" height="4" rx="2" fill="#F4F4F5"></rect>
|
|
36
|
+
<g filter="url(#sLens)">
|
|
37
|
+
<line x1="113.5" y1="79.5" x2="122" y2="88" stroke="#1F5FAA" stroke-width="6" stroke-linecap="round"></line>
|
|
38
|
+
<circle cx="104" cy="70" r="13" fill="#FFFFFF" stroke="#3785E0" stroke-width="4"></circle>
|
|
39
|
+
</g>
|
|
40
|
+
<line x1="100" y1="66" x2="108" y2="74" stroke="#87B6EC" stroke-width="2.2" stroke-linecap="round"></line>
|
|
41
|
+
<line x1="108" y1="66" x2="100" y2="74" stroke="#87B6EC" stroke-width="2.2" stroke-linecap="round"></line>
|
|
42
|
+
</svg>
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the `Dialog` component family (`Dialog`, `DialogTrigger`, `DialogContent`, `DialogOverlay`, `DialogHeader`, `DialogFooter`, `DialogTitle`, `DialogDescription`, `DialogClose`) are documented in this file.
|
|
4
4
|
|
|
5
|
+
## Date 15th Oct 2026
|
|
6
|
+
## Workspace selection handover (C9, C16; gap G15)
|
|
7
|
+
|
|
8
|
+
### `DialogClose`
|
|
9
|
+
|
|
10
|
+
- **`asChild` (C9):** `<DialogClose asChild><Button variant="outline">Cancel</Button></DialogClose>` closes the dialog with your own button. The wrapper is `display: contents`. Without it, wrapping a Button nested a button in a button.
|
|
11
|
+
- **✕ hover (C16):** `hover:bg-background-button-hover` (zinc-200). The ghost hover (zinc-100) didn't show on light grey surfaces.
|
|
12
|
+
|
|
13
|
+
### Storybook
|
|
14
|
+
|
|
15
|
+
- "Cancel with DialogClose asChild" preview.
|
|
16
|
+
|
|
17
|
+
|
|
5
18
|
## Earlier (commit `c3cec7d`, undocumented at the time)
|
|
6
19
|
|
|
7
20
|
- `DialogContent`: `rounded-xl` → `rounded-lg` (Figma binds 8px radius).
|
|
@@ -5,19 +5,33 @@ import Button from "../button/Button.astro";
|
|
|
5
5
|
|
|
6
6
|
interface Props extends HTMLAttributes<"button"> {
|
|
7
7
|
class?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Radix-like: render a wrapper so your own element closes the dialog, e.g. a
|
|
10
|
+
* Cancel `<Button>`. The wrapper is `display: contents`, so the child lays out
|
|
11
|
+
* as if it were placed directly.
|
|
12
|
+
*/
|
|
13
|
+
asChild?: boolean;
|
|
8
14
|
}
|
|
9
15
|
|
|
10
|
-
const { class: className = "", ...rest } = Astro.props as Props;
|
|
16
|
+
const { class: className = "", asChild = false, ...rest } = Astro.props as Props;
|
|
11
17
|
---
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
{
|
|
20
|
+
asChild ? (
|
|
21
|
+
<div data-slot="dialog-close" data-dialog-close data-as-child class={cn("contents", className)}>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
24
|
+
) : (
|
|
25
|
+
<Button
|
|
26
|
+
{...rest}
|
|
27
|
+
data-slot="dialog-close"
|
|
28
|
+
data-dialog-close
|
|
29
|
+
variant="ghost"
|
|
30
|
+
size="icon-sm"
|
|
31
|
+
class={cn("absolute top-2 right-2 hover:bg-background-button-hover", className)}
|
|
32
|
+
>
|
|
33
|
+
<slot />
|
|
34
|
+
{!Astro.slots.has("default") && <span class="sr-only">Close</span>}
|
|
35
|
+
</Button>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the `DropdownMenu` component will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## Date 15th Oct 2026
|
|
6
|
+
## Workspace selection handover (C17, gap G7)
|
|
7
|
+
|
|
8
|
+
### States
|
|
9
|
+
|
|
10
|
+
- `destructive` item hover is now `bg-callout-error` (`--callout-background-error`, Figma Red/50), was the neutral `background-hover`. The workspace-selection screen overrode it with `destructive/10`, which this replaces. Dark mode keeps `destructive/20`.
|
|
11
|
+
|
|
5
12
|
## Date 10th Sep 2026
|
|
6
13
|
## Figma alignment (node 2329-6521, prop table 7392-10142)
|
|
7
14
|
|
|
@@ -11,7 +11,7 @@ export const itemVariants = cva(
|
|
|
11
11
|
variant: {
|
|
12
12
|
default: "p-2 text-xs font-semibold text-foreground hover:bg-background-hover hover:text-foreground",
|
|
13
13
|
destructive:
|
|
14
|
-
"p-2 text-xs font-semibold text-destructive hover:bg-
|
|
14
|
+
"p-2 text-xs font-semibold text-destructive hover:bg-callout-error hover:text-destructive dark:hover:bg-destructive/20 [&_svg]:text-destructive",
|
|
15
15
|
category: "pointer-events-none gap-1 pt-1 pr-1 pb-0 pl-1 text-xs font-medium text-muted-foreground",
|
|
16
16
|
},
|
|
17
17
|
},
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `EmptyState` component will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## Date 15th Oct 2026
|
|
6
|
+
## Workspace selection handover (N15)
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- `EmptyState`: illustration (or icon), title, text and an optional action, centred.
|
|
11
|
+
- `size="page"`: 280×200 illustrations, 18px semibold title (`h2`), 14px text, 16px gaps, `py-12`.
|
|
12
|
+
- `size="menu"`: 144×104 / 184×124 illustrations, 14px medium title (`p`), 12px text, 8px gaps, `py-10`.
|
|
13
|
+
- `variant="panel"`: on a white (`bg-background`) dashed, rounded panel, for card grids (D188, D202). `plain` (default) has no frame, e.g. inside `TableEmpty` or a popover.
|
|
14
|
+
- `illustration`: built-in name; `icon`: a Lucide component in a 48px muted circle (the reference's "no favourites" state); `illustration` slot for custom artwork.
|
|
15
|
+
- `title` / `description` props or slots, `titleAs` to change the heading element, `action` slot for buttons. Other attributes pass through (e.g. `role="alert"` for a load error).
|
|
16
|
+
- Illustrations (`illustrations/`), from the designer's handover SVGs: `empty`, `no-results`, `error` (280×200), `all-caught-up` (144×104), `nothing-matches` (184×124). Converted to inline Astro components so their colours are design tokens (`background`, `foreground`, `muted`, `border`, `primary`, `primary-50/100/300/700`, `destructive`) and follow the theme; the C2PA metadata is stripped and filter ids are unique per instance. Exceptions without a token: two neutral greys (`zinc-400`, `zinc-300`, via Tailwind's variables with hex fallbacks), the lightest ring (a mix of `primary-50` and `background`), and the drop shadows' `#051729` (the same colour as `shadow-card-light`).
|
|
17
|
+
- `emptyStateIllustrations`, `EMPTY_STATE_ILLUSTRATIONS`, `EmptyStateIllustrationName` exported.
|
|
18
|
+
- Storybook: "Empty State" under Feedback.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* @component EmptyState
|
|
4
|
+
* @title Empty State
|
|
5
|
+
* @description A message for when there is nothing to show, or something failed: an illustration, a title, a line of text and an optional action. Page and menu sizes, optionally on a white dashed panel.
|
|
6
|
+
*
|
|
7
|
+
* @preview
|
|
8
|
+
*
|
|
9
|
+
* <EmptyState
|
|
10
|
+
* illustration="empty"
|
|
11
|
+
* title="You're not in any workspaces yet"
|
|
12
|
+
* description="Create one to get started, or ask a colleague to invite you to theirs."
|
|
13
|
+
* variant="panel"
|
|
14
|
+
* >
|
|
15
|
+
* <Button slot="action">New workspace</Button>
|
|
16
|
+
* </EmptyState>
|
|
17
|
+
*
|
|
18
|
+
* @usage
|
|
19
|
+
*
|
|
20
|
+
* ```astro nocollapse
|
|
21
|
+
* ---
|
|
22
|
+
* import { EmptyState } from '@cl-light-ds/ui/components/empty-state';
|
|
23
|
+
* import { Button } from '@cl-light-ds/ui/components/button';
|
|
24
|
+
* ---
|
|
25
|
+
*
|
|
26
|
+
* <EmptyState illustration="no-results" title="No results for “acme”" description="Check the spelling, or try a shorter name.">
|
|
27
|
+
* <Button slot="action" variant="outline">Clear search</Button>
|
|
28
|
+
* </EmptyState>
|
|
29
|
+
*
|
|
30
|
+
* <EmptyState size="menu" illustration="all-caught-up" title="You're all caught up" description="New notifications show up here." />
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* - Built-in illustrations (`illustration`): `empty`, `no-results`, `error`
|
|
34
|
+
* (280×200, for pages), `all-caught-up` (144×104) and `nothing-matches`
|
|
35
|
+
* (184×124, for menus). Drawn with design tokens, so they follow the theme.
|
|
36
|
+
* - Or an `icon` (a Lucide component) in a 48px muted circle, or your own
|
|
37
|
+
* artwork in the `illustration` slot.
|
|
38
|
+
* - For a failure that appears after an action, add `role="alert"` so it is
|
|
39
|
+
* announced; for results that change as you type, `role="status"`.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
import type { HTMLAttributes, HTMLTag } from "astro/types";
|
|
43
|
+
import type { AstroComponent } from "@lucide/astro";
|
|
44
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
45
|
+
import { cn } from "@cl-light-ds/ui/lib/utils";
|
|
46
|
+
import { emptyStateIllustrations, type EmptyStateIllustrationName } from "./illustrations";
|
|
47
|
+
|
|
48
|
+
export const emptyStateVariants = cva("flex flex-col items-center text-center", {
|
|
49
|
+
variants: {
|
|
50
|
+
size: {
|
|
51
|
+
page: "gap-4 px-6 py-12",
|
|
52
|
+
menu: "gap-2 px-6 py-10",
|
|
53
|
+
},
|
|
54
|
+
variant: {
|
|
55
|
+
plain: "",
|
|
56
|
+
panel: "rounded-lg border border-dashed bg-background",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
defaultVariants: {
|
|
60
|
+
size: "page",
|
|
61
|
+
variant: "plain",
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
interface Props extends VariantProps<typeof emptyStateVariants>, Omit<HTMLAttributes<"div">, "class" | "title"> {
|
|
66
|
+
/** A built-in illustration. */
|
|
67
|
+
illustration?: EmptyStateIllustrationName;
|
|
68
|
+
/** Or a Lucide icon in a 48px muted circle (ignored when there is an illustration). */
|
|
69
|
+
icon?: AstroComponent;
|
|
70
|
+
/** The title. Or the `title` slot. */
|
|
71
|
+
title?: string;
|
|
72
|
+
/** The text under the title. Or the `description` slot. */
|
|
73
|
+
description?: string;
|
|
74
|
+
/** Element for the title: `h2` on pages, `p` in menus by default. */
|
|
75
|
+
titleAs?: HTMLTag;
|
|
76
|
+
class?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const {
|
|
80
|
+
illustration,
|
|
81
|
+
icon,
|
|
82
|
+
title,
|
|
83
|
+
description,
|
|
84
|
+
size = "page",
|
|
85
|
+
variant = "plain",
|
|
86
|
+
titleAs,
|
|
87
|
+
class: className = "",
|
|
88
|
+
...rest
|
|
89
|
+
} = Astro.props as Props;
|
|
90
|
+
|
|
91
|
+
const hasIllustrationSlot = Astro.slots.has("illustration");
|
|
92
|
+
const hasTitleSlot = Astro.slots.has("title");
|
|
93
|
+
const hasDescriptionSlot = Astro.slots.has("description");
|
|
94
|
+
const hasAction = Astro.slots.has("action");
|
|
95
|
+
|
|
96
|
+
const art = illustration ? emptyStateIllustrations[illustration] : undefined;
|
|
97
|
+
const Illustration = art?.component;
|
|
98
|
+
const Icon = icon;
|
|
99
|
+
const TitleTag = titleAs ?? (size === "menu" ? "p" : "h2");
|
|
100
|
+
const isMenu = size === "menu";
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
<div
|
|
104
|
+
{...rest}
|
|
105
|
+
data-slot="empty-state"
|
|
106
|
+
data-size={size}
|
|
107
|
+
data-variant={variant}
|
|
108
|
+
class={cn(emptyStateVariants({ size, variant }), className)}
|
|
109
|
+
>
|
|
110
|
+
{
|
|
111
|
+
hasIllustrationSlot ? (
|
|
112
|
+
<div data-slot="empty-state-illustration" class="flex justify-center">
|
|
113
|
+
<slot name="illustration" />
|
|
114
|
+
</div>
|
|
115
|
+
) : Illustration && art ? (
|
|
116
|
+
<Illustration data-slot="empty-state-illustration" class={cn("max-w-full shrink-0", art.pull)} />
|
|
117
|
+
) : (
|
|
118
|
+
Icon && (
|
|
119
|
+
<span
|
|
120
|
+
data-slot="empty-state-icon"
|
|
121
|
+
class="flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground"
|
|
122
|
+
aria-hidden="true"
|
|
123
|
+
>
|
|
124
|
+
<Icon class="size-6" />
|
|
125
|
+
</span>
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
<div class={cn("flex flex-col", isMenu ? "max-w-xs gap-2" : "max-w-md gap-1")}>
|
|
131
|
+
{
|
|
132
|
+
(hasTitleSlot || title) && (
|
|
133
|
+
<TitleTag
|
|
134
|
+
data-slot="empty-state-title"
|
|
135
|
+
class={cn("text-foreground", isMenu ? "text-sm font-medium" : "text-lg font-semibold")}
|
|
136
|
+
>
|
|
137
|
+
{hasTitleSlot ? <slot name="title" /> : title}
|
|
138
|
+
</TitleTag>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
{
|
|
142
|
+
(hasDescriptionSlot || description) && (
|
|
143
|
+
<p data-slot="empty-state-description" class={cn("text-muted-foreground", isMenu ? "text-xs" : "text-sm")}>
|
|
144
|
+
{hasDescriptionSlot ? <slot name="description" /> : description}
|
|
145
|
+
</p>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{
|
|
151
|
+
hasAction && (
|
|
152
|
+
<div data-slot="empty-state-action" class="flex flex-wrap items-center justify-center gap-2">
|
|
153
|
+
<slot name="action" />
|
|
154
|
+
</div>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
</div>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Illustration "all-caught-up" (144×104, with its own padding inside the viewBox).
|
|
4
|
+
* The designer's artwork; colours mapped to design tokens so it follows the theme.
|
|
5
|
+
* Decorative. Generated from the workspace selection handover assets (N15).
|
|
6
|
+
*/
|
|
7
|
+
import type { HTMLAttributes } from "astro/types";
|
|
8
|
+
|
|
9
|
+
type Props = Omit<HTMLAttributes<"svg">, "width" | "height">;
|
|
10
|
+
|
|
11
|
+
const props = Astro.props as Props;
|
|
12
|
+
// Unique ids per instance, so several illustrations on one page don't share filters.
|
|
13
|
+
const uid = `es-all-caught-up-${Math.random().toString(36).slice(2, 8)}`;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<svg
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
width="144"
|
|
19
|
+
height="104"
|
|
20
|
+
viewBox="-12 -12 144 104"
|
|
21
|
+
fill="none"
|
|
22
|
+
aria-hidden="true"
|
|
23
|
+
focusable="false"
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
<defs>
|
|
27
|
+
<filter id={`${uid}-sBack`} x="-30%" y="-40%" width="160%" height="190%" color-interpolation-filters="sRGB">
|
|
28
|
+
<feDropShadow dx="0" dy="1.5" stdDeviation="2" flood-color="#051729" flood-opacity="0.05"></feDropShadow>
|
|
29
|
+
</filter>
|
|
30
|
+
<filter id={`${uid}-sFront`} x="-40%" y="-40%" width="180%" height="190%" color-interpolation-filters="sRGB">
|
|
31
|
+
<feDropShadow dx="0" dy="5" stdDeviation="6" flood-color="#051729" flood-opacity="0.10"></feDropShadow>
|
|
32
|
+
</filter>
|
|
33
|
+
<filter id={`${uid}-sCheck`} x="-60%" y="-60%" width="220%" height="220%" color-interpolation-filters="sRGB">
|
|
34
|
+
<feDropShadow dx="0" dy="3" stdDeviation="3" flood-opacity="0.32" style="flood-color:var(--primary)"></feDropShadow>
|
|
35
|
+
</filter>
|
|
36
|
+
</defs>
|
|
37
|
+
<circle cx="60" cy="40" r="35" stroke-width="10" style="stroke:color-mix(in oklab, var(--primary-50) 50%, var(--background))"></circle>
|
|
38
|
+
<circle cx="60" cy="40" r="19" stroke-width="8" style="stroke:var(--primary-50)"></circle>
|
|
39
|
+
<g filter={`url(#${uid}-sBack)`}><rect x="22" y="12" width="76" height="18" rx="6" style="fill:var(--background)"></rect></g>
|
|
40
|
+
<rect x="22.5" y="12.5" width="75" height="17" rx="5.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
41
|
+
<circle cx="31" cy="21" r="4" style="fill:var(--muted)"></circle>
|
|
42
|
+
<rect x="39" y="19" width="30" height="4" rx="2" style="fill:var(--muted)"></rect>
|
|
43
|
+
<g filter={`url(#${uid}-sFront)`}><rect x="16" y="34" width="88" height="24" rx="7" style="fill:var(--background)"></rect></g>
|
|
44
|
+
<rect x="16.5" y="34.5" width="87" height="23" rx="6.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
45
|
+
<circle cx="28" cy="46" r="6" style="fill:var(--primary-50)"></circle>
|
|
46
|
+
<path d="M25.5 45.5 a2.5 2.5 0 0 1 5 0 c0 2.2 1 3 1 3 h-7 s1 -0.8 1 -3 Z M27.2 50.2 a1 1 0 0 0 1.6 0" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round" style="stroke:var(--primary)"></path>
|
|
47
|
+
<rect x="39" y="41" width="40" height="4" rx="2" style="fill:var(--border)"></rect>
|
|
48
|
+
<rect x="39" y="48.5" width="26" height="3.5" rx="1.75" style="fill:var(--muted)"></rect>
|
|
49
|
+
<g filter={`url(#${uid}-sCheck)`}><circle cx="100" cy="58" r="11" style="fill:var(--primary)"></circle></g>
|
|
50
|
+
<circle cx="100" cy="58" r="11" stroke-width="2.5" style="stroke:var(--background)"></circle>
|
|
51
|
+
<path d="M95.5 58.2 l3 3 l6 -6" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="stroke:var(--background)"></path>
|
|
52
|
+
</svg>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Illustration "empty-workspaces" (280×200, with its own padding inside the viewBox).
|
|
4
|
+
* The designer's artwork; colours mapped to design tokens so it follows the theme.
|
|
5
|
+
* Decorative. Generated from the workspace selection handover assets (N15).
|
|
6
|
+
*/
|
|
7
|
+
import type { HTMLAttributes } from "astro/types";
|
|
8
|
+
|
|
9
|
+
type Props = Omit<HTMLAttributes<"svg">, "width" | "height">;
|
|
10
|
+
|
|
11
|
+
const props = Astro.props as Props;
|
|
12
|
+
// Unique ids per instance, so several illustrations on one page don't share filters.
|
|
13
|
+
const uid = `es-empty-workspaces-${Math.random().toString(36).slice(2, 8)}`;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<svg
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
width="280"
|
|
19
|
+
height="200"
|
|
20
|
+
viewBox="-20 -20 280 200"
|
|
21
|
+
fill="none"
|
|
22
|
+
aria-hidden="true"
|
|
23
|
+
focusable="false"
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
<defs>
|
|
27
|
+
<filter id={`${uid}-sBack`} x="-20%" y="-30%" width="140%" height="160%" color-interpolation-filters="sRGB">
|
|
28
|
+
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#051729" flood-opacity="0.05"></feDropShadow>
|
|
29
|
+
</filter>
|
|
30
|
+
<filter id={`${uid}-sFront`} x="-30%" y="-40%" width="160%" height="190%" color-interpolation-filters="sRGB">
|
|
31
|
+
<feDropShadow dx="0" dy="8" stdDeviation="10" flood-color="#051729" flood-opacity="0.10"></feDropShadow>
|
|
32
|
+
</filter>
|
|
33
|
+
<filter id={`${uid}-sBlue`} x="-60%" y="-60%" width="220%" height="240%" color-interpolation-filters="sRGB">
|
|
34
|
+
<feDropShadow dx="0" dy="4" stdDeviation="5" flood-opacity="0.35" style="flood-color:var(--primary)"></feDropShadow>
|
|
35
|
+
</filter>
|
|
36
|
+
</defs>
|
|
37
|
+
<circle cx="120" cy="80" r="69" stroke-width="20" style="stroke:color-mix(in oklab, var(--primary-50) 50%, var(--background))"></circle>
|
|
38
|
+
<circle cx="120" cy="80" r="40" stroke-width="16" style="stroke:var(--primary-50)"></circle>
|
|
39
|
+
<g transform="rotate(-9 94 70)" filter={`url(#${uid}-sBack)`}>
|
|
40
|
+
<rect x="34" y="34" width="120" height="72" rx="10" style="fill:var(--background)"></rect>
|
|
41
|
+
<rect x="34.5" y="34.5" width="119" height="71" rx="9.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
42
|
+
</g>
|
|
43
|
+
<g transform="rotate(8 152 66)" filter={`url(#${uid}-sBack)`}>
|
|
44
|
+
<rect x="92" y="30" width="120" height="72" rx="10" style="fill:var(--background)"></rect>
|
|
45
|
+
<rect x="92.5" y="30.5" width="119" height="71" rx="9.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
46
|
+
</g>
|
|
47
|
+
<g filter={`url(#${uid}-sFront)`}>
|
|
48
|
+
<rect x="50" y="52" width="140" height="84" rx="12" style="fill:var(--background)"></rect>
|
|
49
|
+
</g>
|
|
50
|
+
<rect x="50.5" y="52.5" width="139" height="83" rx="11.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
51
|
+
<rect x="64" y="66" width="28" height="28" rx="8" filter={`url(#${uid}-sBlue)`} style="fill:var(--primary)"></rect>
|
|
52
|
+
<rect x="77" y="74" width="2" height="12" rx="1" style="fill:var(--background)"></rect>
|
|
53
|
+
<rect x="72" y="79" width="12" height="2" rx="1" style="fill:var(--background)"></rect>
|
|
54
|
+
<rect x="64" y="106" width="76" height="7" rx="3.5" style="fill:var(--primary-100)"></rect>
|
|
55
|
+
<rect x="64" y="119" width="48" height="7" rx="3.5" style="fill:var(--muted)"></rect>
|
|
56
|
+
</svg>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Illustration "load-error" (280×200, with its own padding inside the viewBox).
|
|
4
|
+
* The designer's artwork; colours mapped to design tokens so it follows the theme.
|
|
5
|
+
* Decorative. Generated from the workspace selection handover assets (N15).
|
|
6
|
+
*/
|
|
7
|
+
import type { HTMLAttributes } from "astro/types";
|
|
8
|
+
|
|
9
|
+
type Props = Omit<HTMLAttributes<"svg">, "width" | "height">;
|
|
10
|
+
|
|
11
|
+
const props = Astro.props as Props;
|
|
12
|
+
// Unique ids per instance, so several illustrations on one page don't share filters.
|
|
13
|
+
const uid = `es-load-error-${Math.random().toString(36).slice(2, 8)}`;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<svg
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
width="280"
|
|
19
|
+
height="200"
|
|
20
|
+
viewBox="-20 -20 280 200"
|
|
21
|
+
fill="none"
|
|
22
|
+
aria-hidden="true"
|
|
23
|
+
focusable="false"
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
<defs>
|
|
27
|
+
<filter id={`${uid}-sBack`} x="-20%" y="-30%" width="140%" height="160%" color-interpolation-filters="sRGB">
|
|
28
|
+
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#051729" flood-opacity="0.05"></feDropShadow>
|
|
29
|
+
</filter>
|
|
30
|
+
<filter id={`${uid}-sFront`} x="-30%" y="-40%" width="160%" height="190%" color-interpolation-filters="sRGB">
|
|
31
|
+
<feDropShadow dx="0" dy="8" stdDeviation="10" flood-color="#051729" flood-opacity="0.10"></feDropShadow>
|
|
32
|
+
</filter>
|
|
33
|
+
<filter id={`${uid}-sBadge`} x="-60%" y="-60%" width="220%" height="220%" color-interpolation-filters="sRGB">
|
|
34
|
+
<feDropShadow dx="0" dy="4" stdDeviation="5" flood-opacity="0.28" style="flood-color:var(--destructive)"></feDropShadow>
|
|
35
|
+
</filter>
|
|
36
|
+
</defs>
|
|
37
|
+
<circle cx="120" cy="80" r="69" stroke-width="20" style="stroke:color-mix(in oklab, var(--primary-50) 50%, var(--background))"></circle>
|
|
38
|
+
<circle cx="120" cy="80" r="40" stroke-width="16" style="stroke:var(--primary-50)"></circle>
|
|
39
|
+
<g transform="rotate(-9 94 70)" filter={`url(#${uid}-sBack)`}>
|
|
40
|
+
<rect x="34" y="34" width="120" height="72" rx="10" style="fill:var(--background)"></rect>
|
|
41
|
+
<rect x="34.5" y="34.5" width="119" height="71" rx="9.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
42
|
+
</g>
|
|
43
|
+
<g transform="rotate(8 152 66)" filter={`url(#${uid}-sBack)`}>
|
|
44
|
+
<rect x="92" y="30" width="120" height="72" rx="10" style="fill:var(--background)"></rect>
|
|
45
|
+
<rect x="92.5" y="30.5" width="119" height="71" rx="9.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
46
|
+
</g>
|
|
47
|
+
<g filter={`url(#${uid}-sFront)`}>
|
|
48
|
+
<rect x="50" y="52" width="140" height="84" rx="12" style="fill:var(--background)"></rect>
|
|
49
|
+
</g>
|
|
50
|
+
<rect x="50.5" y="52.5" width="139" height="83" rx="11.5" stroke-opacity="0.06" style="stroke:var(--foreground)"></rect>
|
|
51
|
+
<rect x="64" y="66" width="28" height="28" rx="8" style="fill:var(--muted)"></rect>
|
|
52
|
+
<path d="M71 80 h3 l2.5 -5 l4 10 l2.5 -5 h3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="stroke:var(--color-zinc-400, #a1a1aa)"></path>
|
|
53
|
+
<rect x="64" y="106" width="76" height="7" rx="3.5" style="fill:var(--border)"></rect>
|
|
54
|
+
<rect x="64" y="119" width="48" height="7" rx="3.5" style="fill:var(--muted)"></rect>
|
|
55
|
+
<g filter={`url(#${uid}-sBadge)`}>
|
|
56
|
+
<circle cx="180" cy="62" r="20" style="fill:var(--destructive)"></circle>
|
|
57
|
+
</g>
|
|
58
|
+
<circle cx="180" cy="62" r="20" stroke-width="4" style="stroke:var(--background)"></circle>
|
|
59
|
+
<rect x="178" y="51" width="4" height="14" rx="2" style="fill:var(--background)"></rect>
|
|
60
|
+
<circle cx="180" cy="71.5" r="2.4" style="fill:var(--background)"></circle>
|
|
61
|
+
</svg>
|