@adea-ai/ui 0.142.4 → 0.144.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/dist/components/composites/accent-picker/accent-picker.d.ts +28 -0
- package/dist/components/composites/accent-picker/accent-picker.d.ts.map +1 -0
- package/dist/components/composites/accent-picker/accent-picker.js +107 -0
- package/dist/components/composites/accent-picker/accent-picker.js.map +1 -0
- package/dist/components/composites/accent-picker/index.d.ts +2 -0
- package/dist/components/composites/accent-picker/index.d.ts.map +1 -0
- package/dist/components/composites/accent-picker/index.js +2 -0
- package/dist/components/composites/icon-picker/icon-picker.d.ts +52 -0
- package/dist/components/composites/icon-picker/icon-picker.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/icon-picker.js +265 -0
- package/dist/components/composites/icon-picker/icon-picker.js.map +1 -0
- package/dist/components/composites/icon-picker/image-data-url.d.ts +42 -0
- package/dist/components/composites/icon-picker/image-data-url.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/image-data-url.js +90 -0
- package/dist/components/composites/icon-picker/image-data-url.js.map +1 -0
- package/dist/components/composites/icon-picker/index.d.ts +4 -0
- package/dist/components/composites/icon-picker/index.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/index.js +4 -0
- package/dist/components/composites/icon-picker/shell-icons.d.ts +264 -0
- package/dist/components/composites/icon-picker/shell-icons.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/shell-icons.js +334 -0
- package/dist/components/composites/icon-picker/shell-icons.js.map +1 -0
- package/dist/components/composites/settings/settings-navigation.js +1 -1
- package/dist/components/composites/settings/settings-navigation.js.map +1 -1
- package/dist/components/composites/settings/settings.d.ts +8 -14
- package/dist/components/composites/settings/settings.d.ts.map +1 -1
- package/dist/components/composites/settings/settings.js +88 -37
- package/dist/components/composites/settings/settings.js.map +1 -1
- package/dist/components/composites/terminal/terminal.js +2 -2
- package/dist/components/composites/terminal/terminal.js.map +1 -1
- package/dist/components/composites/tree/tree.d.ts +6 -0
- package/dist/components/composites/tree/tree.d.ts.map +1 -1
- package/dist/components/composites/tree/tree.js +35 -14
- package/dist/components/composites/tree/tree.js.map +1 -1
- package/dist/components/composites/workspace-switcher/index.d.ts +2 -0
- package/dist/components/composites/workspace-switcher/index.d.ts.map +1 -0
- package/dist/components/composites/workspace-switcher/index.js +2 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.d.ts +44 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.d.ts.map +1 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.js +157 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.js.map +1 -0
- package/dist/components/layout/shell-rail/index.d.ts +2 -0
- package/dist/components/layout/shell-rail/index.d.ts.map +1 -0
- package/dist/components/layout/shell-rail/index.js +2 -0
- package/dist/components/layout/shell-rail/shell-rail.d.ts +36 -0
- package/dist/components/layout/shell-rail/shell-rail.d.ts.map +1 -0
- package/dist/components/layout/shell-rail/shell-rail.js +124 -0
- package/dist/components/layout/shell-rail/shell-rail.js.map +1 -0
- package/dist/components/layout/shell-top-bar/index.d.ts +2 -0
- package/dist/components/layout/shell-top-bar/index.d.ts.map +1 -0
- package/dist/components/layout/shell-top-bar/index.js +2 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.d.ts +68 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.d.ts.map +1 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.js +135 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/r/accent-picker.json +25 -0
- package/dist/r/icon-picker.json +37 -0
- package/dist/r/registry.json +141 -1
- package/dist/r/settings.json +3 -1
- package/dist/r/shell-rail.json +27 -0
- package/dist/r/shell-top-bar.json +23 -0
- package/dist/r/src/components/composites/accent-picker/accent-picker.tsx +106 -0
- package/dist/r/src/components/composites/accent-picker/index.ts +1 -0
- package/dist/r/src/components/composites/icon-picker/icon-picker.tsx +246 -0
- package/dist/r/src/components/composites/icon-picker/image-data-url.ts +107 -0
- package/dist/r/src/components/composites/icon-picker/index.ts +25 -0
- package/dist/r/src/components/composites/icon-picker/shell-icons.ts +166 -0
- package/dist/r/src/components/composites/settings/settings-navigation.tsx +1 -1
- package/dist/r/src/components/composites/settings/settings.tsx +40 -5
- package/dist/r/src/components/composites/tree/tree.tsx +25 -0
- package/dist/r/src/components/composites/workspace-switcher/index.ts +5 -0
- package/dist/r/src/components/composites/workspace-switcher/workspace-switcher.tsx +128 -0
- package/dist/r/src/components/layout/shell-rail/index.ts +1 -0
- package/dist/r/src/components/layout/shell-rail/shell-rail.tsx +120 -0
- package/dist/r/src/components/layout/shell-top-bar/index.ts +1 -0
- package/dist/r/src/components/layout/shell-top-bar/shell-top-bar.tsx +185 -0
- package/dist/r/workspace-switcher.json +26 -0
- package/package.json +1 -1
- package/registry.json +141 -1
- package/src/components/composites/accent-picker/accent-picker.tsx +106 -0
- package/src/components/composites/accent-picker/index.ts +1 -0
- package/src/components/composites/icon-picker/icon-picker.tsx +246 -0
- package/src/components/composites/icon-picker/image-data-url.ts +107 -0
- package/src/components/composites/icon-picker/index.ts +25 -0
- package/src/components/composites/icon-picker/shell-icons.ts +166 -0
- package/src/components/composites/settings/settings-navigation.tsx +1 -1
- package/src/components/composites/settings/settings.tsx +40 -5
- package/src/components/composites/tree/tree.tsx +25 -0
- package/src/components/composites/workspace-switcher/index.ts +5 -0
- package/src/components/composites/workspace-switcher/workspace-switcher.tsx +128 -0
- package/src/components/layout/shell-rail/index.ts +1 -0
- package/src/components/layout/shell-rail/shell-rail.tsx +120 -0
- package/src/components/layout/shell-top-bar/index.ts +1 -0
- package/src/components/layout/shell-top-bar/shell-top-bar.tsx +185 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Search } from 'lucide-solid'
|
|
2
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
3
|
+
import { children, For, Show, splitProps } from 'solid-js'
|
|
4
|
+
import { cn } from '../../../lib/utils'
|
|
5
|
+
import { Kbd, KbdGroup } from '../../ui/kbd'
|
|
6
|
+
import { Separator } from '../../ui/separator'
|
|
7
|
+
import {
|
|
8
|
+
SideRail,
|
|
9
|
+
SideRailContent,
|
|
10
|
+
SideRailFooter,
|
|
11
|
+
SideRailHeader,
|
|
12
|
+
SideRailItem,
|
|
13
|
+
} from '../side-rail'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ShellRail.
|
|
17
|
+
*
|
|
18
|
+
* The side rail both applications put at the window's leading edge: always the
|
|
19
|
+
* collapsed icon column, with the app's mark at the top, a search entry point
|
|
20
|
+
* under it, the app's destinations in the middle and a footer for account and
|
|
21
|
+
* settings.
|
|
22
|
+
*
|
|
23
|
+
* The rail is never the thing the sidebar toggle collapses. The toggle belongs
|
|
24
|
+
* to the sidebar beside the rail, which is why this component takes no
|
|
25
|
+
* `collapsed` prop: a rail that could be expanded would be a second sidebar,
|
|
26
|
+
* and the two apps would drift on which of them the toggle meant.
|
|
27
|
+
*
|
|
28
|
+
* Destinations are the caller's: pass `SideRailItem`s (or a `SideRailSection`)
|
|
29
|
+
* as children. The mark, the search row and the footer are slots with the
|
|
30
|
+
* geometry decided here, so the rail's rhythm cannot differ between apps.
|
|
31
|
+
*/
|
|
32
|
+
export type ShellRailProps = Omit<ComponentProps<'nav'>, 'children'> & {
|
|
33
|
+
/** The app's mark. Decorative: the rail names itself through `aria-label`. */
|
|
34
|
+
mark: JSX.Element
|
|
35
|
+
/** Opens search. Omit to leave the search row out. */
|
|
36
|
+
onSearch?: () => void
|
|
37
|
+
/** The search row's accessible name. */
|
|
38
|
+
searchLabel?: string
|
|
39
|
+
/** The chord as it is announced, e.g. `Meta+K Control+K`. */
|
|
40
|
+
searchKeyshortcuts?: string
|
|
41
|
+
/** The cap labels drawn under the icon, in press order, e.g. `['⌘', 'K']`. */
|
|
42
|
+
searchKeys?: readonly string[]
|
|
43
|
+
/** Destinations between the search row and the footer. */
|
|
44
|
+
children?: JSX.Element
|
|
45
|
+
/** Account, plugins, settings. Pinned to the rail's foot. */
|
|
46
|
+
footer?: JSX.Element
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function ShellRail(props: ShellRailProps) {
|
|
50
|
+
const [local, rest] = splitProps(props, [
|
|
51
|
+
'class',
|
|
52
|
+
'mark',
|
|
53
|
+
'onSearch',
|
|
54
|
+
'searchLabel',
|
|
55
|
+
'searchKeyshortcuts',
|
|
56
|
+
'searchKeys',
|
|
57
|
+
'children',
|
|
58
|
+
'footer',
|
|
59
|
+
'aria-label',
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
// Resolve the footer once: reading a JSX prop twice builds two copies.
|
|
63
|
+
const footer = children(() => local.footer)
|
|
64
|
+
const content = children(() => local.children)
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<SideRail
|
|
68
|
+
collapsed
|
|
69
|
+
data-slot="shell-rail"
|
|
70
|
+
aria-label={local['aria-label'] ?? 'Global navigation'}
|
|
71
|
+
class={cn('relative z-(--z-sticky) min-w-0', local.class)}
|
|
72
|
+
{...rest}
|
|
73
|
+
>
|
|
74
|
+
<SideRailHeader data-slot="shell-rail-header" class="h-auto justify-center px-0 pt-1">
|
|
75
|
+
<span
|
|
76
|
+
data-slot="shell-rail-mark"
|
|
77
|
+
aria-hidden="true"
|
|
78
|
+
class="flex h-rail-item items-center justify-center"
|
|
79
|
+
>
|
|
80
|
+
{local.mark}
|
|
81
|
+
</span>
|
|
82
|
+
</SideRailHeader>
|
|
83
|
+
|
|
84
|
+
<SideRailContent data-slot="shell-rail-content" class="pt-0.5">
|
|
85
|
+
<Show when={local.onSearch}>
|
|
86
|
+
<div data-slot="shell-rail-search" class="flex min-w-0 flex-col gap-0.5">
|
|
87
|
+
<SideRailItem
|
|
88
|
+
as="button"
|
|
89
|
+
type="button"
|
|
90
|
+
label={local.searchLabel ?? 'Search'}
|
|
91
|
+
aria-label={local.searchLabel ?? 'Search'}
|
|
92
|
+
keyshortcuts={local.searchKeyshortcuts}
|
|
93
|
+
shortcut={local.searchKeys?.join('')}
|
|
94
|
+
onClick={() => local.onSearch?.()}
|
|
95
|
+
>
|
|
96
|
+
<Search aria-hidden="true" />
|
|
97
|
+
</SideRailItem>
|
|
98
|
+
{/* The chord is drawn as key caps under the icon: the one row that
|
|
99
|
+
advertises a shortcut. The accessible chord stays on the row. */}
|
|
100
|
+
<Show when={local.searchKeys?.length}>
|
|
101
|
+
<KbdGroup
|
|
102
|
+
size="compact"
|
|
103
|
+
class="justify-center pb-1"
|
|
104
|
+
data-slot="shell-rail-search-keys"
|
|
105
|
+
>
|
|
106
|
+
<For each={local.searchKeys}>{(key) => <Kbd size="compact">{key}</Kbd>}</For>
|
|
107
|
+
</KbdGroup>
|
|
108
|
+
</Show>
|
|
109
|
+
</div>
|
|
110
|
+
<Separator class="my-1" />
|
|
111
|
+
</Show>
|
|
112
|
+
{content()}
|
|
113
|
+
</SideRailContent>
|
|
114
|
+
|
|
115
|
+
<Show when={footer()}>
|
|
116
|
+
<SideRailFooter data-slot="shell-rail-footer">{footer()}</SideRailFooter>
|
|
117
|
+
</Show>
|
|
118
|
+
</SideRail>
|
|
119
|
+
)
|
|
120
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ShellTopBar, type ShellTopBarProps } from './shell-top-bar'
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
+
import { children, Show, splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
import { Separator } from '../../ui/separator'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ShellTopBar.
|
|
8
|
+
*
|
|
9
|
+
* The window's top bar as both applications draw it. It has two halves with a
|
|
10
|
+
* vertical divider between them:
|
|
11
|
+
*
|
|
12
|
+
* - **Leading**: history arrows, the sidebar toggle and the workspace
|
|
13
|
+
* switcher, in that order. This is the part that belongs to the window.
|
|
14
|
+
* - **Content**: breadcrumbs, search and the view's actions. This is the part
|
|
15
|
+
* that belongs to the view, and it always sits to the right of the divider.
|
|
16
|
+
*
|
|
17
|
+
* ## Why the divider tracks the sidebar
|
|
18
|
+
*
|
|
19
|
+
* With the sidebar open the divider lands on the sidebar's trailing edge, so the
|
|
20
|
+
* bar reads as the rail and sidebar's header on one side and the content's
|
|
21
|
+
* header on the other. The bar spans the rail and the sidebar (they sit under
|
|
22
|
+
* it), so the leading half is as wide as `--rail-width` plus the sidebar's width
|
|
23
|
+
* less the bar's own start padding. The host publishes the width as
|
|
24
|
+
* `--shell-sidebar-width` on an ancestor; the fallback of 17rem matches the
|
|
25
|
+
* default sidebar. Below the 48rem breakpoint the sidebar is a drawer and the
|
|
26
|
+
* leading half is only as wide as its controls.
|
|
27
|
+
*
|
|
28
|
+
* ## Narrow windows
|
|
29
|
+
*
|
|
30
|
+
* The bar is its own container. Below 34rem the search drops to a row of its
|
|
31
|
+
* own so the leading controls, the breadcrumb and the actions keep their room;
|
|
32
|
+
* the breadcrumb is the first thing to truncate.
|
|
33
|
+
*
|
|
34
|
+
* On a frameless desktop window the bar is the drag region (`draggable`) and
|
|
35
|
+
* every control opts back out; `macosInset` and `windowsInset` reserve the
|
|
36
|
+
* native window controls.
|
|
37
|
+
*/
|
|
38
|
+
export type ShellTopBarProps = Omit<ComponentProps<'header'>, 'children'> & {
|
|
39
|
+
/** History arrows. Rendered first, left of the sidebar toggle. */
|
|
40
|
+
navigation?: JSX.Element
|
|
41
|
+
/** The sidebar toggle button. */
|
|
42
|
+
sidebarToggle?: JSX.Element
|
|
43
|
+
/** The workspace switcher. */
|
|
44
|
+
workspace?: JSX.Element
|
|
45
|
+
/**
|
|
46
|
+
* Whether the sidebar is open at wide widths. Open, the divider aligns with
|
|
47
|
+
* the sidebar's edge; closed, the leading half hugs its controls.
|
|
48
|
+
*/
|
|
49
|
+
sidebarOpen?: boolean
|
|
50
|
+
/**
|
|
51
|
+
* The open sidebar's width in pixels. Published as `--shell-sidebar-width` on
|
|
52
|
+
* the bar so the divider tracks a resizable sidebar; leave it unset to use an
|
|
53
|
+
* ancestor's variable or the 17rem default.
|
|
54
|
+
*/
|
|
55
|
+
sidebarWidth?: number
|
|
56
|
+
/** Breadcrumbs or the view's title. Takes the free space and truncates first. */
|
|
57
|
+
breadcrumb?: JSX.Element
|
|
58
|
+
/** The view's search. */
|
|
59
|
+
search?: JSX.Element
|
|
60
|
+
/** The view's actions, at the trailing edge. */
|
|
61
|
+
actions?: JSX.Element
|
|
62
|
+
/** Make the bar a drag region, for a frameless window. */
|
|
63
|
+
draggable?: boolean
|
|
64
|
+
/** Reserve space for the macOS traffic lights. */
|
|
65
|
+
macosInset?: boolean
|
|
66
|
+
/** Reserve space for the Windows caption buttons. */
|
|
67
|
+
windowsInset?: boolean
|
|
68
|
+
/** Blur the content scrolling under the bar. */
|
|
69
|
+
glass?: boolean
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function ShellTopBar(props: ShellTopBarProps) {
|
|
73
|
+
const [local, rest] = splitProps(props, [
|
|
74
|
+
'class',
|
|
75
|
+
'navigation',
|
|
76
|
+
'sidebarToggle',
|
|
77
|
+
'workspace',
|
|
78
|
+
'sidebarOpen',
|
|
79
|
+
'sidebarWidth',
|
|
80
|
+
'breadcrumb',
|
|
81
|
+
'search',
|
|
82
|
+
'actions',
|
|
83
|
+
'draggable',
|
|
84
|
+
'macosInset',
|
|
85
|
+
'windowsInset',
|
|
86
|
+
'glass',
|
|
87
|
+
])
|
|
88
|
+
|
|
89
|
+
// Resolve each slot once: a JSX prop is a getter that builds its elements on
|
|
90
|
+
// every read, so testing it with `Show` and then rendering it would build
|
|
91
|
+
// (and run the refs of) two copies.
|
|
92
|
+
const navigation = children(() => local.navigation)
|
|
93
|
+
const sidebarToggle = children(() => local.sidebarToggle)
|
|
94
|
+
const workspace = children(() => local.workspace)
|
|
95
|
+
const breadcrumb = children(() => local.breadcrumb)
|
|
96
|
+
const search = children(() => local.search)
|
|
97
|
+
const actions = children(() => local.actions)
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<header
|
|
101
|
+
data-slot="shell-top-bar"
|
|
102
|
+
class={cn(
|
|
103
|
+
'@container/shell-top-bar relative z-(--z-sticky) flex min-h-topbar shrink-0 flex-wrap items-center border-b border-border bg-card text-card-foreground',
|
|
104
|
+
local.glass && 'glass-panel',
|
|
105
|
+
local.draggable && 'window-drag',
|
|
106
|
+
/* Each edge gets exactly one inline-padding utility, for the reason the
|
|
107
|
+
shared TopBar documents: two would tie-break by build order. The inset
|
|
108
|
+
is also published as a variable so the leading half can subtract it. */
|
|
109
|
+
local.macosInset
|
|
110
|
+
? 'window-inset-macos [--shell-top-bar-inset:84px]'
|
|
111
|
+
: 'ps-3 [--shell-top-bar-inset:0.75rem]',
|
|
112
|
+
local.windowsInset ? 'window-inset-windows' : 'pe-3',
|
|
113
|
+
local.class
|
|
114
|
+
)}
|
|
115
|
+
style={
|
|
116
|
+
local.sidebarWidth === undefined
|
|
117
|
+
? undefined
|
|
118
|
+
: { '--shell-sidebar-width': `${local.sidebarWidth}px` }
|
|
119
|
+
}
|
|
120
|
+
{...rest}
|
|
121
|
+
>
|
|
122
|
+
<div
|
|
123
|
+
data-slot="shell-top-bar-leading"
|
|
124
|
+
data-sidebar-open={local.sidebarOpen ? 'true' : 'false'}
|
|
125
|
+
class={cn(
|
|
126
|
+
'window-no-drag flex h-topbar min-w-0 shrink-0 items-center gap-2 overflow-x-auto overflow-y-hidden pe-3',
|
|
127
|
+
/* Wide and open: span the rail and the sidebar so the divider lands on
|
|
128
|
+
the sidebar's edge. The sidebar's own border is the 1px the divider
|
|
129
|
+
overlaps, so no extra allowance is needed. */
|
|
130
|
+
local.sidebarOpen &&
|
|
131
|
+
'md:w-[calc(var(--rail-width)+var(--shell-sidebar-width,17rem)-var(--shell-top-bar-inset))]'
|
|
132
|
+
)}
|
|
133
|
+
>
|
|
134
|
+
<Show when={navigation()}>
|
|
135
|
+
<div data-slot="shell-top-bar-navigation" class="flex shrink-0 items-center gap-2">
|
|
136
|
+
{navigation()}
|
|
137
|
+
</div>
|
|
138
|
+
</Show>
|
|
139
|
+
<Show when={sidebarToggle()}>
|
|
140
|
+
<div data-slot="shell-top-bar-toggle" class="flex shrink-0 items-center">
|
|
141
|
+
{sidebarToggle()}
|
|
142
|
+
</div>
|
|
143
|
+
</Show>
|
|
144
|
+
<Show when={workspace()}>
|
|
145
|
+
<div data-slot="shell-top-bar-workspace" class="flex min-w-0 items-center">
|
|
146
|
+
{workspace()}
|
|
147
|
+
</div>
|
|
148
|
+
</Show>
|
|
149
|
+
</div>
|
|
150
|
+
<Separator
|
|
151
|
+
orientation="vertical"
|
|
152
|
+
data-slot="shell-top-bar-divider"
|
|
153
|
+
aria-hidden="true"
|
|
154
|
+
class="h-5"
|
|
155
|
+
/>
|
|
156
|
+
<Show when={breadcrumb()}>
|
|
157
|
+
<div
|
|
158
|
+
data-slot="shell-top-bar-breadcrumb"
|
|
159
|
+
class="window-no-drag flex h-topbar min-w-0 flex-1 items-center truncate ps-3 text-sm [&_:is(a,button)]:window-no-drag"
|
|
160
|
+
>
|
|
161
|
+
{breadcrumb()}
|
|
162
|
+
</div>
|
|
163
|
+
</Show>
|
|
164
|
+
<Show when={!breadcrumb()}>
|
|
165
|
+
<div class="min-w-0 flex-1" aria-hidden="true" />
|
|
166
|
+
</Show>
|
|
167
|
+
<Show when={search()}>
|
|
168
|
+
<div
|
|
169
|
+
data-slot="shell-top-bar-search"
|
|
170
|
+
class="window-no-drag min-w-0 max-w-md shrink basis-72 px-3 @max-[34rem]/shell-top-bar:order-last @max-[34rem]/shell-top-bar:max-w-none @max-[34rem]/shell-top-bar:basis-full @max-[34rem]/shell-top-bar:pb-2"
|
|
171
|
+
>
|
|
172
|
+
{search()}
|
|
173
|
+
</div>
|
|
174
|
+
</Show>
|
|
175
|
+
<Show when={actions()}>
|
|
176
|
+
<div
|
|
177
|
+
data-slot="shell-top-bar-actions"
|
|
178
|
+
class="window-no-drag flex h-topbar min-w-0 shrink-0 items-center gap-2 overflow-x-auto overflow-y-hidden ps-1"
|
|
179
|
+
>
|
|
180
|
+
{actions()}
|
|
181
|
+
</div>
|
|
182
|
+
</Show>
|
|
183
|
+
</header>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "workspace-switcher",
|
|
3
|
+
"type": "registry:ui",
|
|
4
|
+
"title": "Workspace Switcher",
|
|
5
|
+
"description": "",
|
|
6
|
+
"dependencies": [
|
|
7
|
+
"lucide-solid@^1.51.0"
|
|
8
|
+
],
|
|
9
|
+
"registryDependencies": [
|
|
10
|
+
"@adea-ai/ui/action-button",
|
|
11
|
+
"@adea-ai/ui/dropdown-menu",
|
|
12
|
+
"lib"
|
|
13
|
+
],
|
|
14
|
+
"files": [
|
|
15
|
+
{
|
|
16
|
+
"path": "src/components/composites/workspace-switcher/index.ts",
|
|
17
|
+
"type": "registry:ui",
|
|
18
|
+
"target": "components/composites/workspace-switcher/index.ts"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"path": "src/components/composites/workspace-switcher/workspace-switcher.tsx",
|
|
22
|
+
"type": "registry:ui",
|
|
23
|
+
"target": "components/composites/workspace-switcher/workspace-switcher.tsx"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
package/package.json
CHANGED
package/registry.json
CHANGED
|
@@ -1918,6 +1918,56 @@
|
|
|
1918
1918
|
}
|
|
1919
1919
|
]
|
|
1920
1920
|
},
|
|
1921
|
+
{
|
|
1922
|
+
"name": "shell-rail",
|
|
1923
|
+
"type": "registry:ui",
|
|
1924
|
+
"title": "Shell Rail",
|
|
1925
|
+
"description": "",
|
|
1926
|
+
"dependencies": [
|
|
1927
|
+
"lucide-solid@^1.51.0"
|
|
1928
|
+
],
|
|
1929
|
+
"registryDependencies": [
|
|
1930
|
+
"@adea-ai/ui/kbd",
|
|
1931
|
+
"@adea-ai/ui/separator",
|
|
1932
|
+
"@adea-ai/ui/side-rail",
|
|
1933
|
+
"lib"
|
|
1934
|
+
],
|
|
1935
|
+
"files": [
|
|
1936
|
+
{
|
|
1937
|
+
"path": "src/components/layout/shell-rail/index.ts",
|
|
1938
|
+
"type": "registry:ui",
|
|
1939
|
+
"target": "components/layout/shell-rail/index.ts"
|
|
1940
|
+
},
|
|
1941
|
+
{
|
|
1942
|
+
"path": "src/components/layout/shell-rail/shell-rail.tsx",
|
|
1943
|
+
"type": "registry:ui",
|
|
1944
|
+
"target": "components/layout/shell-rail/shell-rail.tsx"
|
|
1945
|
+
}
|
|
1946
|
+
]
|
|
1947
|
+
},
|
|
1948
|
+
{
|
|
1949
|
+
"name": "shell-top-bar",
|
|
1950
|
+
"type": "registry:ui",
|
|
1951
|
+
"title": "Shell Top Bar",
|
|
1952
|
+
"description": "",
|
|
1953
|
+
"dependencies": [],
|
|
1954
|
+
"registryDependencies": [
|
|
1955
|
+
"@adea-ai/ui/separator",
|
|
1956
|
+
"lib"
|
|
1957
|
+
],
|
|
1958
|
+
"files": [
|
|
1959
|
+
{
|
|
1960
|
+
"path": "src/components/layout/shell-top-bar/index.ts",
|
|
1961
|
+
"type": "registry:ui",
|
|
1962
|
+
"target": "components/layout/shell-top-bar/index.ts"
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
"path": "src/components/layout/shell-top-bar/shell-top-bar.tsx",
|
|
1966
|
+
"type": "registry:ui",
|
|
1967
|
+
"target": "components/layout/shell-top-bar/shell-top-bar.tsx"
|
|
1968
|
+
}
|
|
1969
|
+
]
|
|
1970
|
+
},
|
|
1921
1971
|
{
|
|
1922
1972
|
"name": "side-rail",
|
|
1923
1973
|
"type": "registry:ui",
|
|
@@ -2143,6 +2193,31 @@
|
|
|
2143
2193
|
}
|
|
2144
2194
|
]
|
|
2145
2195
|
},
|
|
2196
|
+
{
|
|
2197
|
+
"name": "accent-picker",
|
|
2198
|
+
"type": "registry:ui",
|
|
2199
|
+
"title": "Accent Picker",
|
|
2200
|
+
"description": "",
|
|
2201
|
+
"dependencies": [
|
|
2202
|
+
"@kobalte/core@^0.13.14"
|
|
2203
|
+
],
|
|
2204
|
+
"registryDependencies": [
|
|
2205
|
+
"@adea-ai/ui/tooltip",
|
|
2206
|
+
"lib"
|
|
2207
|
+
],
|
|
2208
|
+
"files": [
|
|
2209
|
+
{
|
|
2210
|
+
"path": "src/components/composites/accent-picker/accent-picker.tsx",
|
|
2211
|
+
"type": "registry:ui",
|
|
2212
|
+
"target": "components/composites/accent-picker/accent-picker.tsx"
|
|
2213
|
+
},
|
|
2214
|
+
{
|
|
2215
|
+
"path": "src/components/composites/accent-picker/index.ts",
|
|
2216
|
+
"type": "registry:ui",
|
|
2217
|
+
"target": "components/composites/accent-picker/index.ts"
|
|
2218
|
+
}
|
|
2219
|
+
]
|
|
2220
|
+
},
|
|
2146
2221
|
{
|
|
2147
2222
|
"name": "account-menu",
|
|
2148
2223
|
"type": "registry:ui",
|
|
@@ -2518,6 +2593,43 @@
|
|
|
2518
2593
|
}
|
|
2519
2594
|
]
|
|
2520
2595
|
},
|
|
2596
|
+
{
|
|
2597
|
+
"name": "icon-picker",
|
|
2598
|
+
"type": "registry:ui",
|
|
2599
|
+
"title": "Icon Picker",
|
|
2600
|
+
"description": "",
|
|
2601
|
+
"dependencies": [
|
|
2602
|
+
"@kobalte/core@^0.13.14",
|
|
2603
|
+
"lucide-solid@^1.51.0"
|
|
2604
|
+
],
|
|
2605
|
+
"registryDependencies": [
|
|
2606
|
+
"@adea-ai/ui/button",
|
|
2607
|
+
"@adea-ai/ui/popover",
|
|
2608
|
+
"lib"
|
|
2609
|
+
],
|
|
2610
|
+
"files": [
|
|
2611
|
+
{
|
|
2612
|
+
"path": "src/components/composites/icon-picker/icon-picker.tsx",
|
|
2613
|
+
"type": "registry:ui",
|
|
2614
|
+
"target": "components/composites/icon-picker/icon-picker.tsx"
|
|
2615
|
+
},
|
|
2616
|
+
{
|
|
2617
|
+
"path": "src/components/composites/icon-picker/image-data-url.ts",
|
|
2618
|
+
"type": "registry:ui",
|
|
2619
|
+
"target": "components/composites/icon-picker/image-data-url.ts"
|
|
2620
|
+
},
|
|
2621
|
+
{
|
|
2622
|
+
"path": "src/components/composites/icon-picker/index.ts",
|
|
2623
|
+
"type": "registry:ui",
|
|
2624
|
+
"target": "components/composites/icon-picker/index.ts"
|
|
2625
|
+
},
|
|
2626
|
+
{
|
|
2627
|
+
"path": "src/components/composites/icon-picker/shell-icons.ts",
|
|
2628
|
+
"type": "registry:ui",
|
|
2629
|
+
"target": "components/composites/icon-picker/shell-icons.ts"
|
|
2630
|
+
}
|
|
2631
|
+
]
|
|
2632
|
+
},
|
|
2521
2633
|
{
|
|
2522
2634
|
"name": "inline-citation",
|
|
2523
2635
|
"type": "registry:ui",
|
|
@@ -2757,11 +2869,13 @@
|
|
|
2757
2869
|
"title": "Settings",
|
|
2758
2870
|
"description": "",
|
|
2759
2871
|
"dependencies": [
|
|
2760
|
-
"@kobalte/core@^0.13.14"
|
|
2872
|
+
"@kobalte/core@^0.13.14",
|
|
2873
|
+
"lucide-solid@^1.51.0"
|
|
2761
2874
|
],
|
|
2762
2875
|
"registryDependencies": [
|
|
2763
2876
|
"@adea-ai/ui/sidebar-nav",
|
|
2764
2877
|
"@adea-ai/ui/tabs",
|
|
2878
|
+
"@adea-ai/ui/tooltip",
|
|
2765
2879
|
"@adea-ai/ui/typography",
|
|
2766
2880
|
"lib"
|
|
2767
2881
|
],
|
|
@@ -3144,6 +3258,32 @@
|
|
|
3144
3258
|
}
|
|
3145
3259
|
]
|
|
3146
3260
|
},
|
|
3261
|
+
{
|
|
3262
|
+
"name": "workspace-switcher",
|
|
3263
|
+
"type": "registry:ui",
|
|
3264
|
+
"title": "Workspace Switcher",
|
|
3265
|
+
"description": "",
|
|
3266
|
+
"dependencies": [
|
|
3267
|
+
"lucide-solid@^1.51.0"
|
|
3268
|
+
],
|
|
3269
|
+
"registryDependencies": [
|
|
3270
|
+
"@adea-ai/ui/action-button",
|
|
3271
|
+
"@adea-ai/ui/dropdown-menu",
|
|
3272
|
+
"lib"
|
|
3273
|
+
],
|
|
3274
|
+
"files": [
|
|
3275
|
+
{
|
|
3276
|
+
"path": "src/components/composites/workspace-switcher/index.ts",
|
|
3277
|
+
"type": "registry:ui",
|
|
3278
|
+
"target": "components/composites/workspace-switcher/index.ts"
|
|
3279
|
+
},
|
|
3280
|
+
{
|
|
3281
|
+
"path": "src/components/composites/workspace-switcher/workspace-switcher.tsx",
|
|
3282
|
+
"type": "registry:ui",
|
|
3283
|
+
"target": "components/composites/workspace-switcher/workspace-switcher.tsx"
|
|
3284
|
+
}
|
|
3285
|
+
]
|
|
3286
|
+
},
|
|
3147
3287
|
{
|
|
3148
3288
|
"name": "conversation",
|
|
3149
3289
|
"type": "registry:ui",
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { RadioGroup as Radio } from '@kobalte/core/radio-group'
|
|
2
|
+
import type { JSX } from 'solid-js'
|
|
3
|
+
import { For } from 'solid-js'
|
|
4
|
+
import { accents } from '#lib/accent-presets'
|
|
5
|
+
import { cn } from '#lib/utils'
|
|
6
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* AccentPicker.
|
|
10
|
+
*
|
|
11
|
+
* A row of accent swatches with a leading "none" choice, for a setting that
|
|
12
|
+
* overrides the accent it would otherwise inherit: a project's icon colour, a
|
|
13
|
+
* workspace's colour over the app's. `null` is a real value, not an empty one:
|
|
14
|
+
* it means "do not override", so the swatch row never has an unchecked state and
|
|
15
|
+
* the control can say what the inherited colour is through `inheritLabel`.
|
|
16
|
+
*
|
|
17
|
+
* The swatches are the theme's own accent presets, each carrying its light and
|
|
18
|
+
* dark colour and switching on the `dark` class, so a swatch is the colour the
|
|
19
|
+
* setting will produce in whichever appearance is in force and the picker needs
|
|
20
|
+
* no theme provider.
|
|
21
|
+
*/
|
|
22
|
+
export type AccentPickerProps = {
|
|
23
|
+
/** The group's accessible name, e.g. "Icon colour". */
|
|
24
|
+
label: string
|
|
25
|
+
/** An accent preset id, or `null` for no override. */
|
|
26
|
+
value: string | null
|
|
27
|
+
onValueChange(value: string | null): void
|
|
28
|
+
/** What `null` means here, e.g. "Inherit workspace accent". Also the first swatch's name and tooltip. */
|
|
29
|
+
inheritLabel?: string
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
class?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const NONE = '__none__'
|
|
35
|
+
|
|
36
|
+
export function AccentPicker(props: AccentPickerProps) {
|
|
37
|
+
return (
|
|
38
|
+
<Radio
|
|
39
|
+
data-slot="swatch-picker"
|
|
40
|
+
aria-label={props.label}
|
|
41
|
+
value={props.value ?? NONE}
|
|
42
|
+
disabled={props.disabled}
|
|
43
|
+
onChange={(id) => props.onValueChange(id === NONE ? null : id)}
|
|
44
|
+
class={cn('flex flex-wrap items-center gap-2', props.class)}
|
|
45
|
+
>
|
|
46
|
+
<SwatchItem id={NONE} label={props.inheritLabel ?? 'Inherit (default)'}>
|
|
47
|
+
<InheritSwatch />
|
|
48
|
+
</SwatchItem>
|
|
49
|
+
<For each={accents}>
|
|
50
|
+
{(accent) => (
|
|
51
|
+
<SwatchItem id={accent.id} label={accent.label}>
|
|
52
|
+
<span
|
|
53
|
+
aria-hidden="true"
|
|
54
|
+
class="block size-full rounded-full bg-(--swatch-light) dark:bg-(--swatch-dark)"
|
|
55
|
+
style={{
|
|
56
|
+
'--swatch-light': accent.light ?? 'currentColor',
|
|
57
|
+
'--swatch-dark': accent.dark ?? accent.light ?? 'currentColor',
|
|
58
|
+
}}
|
|
59
|
+
/>
|
|
60
|
+
</SwatchItem>
|
|
61
|
+
)}
|
|
62
|
+
</For>
|
|
63
|
+
</Radio>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The "inherit" swatch: a black disc with a red slash, the universal "no
|
|
69
|
+
* override" mark. It is drawn rather than painted from a token so it reads the
|
|
70
|
+
* same in every theme and appearance.
|
|
71
|
+
*/
|
|
72
|
+
function InheritSwatch() {
|
|
73
|
+
return (
|
|
74
|
+
<span
|
|
75
|
+
aria-hidden="true"
|
|
76
|
+
data-slot="swatch-inherit"
|
|
77
|
+
class="relative block size-full overflow-hidden rounded-full bg-(--swatch-inherit)"
|
|
78
|
+
style={{ '--swatch-inherit': '#000' }}
|
|
79
|
+
>
|
|
80
|
+
<span class="absolute inset-x-0 top-1/2 h-0.5 -translate-y-1/2 -rotate-45 bg-destructive" />
|
|
81
|
+
</span>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function SwatchItem(props: { id: string; label: string; children: JSX.Element }) {
|
|
86
|
+
return (
|
|
87
|
+
<Radio.Item value={props.id} data-accent-option={props.id} class="contents">
|
|
88
|
+
<Radio.ItemInput class="peer" />
|
|
89
|
+
<Tooltip>
|
|
90
|
+
<TooltipTrigger
|
|
91
|
+
as={Radio.ItemLabel}
|
|
92
|
+
class={cn(
|
|
93
|
+
'flex size-7 cursor-pointer items-center justify-center rounded-full border border-border p-0.5',
|
|
94
|
+
'peer-focus-visible:border-ring peer-focus-visible:ring-3 peer-focus-visible:ring-primary-subtle',
|
|
95
|
+
'data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary',
|
|
96
|
+
'data-[disabled]:pointer-events-none data-[disabled]:opacity-50'
|
|
97
|
+
)}
|
|
98
|
+
>
|
|
99
|
+
{props.children}
|
|
100
|
+
<span class="sr-only">{props.label}</span>
|
|
101
|
+
</TooltipTrigger>
|
|
102
|
+
<TooltipContent>{props.label}</TooltipContent>
|
|
103
|
+
</Tooltip>
|
|
104
|
+
</Radio.Item>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AccentPicker, type AccentPickerProps } from './accent-picker'
|