@ismail-elkorchi/ui-shell 0.1.0 → 0.1.2
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/README.md +134 -81
- package/dist/custom-elements.json +1333 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/register.d.ts +5 -5
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +5 -5
- package/dist/register.js.map +1 -1
- package/dist/src/internal/light-dom-slot-controller.d.ts +22 -0
- package/dist/src/internal/light-dom-slot-controller.d.ts.map +1 -0
- package/dist/src/internal/light-dom-slot-controller.js +92 -0
- package/dist/src/internal/light-dom-slot-controller.js.map +1 -0
- package/dist/src/internal/router.d.ts +45 -0
- package/dist/src/internal/router.d.ts.map +1 -0
- package/dist/src/internal/router.js +89 -0
- package/dist/src/internal/router.js.map +1 -0
- package/dist/src/structures/uik-shell-activity-bar-contract.d.ts +10 -0
- package/dist/src/structures/uik-shell-activity-bar-contract.d.ts.map +1 -0
- package/dist/src/structures/uik-shell-activity-bar-contract.js +2 -0
- package/dist/src/structures/uik-shell-activity-bar-contract.js.map +1 -0
- package/dist/src/structures/uik-shell-activity-bar.d.ts +40 -0
- package/dist/src/structures/uik-shell-activity-bar.d.ts.map +1 -0
- package/dist/src/structures/uik-shell-activity-bar.js +148 -0
- package/dist/src/structures/uik-shell-activity-bar.js.map +1 -0
- package/dist/src/structures/uik-shell-layout.d.ts +35 -0
- package/dist/src/structures/uik-shell-layout.d.ts.map +1 -0
- package/dist/src/structures/uik-shell-layout.js +213 -0
- package/dist/src/structures/uik-shell-layout.js.map +1 -0
- package/dist/src/structures/uik-shell-secondary-sidebar.d.ts +51 -0
- package/dist/src/structures/uik-shell-secondary-sidebar.d.ts.map +1 -0
- package/dist/src/structures/uik-shell-secondary-sidebar.js +306 -0
- package/dist/src/structures/uik-shell-secondary-sidebar.js.map +1 -0
- package/dist/src/structures/uik-shell-sidebar.d.ts +44 -0
- package/dist/src/structures/uik-shell-sidebar.d.ts.map +1 -0
- package/dist/src/structures/uik-shell-sidebar.js +253 -0
- package/dist/src/structures/uik-shell-sidebar.js.map +1 -0
- package/dist/src/structures/uik-shell-status-bar.d.ts +42 -0
- package/dist/src/structures/uik-shell-status-bar.d.ts.map +1 -0
- package/dist/src/structures/uik-shell-status-bar.js +193 -0
- package/dist/src/structures/uik-shell-status-bar.js.map +1 -0
- package/package.json +40 -28
- package/dist/ActivityBar.d.ts +0 -25
- package/dist/ActivityBar.d.ts.map +0 -1
- package/dist/ActivityBar.js +0 -81
- package/dist/ActivityBar.js.map +0 -1
- package/dist/AppShellLayout.d.ts +0 -17
- package/dist/AppShellLayout.d.ts.map +0 -1
- package/dist/AppShellLayout.js +0 -66
- package/dist/AppShellLayout.js.map +0 -1
- package/dist/SecondarySidebar.d.ts +0 -18
- package/dist/SecondarySidebar.d.ts.map +0 -1
- package/dist/SecondarySidebar.js +0 -84
- package/dist/SecondarySidebar.js.map +0 -1
- package/dist/Sidebar.d.ts +0 -20
- package/dist/Sidebar.d.ts.map +0 -1
- package/dist/Sidebar.js +0 -105
- package/dist/Sidebar.js.map +0 -1
- package/dist/Statusbar.d.ts +0 -19
- package/dist/Statusbar.d.ts.map +0 -1
- package/dist/Statusbar.js +0 -73
- package/dist/Statusbar.js.map +0 -1
- package/dist/router.d.ts +0 -36
- package/dist/router.d.ts.map +0 -1
- package/dist/router.js +0 -72
- package/dist/router.js.map +0 -1
- package/dist/tailwind-source.css +0 -2
package/README.md
CHANGED
|
@@ -1,113 +1,185 @@
|
|
|
1
1
|
# @ismail-elkorchi/ui-shell
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Build & distribution
|
|
6
|
-
|
|
7
|
-
- `npm run build` emits ESM + `.d.ts` modules into `dist/` for `index/register/router`, layout, activity bar, sidebar, secondary sidebar, and status bar.
|
|
8
|
-
- Tailwind scanning helper ships as `dist/tailwind-source.css`.
|
|
9
|
-
- Published output contains only `dist/` plus this README; TypeScript sources stay in the workspace.
|
|
3
|
+
Token-driven shell components (activity bar, sidebars, status bar, and an optional frame layout) for Light DOM composition. They depend on `@ismail-elkorchi/ui-primitives` for controls, expose slots + parts, and read all visual values from `@ismail-elkorchi/ui-tokens` CSS variables.
|
|
10
4
|
|
|
11
5
|
## Layout layer
|
|
12
6
|
|
|
13
7
|
- Regions: left rail (`activity-bar`), primary sidebar, main content, optional secondary sidebar, and status bar.
|
|
14
8
|
- `uik-shell-layout` stitches the regions together and tags them with `data-region` attributes to keep the layout contract visible in the DOM.
|
|
15
9
|
- Shell components expose only UI surface/state; business logic should live in the host app.
|
|
16
|
-
- **Contract**: Shell components use `ui-primitives` strictly via their public API (attributes/props).
|
|
10
|
+
- **Contract**: Shell components use `ui-primitives` strictly via their public API (attributes/props). Visual styling comes from `--uik-*` custom properties (no framework utility classes).
|
|
11
|
+
|
|
12
|
+
## Landmarks & labels (Accessibility contract)
|
|
13
|
+
|
|
14
|
+
- `uik-shell-layout` renders a `role="region"` container; override its label via `aria-label` or `aria-labelledby` on the host.
|
|
15
|
+
- `uik-shell-activity-bar` renders an `<aside>` landmark and forwards `aria-label`/`aria-labelledby` to the internal nav rail; default label is "Activity bar".
|
|
16
|
+
- `uik-shell-sidebar` and `uik-shell-secondary-sidebar` render `<aside>` landmarks; default labels come from the `heading` or fall back to "Sidebar"/"Secondary sidebar".
|
|
17
|
+
- `uik-shell-status-bar` uses `role="status"` with `aria-live="polite"` for status messages.
|
|
18
|
+
- Provide a semantic `<main>` element in the `main-content` slot and label additional landmarks as needed in host markup.
|
|
19
|
+
|
|
20
|
+
## Focus + roving focus
|
|
21
|
+
|
|
22
|
+
- Shell navigation surfaces delegate roving focus to primitives (`uik-nav-rail`, `uik-tree-view`) and do not add competing keyboard handlers.
|
|
23
|
+
- Follow the Focus + Roving Focus contract in `@ismail-elkorchi/ui-primitives` when composing activity bars or navigation trees.
|
|
24
|
+
|
|
25
|
+
## Overlay close semantics
|
|
26
|
+
|
|
27
|
+
- Overlay-like shells emit close events with `detail.reason` aligned to primitives: `escape | outside | programmatic | toggle`.
|
|
28
|
+
- `uik-shell-secondary-sidebar` captures the previously focused element on open and restores focus on close (unless a `focus-return-target` is provided).
|
|
17
29
|
|
|
18
30
|
## Using the components
|
|
19
31
|
|
|
20
32
|
```ts
|
|
21
|
-
import {html} from
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import type {
|
|
33
|
+
import { html } from "lit";
|
|
34
|
+
import "@ismail-elkorchi/ui-primitives/register";
|
|
35
|
+
import "@ismail-elkorchi/ui-shell/register";
|
|
36
|
+
import type { UikShellActivityBarItem } from "@ismail-elkorchi/ui-shell/activity-bar";
|
|
25
37
|
|
|
26
|
-
const activityItems:
|
|
38
|
+
const activityItems: UikShellActivityBarItem[] = [
|
|
27
39
|
{
|
|
28
|
-
id:
|
|
29
|
-
label:
|
|
30
|
-
icon:
|
|
40
|
+
id: "explorer",
|
|
41
|
+
label: "Explorer",
|
|
42
|
+
icon: "M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "search",
|
|
46
|
+
label: "Search",
|
|
47
|
+
icon: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z",
|
|
31
48
|
},
|
|
32
|
-
{id: 'search', label: 'Search', icon: 'M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z'}
|
|
33
49
|
];
|
|
34
50
|
|
|
35
51
|
html`
|
|
36
|
-
<uik-shell-layout
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
52
|
+
<uik-shell-layout ?isSecondarySidebarVisible=${true}>
|
|
53
|
+
<uik-shell-activity-bar
|
|
54
|
+
slot="activity-bar"
|
|
55
|
+
.items=${activityItems}
|
|
56
|
+
.activeId=${"explorer"}
|
|
57
|
+
@activity-bar-select=${(e: CustomEvent<{ id: string }>) =>
|
|
58
|
+
console.log(e.detail.id)}
|
|
59
|
+
>
|
|
60
|
+
</uik-shell-activity-bar>
|
|
61
|
+
<uik-shell-sidebar slot="primary-sidebar" heading="Explorer">
|
|
62
|
+
<uik-button slot="actions" variant="ghost" size="icon">…</uik-button>
|
|
63
|
+
<div style="font-size: var(--uik-typography-font-size-2);">
|
|
64
|
+
<!-- put your tree view or navigation here -->
|
|
65
|
+
</div>
|
|
66
|
+
</uik-shell-sidebar>
|
|
67
|
+
<main
|
|
68
|
+
slot="main-content"
|
|
69
|
+
style="flex: 1 1 auto; min-height: var(--uik-space-0);"
|
|
70
|
+
>
|
|
71
|
+
Your editor or subviews
|
|
72
|
+
</main>
|
|
73
|
+
<uik-shell-secondary-sidebar
|
|
74
|
+
slot="secondary-sidebar"
|
|
75
|
+
.isOpen=${true}
|
|
76
|
+
heading="AI Assistant"
|
|
77
|
+
@secondary-sidebar-close=${() => console.log("close secondary")}
|
|
78
|
+
>
|
|
79
|
+
<p
|
|
80
|
+
style="
|
|
81
|
+
font-size: var(--uik-typography-font-size-2);
|
|
82
|
+
color: oklch(var(--uik-text-muted));
|
|
83
|
+
"
|
|
84
|
+
>
|
|
85
|
+
Auxiliary tools live here.
|
|
86
|
+
</p>
|
|
87
|
+
</uik-shell-secondary-sidebar>
|
|
88
|
+
<uik-shell-status-bar
|
|
89
|
+
slot="status-bar"
|
|
90
|
+
message="Ready"
|
|
91
|
+
tone="info"
|
|
92
|
+
meta="3 files selected"
|
|
93
|
+
></uik-shell-status-bar>
|
|
63
94
|
</uik-shell-layout>
|
|
64
95
|
`;
|
|
65
96
|
```
|
|
66
97
|
|
|
67
98
|
### Component notes
|
|
68
99
|
|
|
69
|
-
- `uik-shell-activity-bar
|
|
70
|
-
- `uik-shell-
|
|
71
|
-
- `uik-shell-
|
|
72
|
-
- `uik-shell-
|
|
100
|
+
- `uik-shell-layout`: named slots `activity-bar`, `primary-sidebar`, `main-content`, `secondary-sidebar`, `status-bar`.
|
|
101
|
+
- `uik-shell-activity-bar`: accepts `.items` (id/label/icon/path) and emits `activity-bar-select`; optional `footer` slot; delegates roving focus to `uik-nav-rail` (set `aria-label` if you need a custom name).
|
|
102
|
+
- `uik-shell-sidebar`: `slot="actions"` for header actions, default slot for body, optional `slot="footer"`; `isBodyPadded`/`isBodyScrollable` toggle spacing + scroll.
|
|
103
|
+
- `uik-shell-secondary-sidebar`: controlled via `.isOpen`; optional `focus-return-target` (selector or element) to restore focus on close; Escape and the close button emit `secondary-sidebar-close` (`detail.reason` is `escape | toggle`).
|
|
104
|
+
- `uik-shell-status-bar`: `.message` + `.tone` colorize the left side; `meta` string (outline badge) or `slot="meta"` for custom content; optional `slot="actions"`.
|
|
105
|
+
- Use `@ismail-elkorchi/ui-primitives/uik-nav` or `@ismail-elkorchi/ui-primitives/uik-tree-view` for sidebar navigation content.
|
|
106
|
+
|
|
107
|
+
### Custom properties
|
|
108
|
+
|
|
109
|
+
- Activity bar: `--uik-component-shell-activity-bar-bg`, `--uik-component-shell-activity-bar-fg`, `--uik-component-shell-activity-bar-width`, `--uik-component-shell-activity-bar-item-size`, `--uik-component-shell-activity-bar-item-icon-size`, `--uik-component-shell-activity-bar-item-indicator-bg`, `--uik-component-shell-activity-bar-item-indicator-radius`, `--uik-component-shell-activity-bar-item-indicator-width`.
|
|
110
|
+
- Sidebar: `--uik-component-shell-sidebar-bg`, `--uik-component-shell-sidebar-fg`, `--uik-component-shell-sidebar-width`.
|
|
111
|
+
- Secondary sidebar: `--uik-component-shell-secondary-sidebar-bg`, `--uik-component-shell-secondary-sidebar-width`.
|
|
112
|
+
- Status bar: `--uik-component-shell-status-bar-bg`, `--uik-component-shell-status-bar-fg`, `--uik-component-shell-status-bar-height`.
|
|
113
|
+
- Shared: `--uik-component-shell-divider-color`, `--uik-component-shell-scrollbar-track`, `--uik-component-shell-scrollbar-thumb`.
|
|
114
|
+
|
|
115
|
+
## Tokens & theming
|
|
116
|
+
|
|
117
|
+
Load tokens once and set theme/density attributes on a shared container (often `:root`):
|
|
118
|
+
|
|
119
|
+
```css
|
|
120
|
+
@import "@ismail-elkorchi/ui-tokens/index.css";
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<html data-uik-theme="light" data-uik-density="comfortable">
|
|
125
|
+
...
|
|
126
|
+
</html>
|
|
127
|
+
```
|
|
73
128
|
|
|
74
129
|
## Routing store
|
|
75
130
|
|
|
76
|
-
A tiny EventTarget-based router lives in `@ismail-elkorchi/ui-shell/router`. It is framework-light, keeps state in memory (no history), and is meant for desktop flows that only need named views and optional subviews
|
|
131
|
+
A tiny EventTarget-based router lives in `@ismail-elkorchi/ui-shell/router`. It is framework-light, keeps state in memory (no history), and is meant for desktop flows that only need named views and optional subviews.
|
|
77
132
|
|
|
78
133
|
```ts
|
|
79
|
-
import {
|
|
134
|
+
import {
|
|
135
|
+
createUikShellRouter,
|
|
136
|
+
UIK_SHELL_NAVIGATION_EVENT,
|
|
137
|
+
type UikShellNavigationDetail,
|
|
138
|
+
} from "@ismail-elkorchi/ui-shell/router";
|
|
80
139
|
|
|
81
140
|
const routes = [
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
141
|
+
{
|
|
142
|
+
id: "explorer",
|
|
143
|
+
label: "Explorer",
|
|
144
|
+
subviews: ["code", "prompt", "apply"],
|
|
145
|
+
defaultSubview: "code",
|
|
146
|
+
},
|
|
147
|
+
{ id: "search", label: "Search" },
|
|
148
|
+
{ id: "settings", label: "Settings" },
|
|
85
149
|
] as const;
|
|
86
150
|
|
|
87
|
-
export const shellRouter =
|
|
151
|
+
export const shellRouter = createUikShellRouter({
|
|
152
|
+
routes,
|
|
153
|
+
initialView: "explorer",
|
|
154
|
+
initialSubview: "code",
|
|
155
|
+
});
|
|
88
156
|
|
|
89
157
|
// React to navigation anywhere in the app
|
|
90
|
-
const unsubscribe = shellRouter.subscribe(({view, subview}) => {
|
|
91
|
-
console.log(
|
|
158
|
+
const unsubscribe = shellRouter.subscribe(({ view, subview }) => {
|
|
159
|
+
console.log("Current location", view, subview);
|
|
92
160
|
});
|
|
93
161
|
|
|
94
162
|
// Wire Lit components through events
|
|
95
163
|
html`
|
|
96
164
|
<uik-shell-activity-bar
|
|
97
|
-
.items=${routes.map(r => ({id: r.id, label: r.label ?? r.id}))}
|
|
165
|
+
.items=${routes.map((r) => ({ id: r.id, label: r.label ?? r.id }))}
|
|
98
166
|
.activeId=${shellRouter.current.view}
|
|
99
|
-
@activity-select=${(e: CustomEvent<{id: string}>) =>
|
|
167
|
+
@activity-bar-select=${(e: CustomEvent<{ id: string }>) =>
|
|
168
|
+
shellRouter.navigate(e.detail.id)}
|
|
169
|
+
>
|
|
100
170
|
</uik-shell-activity-bar>
|
|
101
171
|
|
|
102
172
|
<editor-area
|
|
103
|
-
.
|
|
104
|
-
@
|
|
173
|
+
.activeSubview=${shellRouter.current.subview ?? "code"}
|
|
174
|
+
@subview-change=${(e: CustomEvent<{ subview: string }>) =>
|
|
175
|
+
shellRouter.navigate(shellRouter.current.view, e.detail.subview)}
|
|
176
|
+
>
|
|
105
177
|
</editor-area>
|
|
106
178
|
`;
|
|
107
179
|
|
|
108
180
|
// Listen to the low-level navigation event if you prefer EventTarget
|
|
109
|
-
window.addEventListener(
|
|
110
|
-
const detail = (event as CustomEvent<
|
|
181
|
+
window.addEventListener(UIK_SHELL_NAVIGATION_EVENT, (event: Event) => {
|
|
182
|
+
const detail = (event as CustomEvent<UikShellNavigationDetail>).detail;
|
|
111
183
|
console.log(detail.from, detail.to, detail.route);
|
|
112
184
|
});
|
|
113
185
|
```
|
|
@@ -115,22 +187,3 @@ window.addEventListener(APP_SHELL_NAV_EVENT, (event: Event) => {
|
|
|
115
187
|
- Routes are simple `{id, label?, subviews?, defaultSubview?}` objects.
|
|
116
188
|
- `navigate(view, subview?)` resolves subviews per route (keeping the last used subview for that route).
|
|
117
189
|
- `subscribe` immediately fires with the current location and returns an unsubscribe function.
|
|
118
|
-
|
|
119
|
-
## Tailwind v4 scanning
|
|
120
|
-
|
|
121
|
-
The package ships Tailwind class strings in TypeScript. Add the source hint before importing Tailwind:
|
|
122
|
-
|
|
123
|
-
```css
|
|
124
|
-
@import '@ismail-elkorchi/ui-tokens/index.css';
|
|
125
|
-
@import '@ismail-elkorchi/ui-shell/tailwind-source.css'; /* pulls in @source "./**/*.{ts,js}" */
|
|
126
|
-
@source "./**/*.{ts,js,html}";
|
|
127
|
-
@import 'tailwindcss';
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Adjust the `@source` path to match the location of your entry CSS. Alternatively, add the line yourself:
|
|
131
|
-
|
|
132
|
-
```css
|
|
133
|
-
@source "../../node_modules/@ismail-elkorchi/ui-shell/**/*.{ts,js}";
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
Make sure these appear in the renderer entry CSS so Tailwind keeps the shell utilities during tree-shaking.
|