@c9up/nebula 0.1.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/LICENSE +21 -0
- package/README.md +256 -0
- package/dist/adapters/css.d.ts +33 -0
- package/dist/adapters/css.js +67 -0
- package/dist/adapters/index.d.ts +16 -0
- package/dist/adapters/index.js +27 -0
- package/dist/adapters/tailwind.d.ts +25 -0
- package/dist/adapters/tailwind.js +122 -0
- package/dist/adapters/types.d.ts +49 -0
- package/dist/adapters/types.js +21 -0
- package/dist/adapters/unocss.d.ts +17 -0
- package/dist/adapters/unocss.js +107 -0
- package/dist/atoms/AspectRatio.d.ts +17 -0
- package/dist/atoms/AspectRatio.js +19 -0
- package/dist/atoms/Avatar.d.ts +23 -0
- package/dist/atoms/Avatar.js +46 -0
- package/dist/atoms/Badge.d.ts +25 -0
- package/dist/atoms/Badge.js +28 -0
- package/dist/atoms/Button.d.ts +58 -0
- package/dist/atoms/Button.js +67 -0
- package/dist/atoms/Checkbox.d.ts +41 -0
- package/dist/atoms/Checkbox.js +47 -0
- package/dist/atoms/Input.d.ts +36 -0
- package/dist/atoms/Input.js +50 -0
- package/dist/atoms/Kbd.d.ts +14 -0
- package/dist/atoms/Kbd.js +17 -0
- package/dist/atoms/Label.d.ts +24 -0
- package/dist/atoms/Label.js +26 -0
- package/dist/atoms/Marker.d.ts +42 -0
- package/dist/atoms/Marker.js +55 -0
- package/dist/atoms/NativeSelect.d.ts +43 -0
- package/dist/atoms/NativeSelect.js +81 -0
- package/dist/atoms/Progress.d.ts +21 -0
- package/dist/atoms/Progress.js +48 -0
- package/dist/atoms/ScrollArea.d.ts +28 -0
- package/dist/atoms/ScrollArea.js +37 -0
- package/dist/atoms/Separator.d.ts +16 -0
- package/dist/atoms/Separator.js +21 -0
- package/dist/atoms/Skeleton.d.ts +13 -0
- package/dist/atoms/Skeleton.js +18 -0
- package/dist/atoms/Slider.d.ts +30 -0
- package/dist/atoms/Slider.js +40 -0
- package/dist/atoms/Spinner.d.ts +17 -0
- package/dist/atoms/Spinner.js +20 -0
- package/dist/atoms/Switch.d.ts +24 -0
- package/dist/atoms/Switch.js +41 -0
- package/dist/atoms/Textarea.d.ts +28 -0
- package/dist/atoms/Textarea.js +36 -0
- package/dist/atoms/Toggle.d.ts +38 -0
- package/dist/atoms/Toggle.js +45 -0
- package/dist/atoms/index.d.ts +32 -0
- package/dist/atoms/index.js +32 -0
- package/dist/cli/add.d.ts +44 -0
- package/dist/cli/add.js +99 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +10 -0
- package/dist/cli/registry.d.ts +31 -0
- package/dist/cli/registry.js +83 -0
- package/dist/config.d.ts +81 -0
- package/dist/config.js +43 -0
- package/dist/configure.d.ts +34 -0
- package/dist/configure.js +85 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +41 -0
- package/dist/lib/children.d.ts +28 -0
- package/dist/lib/children.js +27 -0
- package/dist/lib/cn.d.ts +13 -0
- package/dist/lib/cn.js +13 -0
- package/dist/lib/cva.d.ts +83 -0
- package/dist/lib/cva.js +178 -0
- package/dist/lib/icons.d.ts +44 -0
- package/dist/lib/icons.js +79 -0
- package/dist/lib/id.d.ts +31 -0
- package/dist/lib/id.js +41 -0
- package/dist/lib/index.d.ts +12 -0
- package/dist/lib/index.js +12 -0
- package/dist/lib/motion.d.ts +31 -0
- package/dist/lib/motion.js +39 -0
- package/dist/lib/props.d.ts +48 -0
- package/dist/lib/props.js +59 -0
- package/dist/lib/styled.d.ts +31 -0
- package/dist/lib/styled.js +39 -0
- package/dist/molecules/Accordion.d.ts +35 -0
- package/dist/molecules/Accordion.js +117 -0
- package/dist/molecules/Alert.d.ts +30 -0
- package/dist/molecules/Alert.js +35 -0
- package/dist/molecules/Attachment.d.ts +39 -0
- package/dist/molecules/Attachment.js +103 -0
- package/dist/molecules/Breadcrumb.d.ts +29 -0
- package/dist/molecules/Breadcrumb.js +73 -0
- package/dist/molecules/Bubble.d.ts +56 -0
- package/dist/molecules/Bubble.js +92 -0
- package/dist/molecules/ButtonGroup.d.ts +23 -0
- package/dist/molecules/ButtonGroup.js +30 -0
- package/dist/molecules/Card.d.ts +17 -0
- package/dist/molecules/Card.js +17 -0
- package/dist/molecules/Collapsible.d.ts +40 -0
- package/dist/molecules/Collapsible.js +71 -0
- package/dist/molecules/Empty.d.ts +16 -0
- package/dist/molecules/Empty.js +16 -0
- package/dist/molecules/Field.d.ts +54 -0
- package/dist/molecules/Field.js +82 -0
- package/dist/molecules/InputGroup.d.ts +33 -0
- package/dist/molecules/InputGroup.js +35 -0
- package/dist/molecules/InputOTP.d.ts +33 -0
- package/dist/molecules/InputOTP.js +140 -0
- package/dist/molecules/Item.d.ts +41 -0
- package/dist/molecules/Item.js +48 -0
- package/dist/molecules/Message.d.ts +43 -0
- package/dist/molecules/Message.js +82 -0
- package/dist/molecules/Pagination.d.ts +41 -0
- package/dist/molecules/Pagination.js +144 -0
- package/dist/molecules/RadioGroup.d.ts +32 -0
- package/dist/molecules/RadioGroup.js +65 -0
- package/dist/molecules/Resizable.d.ts +37 -0
- package/dist/molecules/Resizable.js +136 -0
- package/dist/molecules/Table.d.ts +37 -0
- package/dist/molecules/Table.js +78 -0
- package/dist/molecules/Tabs.d.ts +37 -0
- package/dist/molecules/Tabs.js +109 -0
- package/dist/molecules/ToggleGroup.d.ts +37 -0
- package/dist/molecules/ToggleGroup.js +68 -0
- package/dist/molecules/Typography.d.ts +26 -0
- package/dist/molecules/Typography.js +67 -0
- package/dist/molecules/index.d.ts +37 -0
- package/dist/molecules/index.js +37 -0
- package/dist/organisms/AlertDialog.d.ts +40 -0
- package/dist/organisms/AlertDialog.js +104 -0
- package/dist/organisms/Calendar.d.ts +96 -0
- package/dist/organisms/Calendar.js +353 -0
- package/dist/organisms/Carousel.d.ts +29 -0
- package/dist/organisms/Carousel.js +128 -0
- package/dist/organisms/Chart.d.ts +55 -0
- package/dist/organisms/Chart.js +189 -0
- package/dist/organisms/Combobox.d.ts +41 -0
- package/dist/organisms/Combobox.js +102 -0
- package/dist/organisms/Command.d.ts +46 -0
- package/dist/organisms/Command.js +171 -0
- package/dist/organisms/CommandDialog.d.ts +42 -0
- package/dist/organisms/CommandDialog.js +116 -0
- package/dist/organisms/ContextMenu.d.ts +29 -0
- package/dist/organisms/ContextMenu.js +102 -0
- package/dist/organisms/DataTable.d.ts +50 -0
- package/dist/organisms/DataTable.js +257 -0
- package/dist/organisms/DatePicker.d.ts +34 -0
- package/dist/organisms/DatePicker.js +115 -0
- package/dist/organisms/DateRangePicker.d.ts +34 -0
- package/dist/organisms/DateRangePicker.js +122 -0
- package/dist/organisms/Dialog.d.ts +50 -0
- package/dist/organisms/Dialog.js +116 -0
- package/dist/organisms/Drawer.d.ts +40 -0
- package/dist/organisms/Drawer.js +131 -0
- package/dist/organisms/DropdownMenu.d.ts +30 -0
- package/dist/organisms/DropdownMenu.js +91 -0
- package/dist/organisms/Form.d.ts +114 -0
- package/dist/organisms/Form.js +151 -0
- package/dist/organisms/HoverCard.d.ts +30 -0
- package/dist/organisms/HoverCard.js +68 -0
- package/dist/organisms/Menubar.d.ts +28 -0
- package/dist/organisms/Menubar.js +147 -0
- package/dist/organisms/MessageScroller.d.ts +36 -0
- package/dist/organisms/MessageScroller.js +124 -0
- package/dist/organisms/NavigationMenu.d.ts +41 -0
- package/dist/organisms/NavigationMenu.js +139 -0
- package/dist/organisms/Popover.d.ts +33 -0
- package/dist/organisms/Popover.js +58 -0
- package/dist/organisms/Questionnaire.d.ts +74 -0
- package/dist/organisms/Questionnaire.js +235 -0
- package/dist/organisms/Select.d.ts +47 -0
- package/dist/organisms/Select.js +250 -0
- package/dist/organisms/Sheet.d.ts +34 -0
- package/dist/organisms/Sheet.js +107 -0
- package/dist/organisms/Sidebar.d.ts +100 -0
- package/dist/organisms/Sidebar.js +228 -0
- package/dist/organisms/Toaster.d.ts +67 -0
- package/dist/organisms/Toaster.js +189 -0
- package/dist/organisms/Tooltip.d.ts +39 -0
- package/dist/organisms/Tooltip.js +94 -0
- package/dist/organisms/index.d.ts +40 -0
- package/dist/organisms/index.js +40 -0
- package/dist/primitives/controllable.d.ts +38 -0
- package/dist/primitives/controllable.js +43 -0
- package/dist/primitives/dismissable.d.ts +53 -0
- package/dist/primitives/dismissable.js +158 -0
- package/dist/primitives/floating.d.ts +116 -0
- package/dist/primitives/floating.js +289 -0
- package/dist/primitives/floatingSurface.d.ts +56 -0
- package/dist/primitives/floatingSurface.js +142 -0
- package/dist/primitives/focusTrap.d.ts +47 -0
- package/dist/primitives/focusTrap.js +101 -0
- package/dist/primitives/focusable.d.ts +53 -0
- package/dist/primitives/focusable.js +109 -0
- package/dist/primitives/index.d.ts +27 -0
- package/dist/primitives/index.js +27 -0
- package/dist/primitives/menu.d.ts +102 -0
- package/dist/primitives/menu.js +356 -0
- package/dist/primitives/modalSurface.d.ts +54 -0
- package/dist/primitives/modalSurface.js +146 -0
- package/dist/primitives/portal.d.ts +34 -0
- package/dist/primitives/portal.js +42 -0
- package/dist/primitives/presence.d.ts +45 -0
- package/dist/primitives/presence.js +152 -0
- package/dist/primitives/rovingFocus.d.ts +47 -0
- package/dist/primitives/rovingFocus.js +176 -0
- package/dist/primitives/scrollLock.d.ts +21 -0
- package/dist/primitives/scrollLock.js +75 -0
- package/dist/primitives/typeahead.d.ts +39 -0
- package/dist/primitives/typeahead.js +123 -0
- package/dist/templates/AppShell.d.ts +30 -0
- package/dist/templates/AppShell.js +42 -0
- package/dist/templates/AuthLayout.d.ts +23 -0
- package/dist/templates/AuthLayout.js +42 -0
- package/dist/templates/SettingsLayout.d.ts +27 -0
- package/dist/templates/SettingsLayout.js +42 -0
- package/dist/templates/index.d.ts +16 -0
- package/dist/templates/index.js +16 -0
- package/nebula.css +2 -0
- package/package.json +92 -0
- package/registry.json +1107 -0
- package/src/adapters/css.ts +75 -0
- package/src/adapters/index.ts +40 -0
- package/src/adapters/tailwind.ts +134 -0
- package/src/adapters/types.ts +53 -0
- package/src/adapters/unocss.ts +116 -0
- package/src/atoms/AspectRatio.ts +28 -0
- package/src/atoms/Avatar.ts +67 -0
- package/src/atoms/Badge.ts +46 -0
- package/src/atoms/Button.ts +96 -0
- package/src/atoms/Checkbox.ts +76 -0
- package/src/atoms/Input.ts +76 -0
- package/src/atoms/Kbd.ts +28 -0
- package/src/atoms/Label.ts +38 -0
- package/src/atoms/Marker.ts +79 -0
- package/src/atoms/NativeSelect.ts +115 -0
- package/src/atoms/Progress.ts +64 -0
- package/src/atoms/ScrollArea.ts +53 -0
- package/src/atoms/Separator.ts +36 -0
- package/src/atoms/Skeleton.ts +24 -0
- package/src/atoms/Slider.ts +65 -0
- package/src/atoms/Spinner.ts +28 -0
- package/src/atoms/Switch.ts +56 -0
- package/src/atoms/Textarea.ts +58 -0
- package/src/atoms/Toggle.ts +67 -0
- package/src/atoms/index.ts +62 -0
- package/src/cli/add.ts +126 -0
- package/src/cli/index.ts +22 -0
- package/src/cli/registry.ts +116 -0
- package/src/config.ts +102 -0
- package/src/configure.ts +127 -0
- package/src/index.ts +53 -0
- package/src/lib/children.ts +43 -0
- package/src/lib/cn.ts +14 -0
- package/src/lib/cva.ts +249 -0
- package/src/lib/icons.ts +138 -0
- package/src/lib/id.ts +44 -0
- package/src/lib/index.ts +21 -0
- package/src/lib/motion.ts +48 -0
- package/src/lib/props.ts +83 -0
- package/src/lib/styled.ts +60 -0
- package/src/molecules/Accordion.ts +161 -0
- package/src/molecules/Alert.ts +58 -0
- package/src/molecules/Attachment.ts +132 -0
- package/src/molecules/Breadcrumb.ts +107 -0
- package/src/molecules/Bubble.ts +134 -0
- package/src/molecules/ButtonGroup.ts +55 -0
- package/src/molecules/Card.ts +42 -0
- package/src/molecules/Collapsible.ts +89 -0
- package/src/molecules/Empty.ts +43 -0
- package/src/molecules/Field.ts +131 -0
- package/src/molecules/InputGroup.ts +62 -0
- package/src/molecules/InputOTP.ts +166 -0
- package/src/molecules/Item.ts +89 -0
- package/src/molecules/Message.ts +127 -0
- package/src/molecules/Pagination.ts +197 -0
- package/src/molecules/RadioGroup.ts +104 -0
- package/src/molecules/Resizable.ts +166 -0
- package/src/molecules/Table.ts +118 -0
- package/src/molecules/Tabs.ts +148 -0
- package/src/molecules/ToggleGroup.ts +109 -0
- package/src/molecules/Typography.ts +94 -0
- package/src/molecules/index.ts +144 -0
- package/src/organisms/AlertDialog.ts +133 -0
- package/src/organisms/Calendar.ts +470 -0
- package/src/organisms/Carousel.ts +161 -0
- package/src/organisms/Chart.ts +257 -0
- package/src/organisms/Combobox.ts +140 -0
- package/src/organisms/Command.ts +211 -0
- package/src/organisms/CommandDialog.ts +149 -0
- package/src/organisms/ContextMenu.ts +125 -0
- package/src/organisms/DataTable.ts +328 -0
- package/src/organisms/DatePicker.ts +141 -0
- package/src/organisms/DateRangePicker.ts +149 -0
- package/src/organisms/Dialog.ts +162 -0
- package/src/organisms/Drawer.ts +167 -0
- package/src/organisms/DropdownMenu.ts +112 -0
- package/src/organisms/Form.ts +217 -0
- package/src/organisms/HoverCard.ts +92 -0
- package/src/organisms/Menubar.ts +167 -0
- package/src/organisms/MessageScroller.ts +145 -0
- package/src/organisms/NavigationMenu.ts +184 -0
- package/src/organisms/Popover.ts +84 -0
- package/src/organisms/Questionnaire.ts +322 -0
- package/src/organisms/Select.ts +286 -0
- package/src/organisms/Sheet.ts +144 -0
- package/src/organisms/Sidebar.ts +336 -0
- package/src/organisms/Toaster.ts +246 -0
- package/src/organisms/Tooltip.ts +124 -0
- package/src/organisms/index.ts +134 -0
- package/src/primitives/controllable.ts +64 -0
- package/src/primitives/dismissable.ts +195 -0
- package/src/primitives/floating.ts +453 -0
- package/src/primitives/floatingSurface.ts +209 -0
- package/src/primitives/focusTrap.ts +132 -0
- package/src/primitives/focusable.ts +108 -0
- package/src/primitives/index.ts +88 -0
- package/src/primitives/menu.ts +491 -0
- package/src/primitives/modalSurface.ts +199 -0
- package/src/primitives/portal.ts +61 -0
- package/src/primitives/presence.ts +185 -0
- package/src/primitives/rovingFocus.ts +212 -0
- package/src/primitives/scrollLock.ts +79 -0
- package/src/primitives/typeahead.ts +156 -0
- package/src/templates/AppShell.ts +56 -0
- package/src/templates/AuthLayout.ts +66 -0
- package/src/templates/SettingsLayout.ts +63 -0
- package/src/templates/index.ts +21 -0
- package/theme.css +151 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppShell — sidebar, header, content.
|
|
3
|
+
*
|
|
4
|
+
* The layout behind almost every signed-in page. Shipping it is what makes
|
|
5
|
+
* nebula an atomic-design library rather than a component bag: shadcn stops at
|
|
6
|
+
* organisms and leaves the page skeleton to be rebuilt per app, which is why
|
|
7
|
+
* two pages in the same product end up with different header heights.
|
|
8
|
+
*
|
|
9
|
+
* `h-svh` on the shell and `overflow-auto` on the content column, not on the
|
|
10
|
+
* body. That is what keeps the header and the sidebar fixed while only the
|
|
11
|
+
* content scrolls — pinning them with `position: fixed` instead means
|
|
12
|
+
* hand-maintaining a top padding that matches the header, and it breaks the
|
|
13
|
+
* moment the header wraps to two lines.
|
|
14
|
+
*
|
|
15
|
+
* `svh` rather than `vh` because mobile browsers shrink the viewport as their
|
|
16
|
+
* address bar retracts; `vh` leaves the last hundred pixels of a full-height
|
|
17
|
+
* layout under the browser chrome.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { component, html } from "@c9up/aurora";
|
|
21
|
+
import { type Slot, slot } from "../lib/children.js";
|
|
22
|
+
import { cn } from "../lib/cn.js";
|
|
23
|
+
import { type Reactive, read } from "../lib/props.js";
|
|
24
|
+
|
|
25
|
+
export interface AppShellProps {
|
|
26
|
+
/** The navigation column — usually a `Sidebar`. */
|
|
27
|
+
sidebar?: Slot;
|
|
28
|
+
/** The top bar, spanning the content column. */
|
|
29
|
+
header?: Slot;
|
|
30
|
+
children?: Slot;
|
|
31
|
+
class?: Reactive<string>;
|
|
32
|
+
contentClass?: Reactive<string>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const AppShell = component<AppShellProps>((props) => {
|
|
36
|
+
return html`<div
|
|
37
|
+
data-slot="app-shell"
|
|
38
|
+
class="${() => cn("bg-background flex h-svh w-full overflow-hidden", read(props.class))}"
|
|
39
|
+
>
|
|
40
|
+
${slot(props.sidebar)}
|
|
41
|
+
<div data-slot="app-shell-main" class="flex min-w-0 flex-1 flex-col">
|
|
42
|
+
${
|
|
43
|
+
props.header === undefined
|
|
44
|
+
? null
|
|
45
|
+
: html`<header
|
|
46
|
+
data-slot="app-shell-header"
|
|
47
|
+
class="bg-background flex h-14 shrink-0 items-center gap-2 border-b px-4"
|
|
48
|
+
>${slot(props.header)}</header>`
|
|
49
|
+
}
|
|
50
|
+
<main
|
|
51
|
+
data-slot="app-shell-content"
|
|
52
|
+
class="${() => cn("min-h-0 flex-1 overflow-auto p-4 md:p-6", read(props.contentClass))}"
|
|
53
|
+
>${slot(props.children)}</main>
|
|
54
|
+
</div>
|
|
55
|
+
</div>`;
|
|
56
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuthLayout — a centred card for sign-in, sign-up and password reset.
|
|
3
|
+
*
|
|
4
|
+
* `min-h-svh` with the card centred by flex, rather than absolute positioning
|
|
5
|
+
* and a translate. Centring by transform breaks as soon as the card grows
|
|
6
|
+
* taller than the viewport — a sign-up form with four fields and a validation
|
|
7
|
+
* error on each — because the top half goes above the fold with nothing to
|
|
8
|
+
* scroll to.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { component, html } from "@c9up/aurora";
|
|
12
|
+
import type { Child } from "../lib/children.js";
|
|
13
|
+
import { type Slot, slot } from "../lib/children.js";
|
|
14
|
+
import { cn } from "../lib/cn.js";
|
|
15
|
+
import { type Reactive, read } from "../lib/props.js";
|
|
16
|
+
|
|
17
|
+
export interface AuthLayoutProps {
|
|
18
|
+
/** Product name or logo, above the card. */
|
|
19
|
+
brand?: Slot;
|
|
20
|
+
title: Child;
|
|
21
|
+
description?: Child;
|
|
22
|
+
children?: Slot;
|
|
23
|
+
/** Under the card — "Already have an account?" and the like. */
|
|
24
|
+
footer?: Slot;
|
|
25
|
+
class?: Reactive<string>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const AuthLayout = component<AuthLayoutProps>((props) => {
|
|
29
|
+
return html`<div
|
|
30
|
+
data-slot="auth-layout"
|
|
31
|
+
class="${() =>
|
|
32
|
+
cn(
|
|
33
|
+
"bg-muted/40 flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10",
|
|
34
|
+
read(props.class),
|
|
35
|
+
)}"
|
|
36
|
+
>
|
|
37
|
+
<div class="flex w-full max-w-sm flex-col gap-6">
|
|
38
|
+
${
|
|
39
|
+
props.brand === undefined
|
|
40
|
+
? null
|
|
41
|
+
: html`<div class="flex justify-center">${slot(props.brand)}</div>`
|
|
42
|
+
}
|
|
43
|
+
<div
|
|
44
|
+
data-slot="auth-card"
|
|
45
|
+
class="bg-card text-card-foreground flex flex-col gap-6 rounded-xl border p-6 shadow-sm"
|
|
46
|
+
>
|
|
47
|
+
<div class="flex flex-col gap-1.5 text-center">
|
|
48
|
+
<h1 class="text-xl leading-none font-semibold">${props.title}</h1>
|
|
49
|
+
${
|
|
50
|
+
props.description === undefined
|
|
51
|
+
? null
|
|
52
|
+
: html`<p class="text-muted-foreground text-sm">${props.description}</p>`
|
|
53
|
+
}
|
|
54
|
+
</div>
|
|
55
|
+
${slot(props.children)}
|
|
56
|
+
</div>
|
|
57
|
+
${
|
|
58
|
+
props.footer === undefined
|
|
59
|
+
? null
|
|
60
|
+
: html`<div class="text-muted-foreground text-center text-sm">
|
|
61
|
+
${slot(props.footer)}
|
|
62
|
+
</div>`
|
|
63
|
+
}
|
|
64
|
+
</div>
|
|
65
|
+
</div>`;
|
|
66
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SettingsLayout — a section list beside a settings panel.
|
|
3
|
+
*
|
|
4
|
+
* The list is a real `<nav>` of links, not a Tabs component. Settings sections
|
|
5
|
+
* are pages: they need their own URL so a link to "Billing" works, and so the
|
|
6
|
+
* back button returns to the previous section rather than leaving the page
|
|
7
|
+
* entirely. Tabs would give the same look and none of that.
|
|
8
|
+
*
|
|
9
|
+
* The list sits above the panel on narrow screens and beside it from `md` up,
|
|
10
|
+
* which is the one responsive decision this layout has to make.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { component, html } from "@c9up/aurora";
|
|
14
|
+
import type { Child } from "../lib/children.js";
|
|
15
|
+
import { type Slot, slot } from "../lib/children.js";
|
|
16
|
+
import { cn } from "../lib/cn.js";
|
|
17
|
+
import { type Reactive, read } from "../lib/props.js";
|
|
18
|
+
|
|
19
|
+
export interface SettingsSection {
|
|
20
|
+
label: Child;
|
|
21
|
+
href: string;
|
|
22
|
+
active?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SettingsLayoutProps {
|
|
26
|
+
title: Child;
|
|
27
|
+
description?: Child;
|
|
28
|
+
sections: readonly SettingsSection[];
|
|
29
|
+
children?: Slot;
|
|
30
|
+
class?: Reactive<string>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const SettingsLayout = component<SettingsLayoutProps>((props) => {
|
|
34
|
+
return html`<div
|
|
35
|
+
data-slot="settings-layout"
|
|
36
|
+
class="${() => cn("flex flex-col gap-6 p-4 md:p-10", read(props.class))}"
|
|
37
|
+
>
|
|
38
|
+
<div class="flex flex-col gap-1.5">
|
|
39
|
+
<h1 class="text-2xl font-semibold tracking-tight">${props.title}</h1>
|
|
40
|
+
${
|
|
41
|
+
props.description === undefined
|
|
42
|
+
? null
|
|
43
|
+
: html`<p class="text-muted-foreground text-sm">${props.description}</p>`
|
|
44
|
+
}
|
|
45
|
+
</div>
|
|
46
|
+
<div class="flex flex-col gap-8 md:flex-row md:gap-12">
|
|
47
|
+
<nav
|
|
48
|
+
data-slot="settings-nav"
|
|
49
|
+
aria-label="Settings sections"
|
|
50
|
+
class="flex gap-2 overflow-x-auto md:w-48 md:shrink-0 md:flex-col md:overflow-visible"
|
|
51
|
+
>
|
|
52
|
+
${props.sections.map(
|
|
53
|
+
(section) => html`<a
|
|
54
|
+
href="${section.href}"
|
|
55
|
+
aria-current="${section.active === true ? "page" : undefined}"
|
|
56
|
+
class="hover:bg-accent hover:text-accent-foreground aria-[current=page]:bg-accent aria-[current=page]:font-medium rounded-md px-3 py-2 text-sm whitespace-nowrap transition-colors"
|
|
57
|
+
>${section.label}</a>`,
|
|
58
|
+
)}
|
|
59
|
+
</nav>
|
|
60
|
+
<div data-slot="settings-panel" class="min-w-0 flex-1">${slot(props.children)}</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>`;
|
|
63
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Templates — page skeletons.
|
|
3
|
+
*
|
|
4
|
+
* Atomic design's fourth level, and the one shadcn does not have: it stops at
|
|
5
|
+
* organisms and ships "blocks" as copy-paste examples instead. The gap shows
|
|
6
|
+
* up as drift — two pages in the same product with different header heights
|
|
7
|
+
* and different content padding, because each was assembled from organisms by
|
|
8
|
+
* hand.
|
|
9
|
+
*
|
|
10
|
+
* A template is layout only. It positions slots and owns no state, no data and
|
|
11
|
+
* no behaviour, which is what keeps it usable for pages it was not written
|
|
12
|
+
* with in mind.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export { AppShell, type AppShellProps } from "./AppShell.js";
|
|
16
|
+
export { AuthLayout, type AuthLayoutProps } from "./AuthLayout.js";
|
|
17
|
+
export {
|
|
18
|
+
SettingsLayout,
|
|
19
|
+
type SettingsLayoutProps,
|
|
20
|
+
type SettingsSection,
|
|
21
|
+
} from "./SettingsLayout.js";
|
package/theme.css
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* nebula design tokens.
|
|
3
|
+
*
|
|
4
|
+
* Plain CSS custom properties, deliberately: this file has to be readable by
|
|
5
|
+
* all three adapters. Tailwind maps it through `@theme inline`, UnoCSS through
|
|
6
|
+
* its `theme` object, and the `css` adapter emits utilities straight against
|
|
7
|
+
* it. Anything engine-specific here would force a fork per adapter.
|
|
8
|
+
*
|
|
9
|
+
* The palette is shadcn's neutral base in oklch. oklch rather than hex because
|
|
10
|
+
* the whole point of the scale is that `--muted-foreground` sits a predictable
|
|
11
|
+
* perceptual distance from `--foreground`; in sRGB hex that relationship is
|
|
12
|
+
* eyeballed and breaks the moment someone retunes one end of it.
|
|
13
|
+
*
|
|
14
|
+
* Dark mode is applied by `.dark` on an ancestor, matching what the aurora
|
|
15
|
+
* apps in this workspace already do (`@custom-variant dark (&:is(.dark *))`).
|
|
16
|
+
* `prefers-color-scheme` is deliberately NOT wired here — a theme toggle needs
|
|
17
|
+
* to be able to override the system, and a media query cannot be overridden by
|
|
18
|
+
* a class.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
:root {
|
|
22
|
+
--radius: 0.625rem;
|
|
23
|
+
|
|
24
|
+
--background: oklch(1 0 0);
|
|
25
|
+
--foreground: oklch(0.145 0 0);
|
|
26
|
+
|
|
27
|
+
--card: oklch(1 0 0);
|
|
28
|
+
--card-foreground: oklch(0.145 0 0);
|
|
29
|
+
|
|
30
|
+
--popover: oklch(1 0 0);
|
|
31
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
32
|
+
|
|
33
|
+
--primary: oklch(0.205 0 0);
|
|
34
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
35
|
+
|
|
36
|
+
--secondary: oklch(0.97 0 0);
|
|
37
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
38
|
+
|
|
39
|
+
--muted: oklch(0.97 0 0);
|
|
40
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
41
|
+
|
|
42
|
+
--accent: oklch(0.97 0 0);
|
|
43
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
44
|
+
|
|
45
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
46
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
47
|
+
|
|
48
|
+
--border: oklch(0.922 0 0);
|
|
49
|
+
--input: oklch(0.922 0 0);
|
|
50
|
+
--ring: oklch(0.708 0 0);
|
|
51
|
+
|
|
52
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
53
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
54
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
55
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
56
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
57
|
+
|
|
58
|
+
--sidebar: oklch(0.985 0 0);
|
|
59
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
60
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
61
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
62
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
63
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
64
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
65
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.dark {
|
|
69
|
+
--background: oklch(0.145 0 0);
|
|
70
|
+
--foreground: oklch(0.985 0 0);
|
|
71
|
+
|
|
72
|
+
--card: oklch(0.205 0 0);
|
|
73
|
+
--card-foreground: oklch(0.985 0 0);
|
|
74
|
+
|
|
75
|
+
--popover: oklch(0.269 0 0);
|
|
76
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
77
|
+
|
|
78
|
+
--primary: oklch(0.922 0 0);
|
|
79
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
80
|
+
|
|
81
|
+
--secondary: oklch(0.269 0 0);
|
|
82
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
83
|
+
|
|
84
|
+
--muted: oklch(0.269 0 0);
|
|
85
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
86
|
+
|
|
87
|
+
--accent: oklch(0.371 0 0);
|
|
88
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
89
|
+
|
|
90
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
91
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* Borders and inputs are translucent white in dark mode rather than a
|
|
95
|
+
* lighter grey. A solid border reads as a seam against `--card`, which sits
|
|
96
|
+
* above `--background`; alpha lets one value hold up over both surfaces.
|
|
97
|
+
*/
|
|
98
|
+
--border: oklch(1 0 0 / 10%);
|
|
99
|
+
--input: oklch(1 0 0 / 15%);
|
|
100
|
+
--ring: oklch(0.556 0 0);
|
|
101
|
+
|
|
102
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
103
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
104
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
105
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
106
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
107
|
+
|
|
108
|
+
--sidebar: oklch(0.205 0 0);
|
|
109
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
110
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
111
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
112
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
113
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
114
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
115
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/*
|
|
119
|
+
* Keyframes for the enter/exit animations the overlay components reference
|
|
120
|
+
* through `data-[state=open]:animate-in` and friends.
|
|
121
|
+
*
|
|
122
|
+
* These live in nebula rather than in the adapter because `presence()` will
|
|
123
|
+
* hold a node in the DOM waiting for an animation that the stylesheet has to
|
|
124
|
+
* actually define. Ship the behaviour without the keyframes and every overlay
|
|
125
|
+
* unmounts a frame after it is told to close, silently losing the exit.
|
|
126
|
+
*/
|
|
127
|
+
@keyframes nebula-fade-in {
|
|
128
|
+
from {
|
|
129
|
+
opacity: 0;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@keyframes nebula-fade-out {
|
|
134
|
+
to {
|
|
135
|
+
opacity: 0;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@keyframes nebula-zoom-in {
|
|
140
|
+
from {
|
|
141
|
+
opacity: 0;
|
|
142
|
+
transform: scale(0.95);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@keyframes nebula-zoom-out {
|
|
147
|
+
to {
|
|
148
|
+
opacity: 0;
|
|
149
|
+
transform: scale(0.95);
|
|
150
|
+
}
|
|
151
|
+
}
|