@iyulab/desktop-patterns 0.1.3 → 0.3.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/README.md CHANGED
@@ -59,6 +59,32 @@ document.querySelector('dp-toolbar')!.addEventListener('dp-toolbar-toggle', () =
59
59
  })
60
60
  ```
61
61
 
62
+ ### Sidebar items: links, groups, icons, actions
63
+
64
+ ```ts
65
+ nav.items = [
66
+ { id: 'overview', icon: '■', label: 'Overview', href: '/overview' }, // href → rendered as <a>
67
+ {
68
+ id: 'work', label: 'Work', collapsed: false, // a group: a disclosure over its items
69
+ items: [{ id: 'runs', icon: '▶', label: 'Runs', href: '/runs' }],
70
+ },
71
+ ]
72
+ nav.bottomItems = [{ id: 'sign-out', icon: '⎋', label: 'Sign out' }] // actions, not places
73
+ nav.setAttribute('nav-label', 'Main') // names the navigation landmark
74
+ ```
75
+
76
+ - **`href`** renders the item as a link, so a router's link interception (or the browser) does the navigating.
77
+ `dp-sidebar-select` still fires and is cancelable — `preventDefault()` cancels the navigation and keeps the
78
+ active item. A modified click (Ctrl/⌘/Shift/Alt, middle button) opens the link elsewhere and selects nothing.
79
+ Items without `href` stay buttons and the consumer navigates on `dp-sidebar-select`.
80
+ - **Groups** (`{ id, label, items, icon?, collapsed? }`) render as a named `role="group"` under a disclosure
81
+ button (`aria-expanded`). A group holding the active item is always open. In the collapsed rail every group's
82
+ items show, separated by a rule.
83
+ - **Icons**: each item's icon is a slot named `icon-<id>` whose fallback is the item's `icon` text — slot any icon
84
+ element (`<svg slot="icon-overview">`) to replace it.
85
+ - **Bottom items are actions**: each click fires `dp-sidebar-action` (`itemId`) — every time, so a failed action can
86
+ be retried — and never moves `aria-current`. (In 0.2.x they fired `dp-sidebar-select` and took the active mark.)
87
+
62
88
  Every component takes its user-facing text as a plain attribute/property or slot — there is no
63
89
  built-in i18n layer. See each component's Storybook story (`npm run storybook`) for its full API.
64
90
 
@@ -125,9 +151,10 @@ npm run build # per-component ESM output, type declarations
125
151
  npm run storybook # interactive component browser
126
152
  ```
127
153
 
128
- Until `@iyulab/desktop-compact` publishes its first npm release, this package resolves it via
129
- `file:../desktop-compact` for local development (a sibling checkout at that relative path) — this
130
- switches to a registry semver range once `desktop-compact` publishes.
154
+ `@iyulab/desktop-compact` is a **peer** dependency: this package reads its `--dc-*` tokens but never
155
+ imports its code, so the consumer installs one copy and both packages share it. A regular dependency
156
+ would give a consumer on a newer `desktop-compact` minor a second, unused copy nested under this
157
+ package.
131
158
 
132
159
  ## License
133
160
 
@@ -25,6 +25,8 @@ export declare class DpShortcutOverlay extends LitElement {
25
25
  open: boolean;
26
26
  heading: string;
27
27
  emptyMessage: string;
28
+ /** Accessible name of the close button — supply one in the app's language. */
29
+ closeLabel: string;
28
30
  private headingId;
29
31
  updated(changed: Map<string, unknown>): void;
30
32
  disconnectedCallback(): void;
@@ -1,27 +1,65 @@
1
1
  import { LitElement } from 'lit';
2
+ /**
3
+ * One navigation entry. With `href` it renders as a link — a router (or the
4
+ * browser) does the navigating, exactly as it would for any other anchor on
5
+ * the page. Without one it renders as a button and the consumer navigates on
6
+ * `dp-sidebar-select`.
7
+ */
2
8
  export interface SidebarItem {
3
9
  id: string;
10
+ /** Text fallback for the `icon-<id>` slot. */
4
11
  icon: string;
5
12
  label: string;
13
+ href?: string;
14
+ }
15
+ /** A named set of items under one disclosure. */
16
+ export interface SidebarGroup {
17
+ id: string;
18
+ /** Text fallback for the `icon-<id>` slot. */
19
+ icon?: string;
20
+ label: string;
21
+ items: SidebarItem[];
22
+ /** Starts closed. A group holding the active item stays open regardless. */
23
+ collapsed?: boolean;
6
24
  }
25
+ export type SidebarEntry = SidebarItem | SidebarGroup;
26
+ /**
27
+ * Fired when a navigation item is chosen. Cancelable: calling
28
+ * `preventDefault()` keeps the active item where it was and, for a link,
29
+ * cancels the navigation too.
30
+ */
7
31
  export declare class DpSidebarSelectEvent extends Event {
8
32
  readonly itemId: string;
9
33
  constructor(itemId: string);
10
34
  }
35
+ /** Fired on every click of a bottom item — those are actions, not places. */
36
+ export declare class DpSidebarActionEvent extends Event {
37
+ readonly itemId: string;
38
+ constructor(itemId: string);
39
+ }
11
40
  /**
12
- * App-shell navigation rail: an icon+label list with an expanded/collapsed
13
- * state, an optional pinned bottom group, and a `footer` slot for whatever
14
- * the consumer wants to anchor at the bottom — a status badge, a version
15
- * string, anything; this repo doesn't know what.
41
+ * App-shell navigation rail: an icon+label list (flat, or grouped under
42
+ * disclosures) with an expanded/collapsed state, an optional pinned group of
43
+ * bottom actions, and a `footer` slot for whatever the consumer wants to
44
+ * anchor at the bottom — a status badge, a version string, anything; this
45
+ * repo doesn't know what.
46
+ *
47
+ * Every item's icon is a slot, `icon-<id>`, whose fallback is the item's
48
+ * `icon` text — so an icon element from any library can stand in for it.
16
49
  */
17
50
  export declare class DpSidebar extends LitElement {
18
51
  #private;
19
52
  static styles: import('lit').CSSResult;
20
- items: SidebarItem[];
53
+ items: SidebarEntry[];
54
+ /** Actions, not places — see `DpSidebarActionEvent`. */
21
55
  bottomItems: SidebarItem[];
22
56
  activeId: string;
23
57
  header: string;
58
+ /** Accessible name of the navigation landmark. Unset leaves it unnamed. */
59
+ navLabel: string;
24
60
  collapsed: boolean;
61
+ /** Groups whose open/closed state the user has flipped from their `collapsed` default. */
62
+ private toggledGroups;
25
63
  render(): import('lit-html').TemplateResult<1>;
26
64
  }
27
65
  declare global {
@@ -42,6 +42,8 @@ export declare class DpToolbar extends LitElement {
42
42
  heading: string;
43
43
  subtitle: string;
44
44
  showToggle: boolean;
45
+ /** Accessible name of the sidebar toggle — supply one in the app's language. */
46
+ toggleLabel: string;
45
47
  dragRegion: boolean;
46
48
  connectedCallback(): void;
47
49
  render(): import('lit-html').TemplateResult<1>;
package/dist/index.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import { DpPage as o } from "./page.js";
2
- import { DpSidebar as t, DpSidebarSelectEvent as l } from "./sidebar.js";
3
- import { DpToolbar as a, DpToolbarToggleEvent as S } from "./toolbar.js";
4
- import { DpShell as v, DpShellSidebarCloseEvent as b } from "./shell.js";
5
- import { DpShortcutOverlay as i, DpShortcutOverlayDismissEvent as x } from "./shortcut-overlay.js";
2
+ import { DpSidebar as p, DpSidebarActionEvent as l, DpSidebarSelectEvent as D } from "./sidebar.js";
3
+ import { DpToolbar as S, DpToolbarToggleEvent as i } from "./toolbar.js";
4
+ import { DpShell as b, DpShellSidebarCloseEvent as m } from "./shell.js";
5
+ import { DpShortcutOverlay as f, DpShortcutOverlayDismissEvent as x } from "./shortcut-overlay.js";
6
6
  export {
7
7
  o as DpPage,
8
- v as DpShell,
9
- b as DpShellSidebarCloseEvent,
10
- i as DpShortcutOverlay,
8
+ b as DpShell,
9
+ m as DpShellSidebarCloseEvent,
10
+ f as DpShortcutOverlay,
11
11
  x as DpShortcutOverlayDismissEvent,
12
- t as DpSidebar,
13
- l as DpSidebarSelectEvent,
14
- a as DpToolbar,
15
- S as DpToolbarToggleEvent
12
+ p as DpSidebar,
13
+ l as DpSidebarActionEvent,
14
+ D as DpSidebarSelectEvent,
15
+ S as DpToolbar,
16
+ i as DpToolbarToggleEvent
16
17
  };
@@ -1,21 +1,21 @@
1
- import { css as x, LitElement as b, nothing as w, html as d } from "lit";
2
- import { property as l, state as _, customElement as k } from "lit/decorators.js";
1
+ import { css as m, LitElement as x, nothing as w, html as l } from "lit";
2
+ import { property as n, state as _, customElement as k } from "lit/decorators.js";
3
3
  var $ = Object.defineProperty, E = Object.getOwnPropertyDescriptor, g = (e) => {
4
4
  throw TypeError(e);
5
- }, a = (e, t, r, c) => {
6
- for (var s = c > 1 ? void 0 : c ? E(t, r) : t, h = e.length - 1, v; h >= 0; h--)
7
- (v = e[h]) && (s = (c ? v(t, r, s) : v(s)) || s);
8
- return c && s && $(t, r, s), s;
9
- }, m = (e, t, r) => t.has(e) || g("Cannot " + r), u = (e, t, r) => (m(e, t, "read from private field"), t.get(e)), y = (e, t, r) => t.has(e) ? g("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, r), f = (e, t, r) => (m(e, t, "access private method"), r), i, n, p;
5
+ }, a = (e, t, o, d) => {
6
+ for (var s = d > 1 ? void 0 : d ? E(t, o) : t, h = e.length - 1, v; h >= 0; h--)
7
+ (v = e[h]) && (s = (d ? v(t, o, s) : v(s)) || s);
8
+ return d && s && $(t, o, s), s;
9
+ }, b = (e, t, o) => t.has(e) || g("Cannot " + o), u = (e, t, o) => (b(e, t, "read from private field"), t.get(e)), y = (e, t, o) => t.has(e) ? g("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, o), f = (e, t, o) => (b(e, t, "access private method"), o), i, c, p;
10
10
  class z extends Event {
11
11
  constructor() {
12
12
  super("dp-shortcut-overlay-dismiss", { bubbles: !0, composed: !0 });
13
13
  }
14
14
  }
15
- let C = 0, o = class extends b {
15
+ let C = 0, r = class extends x {
16
16
  constructor() {
17
- super(...arguments), y(this, n), this.shortcuts = [], this.open = !1, this.heading = "Keyboard shortcuts", this.emptyMessage = "No shortcuts registered.", this.headingId = `dp-shortcut-overlay-heading-${++C}`, y(this, i, (e) => {
18
- e.key === "Escape" && (e.preventDefault(), f(this, n, p).call(this));
17
+ super(...arguments), y(this, c), this.shortcuts = [], this.open = !1, this.heading = "Keyboard shortcuts", this.emptyMessage = "No shortcuts registered.", this.closeLabel = "Close", this.headingId = `dp-shortcut-overlay-heading-${++C}`, y(this, i, (e) => {
18
+ e.key === "Escape" && (e.preventDefault(), f(this, c, p).call(this));
19
19
  });
20
20
  }
21
21
  updated(e) {
@@ -25,8 +25,8 @@ let C = 0, o = class extends b {
25
25
  super.disconnectedCallback(), window.removeEventListener("keydown", u(this, i));
26
26
  }
27
27
  render() {
28
- return this.open ? d`
29
- <div class="backdrop" @click=${() => f(this, n, p).call(this)}>
28
+ return this.open ? l`
29
+ <div class="backdrop" @click=${() => f(this, c, p).call(this)}>
30
30
  <div
31
31
  class="panel"
32
32
  role="dialog"
@@ -36,13 +36,13 @@ let C = 0, o = class extends b {
36
36
  >
37
37
  <div class="header">
38
38
  <h2 id=${this.headingId}>${this.heading}</h2>
39
- <button class="close" aria-label="Close" @click=${() => f(this, n, p).call(this)}>×</button>
39
+ <button class="close" aria-label=${this.closeLabel} @click=${() => f(this, c, p).call(this)}>×</button>
40
40
  </div>
41
41
  <div class="body">
42
- ${this.shortcuts.length === 0 ? d`<p class="empty">${this.emptyMessage}</p>` : d`
42
+ ${this.shortcuts.length === 0 ? l`<p class="empty">${this.emptyMessage}</p>` : l`
43
43
  <ul>
44
44
  ${this.shortcuts.map(
45
- (e) => d`
45
+ (e) => l`
46
46
  <li>
47
47
  <span>${e.description}</span>
48
48
  <kbd>${e.combo}</kbd>
@@ -58,11 +58,11 @@ let C = 0, o = class extends b {
58
58
  }
59
59
  };
60
60
  i = /* @__PURE__ */ new WeakMap();
61
- n = /* @__PURE__ */ new WeakSet();
61
+ c = /* @__PURE__ */ new WeakSet();
62
62
  p = function() {
63
63
  this.dispatchEvent(new z());
64
64
  };
65
- o.styles = x`
65
+ r.styles = m`
66
66
  :host {
67
67
  display: contents;
68
68
  font-family: var(--dc-font-family, system-ui, sans-serif);
@@ -149,24 +149,27 @@ o.styles = x`
149
149
  }
150
150
  `;
151
151
  a([
152
- l({ type: Array })
153
- ], o.prototype, "shortcuts", 2);
152
+ n({ type: Array })
153
+ ], r.prototype, "shortcuts", 2);
154
154
  a([
155
- l({ type: Boolean, reflect: !0 })
156
- ], o.prototype, "open", 2);
155
+ n({ type: Boolean, reflect: !0 })
156
+ ], r.prototype, "open", 2);
157
157
  a([
158
- l()
159
- ], o.prototype, "heading", 2);
158
+ n()
159
+ ], r.prototype, "heading", 2);
160
160
  a([
161
- l({ attribute: "empty-message" })
162
- ], o.prototype, "emptyMessage", 2);
161
+ n({ attribute: "empty-message" })
162
+ ], r.prototype, "emptyMessage", 2);
163
+ a([
164
+ n({ attribute: "close-label" })
165
+ ], r.prototype, "closeLabel", 2);
163
166
  a([
164
167
  _()
165
- ], o.prototype, "headingId", 2);
166
- o = a([
168
+ ], r.prototype, "headingId", 2);
169
+ r = a([
167
170
  k("dp-shortcut-overlay")
168
- ], o);
171
+ ], r);
169
172
  export {
170
- o as DpShortcutOverlay,
173
+ r as DpShortcutOverlay,
171
174
  z as DpShortcutOverlayDismissEvent
172
175
  };
package/dist/sidebar.js CHANGED
@@ -1,51 +1,110 @@
1
- import { css as m, LitElement as x, nothing as c, html as i } from "lit";
2
- import { property as d, customElement as g } from "lit/decorators.js";
3
- var y = Object.defineProperty, w = Object.getOwnPropertyDescriptor, b = (e) => {
1
+ import { css as $, LitElement as w, nothing as i, html as s } from "lit";
2
+ import { property as h, state as _, customElement as I } from "lit/decorators.js";
3
+ var k = Object.defineProperty, A = Object.getOwnPropertyDescriptor, m = (e) => {
4
4
  throw TypeError(e);
5
- }, s = (e, t, a, l) => {
6
- for (var o = l > 1 ? void 0 : l ? w(t, a) : t, p = e.length - 1, h; p >= 0; p--)
7
- (h = e[p]) && (o = (l ? h(t, a, o) : h(o)) || o);
8
- return l && o && y(t, a, o), o;
9
- }, _ = (e, t, a) => t.has(e) || b("Cannot " + a), I = (e, t, a) => t.has(e) ? b("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, a), v = (e, t, a) => (_(e, t, "access private method"), a), n, f, u;
10
- class $ extends Event {
5
+ }, d = (e, t, a, r) => {
6
+ for (var c = r > 1 ? void 0 : r ? A(t, a) : t, p = e.length - 1, v; p >= 0; p--)
7
+ (v = e[p]) && (c = (r ? v(t, a, c) : v(c)) || c);
8
+ return r && c && k(t, a, c), c;
9
+ }, E = (e, t, a) => t.has(e) || m("Cannot " + a), G = (e, t, a) => t.has(e) ? m("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, a), l = (e, t, a) => (E(e, t, "access private method"), a), o, g, f, x, u, b, y;
10
+ const S = (e) => Array.isArray(e.items);
11
+ class D extends Event {
11
12
  constructor(t) {
12
- super("dp-sidebar-select", { bubbles: !0, composed: !0 }), this.itemId = t;
13
+ super("dp-sidebar-select", { bubbles: !0, composed: !0, cancelable: !0 }), this.itemId = t;
13
14
  }
14
15
  }
15
- let r = class extends x {
16
+ class z extends Event {
17
+ constructor(t) {
18
+ super("dp-sidebar-action", { bubbles: !0, composed: !0 }), this.itemId = t;
19
+ }
20
+ }
21
+ let n = class extends w {
16
22
  constructor() {
17
- super(...arguments), I(this, n), this.items = [], this.bottomItems = [], this.activeId = "", this.header = "", this.collapsed = !1;
23
+ super(...arguments), G(this, o), this.items = [], this.bottomItems = [], this.activeId = "", this.header = "", this.navLabel = "", this.collapsed = !1, this.toggledGroups = /* @__PURE__ */ new Set();
18
24
  }
19
25
  render() {
20
- return i`
26
+ return s`
21
27
  <div class="header">
22
28
  <slot name="icon"></slot>
23
- ${!this.collapsed && this.header ? i`<span class="header-label">${this.header}</span>` : c}
29
+ ${!this.collapsed && this.header ? s`<span class="header-label">${this.header}</span>` : i}
24
30
  </div>
25
- <nav>${this.items.map((e) => v(this, n, f).call(this, e))}</nav>
26
- ${this.bottomItems.length > 0 ? i`<div class="bottom-group">${this.bottomItems.map((e) => v(this, n, f).call(this, e))}</div>` : c}
31
+ <nav aria-label=${this.navLabel || i}>
32
+ ${this.items.map((e) => S(e) ? l(this, o, g).call(this, e) : l(this, o, f).call(this, e))}
33
+ </nav>
34
+ ${this.bottomItems.length > 0 ? s`<div class="bottom-group">${this.bottomItems.map((e) => l(this, o, x).call(this, e))}</div>` : i}
27
35
  <div class="footer"><slot name="footer"></slot></div>
28
36
  `;
29
37
  }
30
38
  };
31
- n = /* @__PURE__ */ new WeakSet();
39
+ o = /* @__PURE__ */ new WeakSet();
40
+ g = function(e) {
41
+ const t = e.items.some((p) => p.id === this.activeId), a = e.collapsed === !0, r = this.collapsed || t || a === this.toggledGroups.has(e.id), c = `group-${e.id}`;
42
+ return s`
43
+ <div class="group">
44
+ ${this.collapsed ? i : s`<button
45
+ class="item group-toggle"
46
+ aria-expanded=${r ? "true" : "false"}
47
+ aria-controls=${c}
48
+ @click=${() => l(this, o, y).call(this, e.id)}
49
+ >
50
+ ${l(this, o, u).call(this, e.id, e.icon ?? "")}
51
+ <span class="label">${e.label}</span>
52
+ <span class="caret" aria-hidden="true">▾</span>
53
+ </button>`}
54
+ <div class="group-items" id=${c} role="group" aria-label=${e.label} ?hidden=${!r}>
55
+ ${e.items.map((p) => l(this, o, f).call(this, p))}
56
+ </div>
57
+ </div>
58
+ `;
59
+ };
32
60
  f = function(e) {
33
- const t = e.id === this.activeId;
34
- return i`
61
+ const t = e.id === this.activeId, a = s`
62
+ ${l(this, o, u).call(this, e.id, e.icon)} ${this.collapsed ? i : s`<span class="label">${e.label}</span>`}
63
+ `;
64
+ return e.href !== void 0 ? s`<a
65
+ class="item"
66
+ href=${e.href}
67
+ title=${this.collapsed ? e.label : i}
68
+ aria-current=${t ? "page" : i}
69
+ @click=${(r) => l(this, o, b).call(this, r, e)}
70
+ >${a}</a
71
+ >` : s`<button
72
+ class="item"
73
+ title=${this.collapsed ? e.label : i}
74
+ aria-current=${t ? "page" : i}
75
+ @click=${(r) => l(this, o, b).call(this, r, e)}
76
+ >
77
+ ${a}
78
+ </button>`;
79
+ };
80
+ x = function(e) {
81
+ return s`
35
82
  <button
36
- title=${this.collapsed ? e.label : c}
37
- aria-current=${t ? "page" : c}
38
- @click=${() => v(this, n, u).call(this, e.id)}
83
+ class="item"
84
+ title=${this.collapsed ? e.label : i}
85
+ @click=${() => this.dispatchEvent(new z(e.id))}
39
86
  >
40
- <span class="icon" aria-hidden="true">${e.icon}</span>
41
- ${this.collapsed ? c : i`<span>${e.label}</span>`}
87
+ ${l(this, o, u).call(this, e.id, e.icon)} ${this.collapsed ? i : s`<span class="label">${e.label}</span>`}
42
88
  </button>
43
89
  `;
44
90
  };
45
- u = function(e) {
46
- e !== this.activeId && (this.activeId = e, this.dispatchEvent(new $(e)));
91
+ u = function(e, t) {
92
+ return s`<span class="icon" aria-hidden="true"><slot name=${`icon-${e}`}>${t}</slot></span>`;
93
+ };
94
+ b = function(e, t) {
95
+ if (!(t.href !== void 0 && (e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey)) && t.id !== this.activeId) {
96
+ if (!this.dispatchEvent(new D(t.id))) {
97
+ e.preventDefault();
98
+ return;
99
+ }
100
+ this.activeId = t.id;
101
+ }
102
+ };
103
+ y = function(e) {
104
+ const t = new Set(this.toggledGroups);
105
+ t.delete(e) || t.add(e), this.toggledGroups = t;
47
106
  };
48
- r.styles = m`
107
+ n.styles = $`
49
108
  :host {
50
109
  display: flex;
51
110
  flex-direction: column;
@@ -89,11 +148,12 @@ r.styles = m`
89
148
  border-top: 1px solid var(--dc-color-border, #e2e2e4);
90
149
  padding: var(--dc-space-1, 4px) 0;
91
150
  }
92
- button {
151
+ .item {
93
152
  appearance: none;
94
153
  background: none;
95
154
  border: none;
96
155
  border-left: 2px solid transparent;
156
+ box-sizing: border-box;
97
157
  width: 100%;
98
158
  display: flex;
99
159
  align-items: center;
@@ -103,12 +163,23 @@ r.styles = m`
103
163
  font-size: var(--dc-font-size-sm, 12px);
104
164
  color: var(--dc-color-text-secondary, #55555c);
105
165
  text-align: left;
166
+ text-decoration: none;
106
167
  cursor: pointer;
107
168
  }
108
- :host([collapsed]) button {
169
+ :host([collapsed]) .item {
109
170
  justify-content: center;
110
171
  padding: var(--dc-space-3, 12px) 0;
111
172
  }
173
+ /* Items inside an open group sit one step in, so the group reads as a set. */
174
+ :host(:not([collapsed])) .group-items .item {
175
+ padding-left: calc(var(--dc-space-3, 12px) * 2);
176
+ }
177
+ /* In the collapsed rail a group has no label to show; a rule marks where it starts. */
178
+ :host([collapsed]) .group + .group,
179
+ :host([collapsed]) .item + .group,
180
+ :host([collapsed]) .group + .item {
181
+ border-top: 1px solid var(--dc-color-border, #e2e2e4);
182
+ }
112
183
  /* The rail marker keeps the fill accent - it is a 3px bar, judged as a UI
113
184
  component (WCAG 1.4.11, 3:1). The label does not: an accent chosen to be
114
185
  read as a *fill* is not necessarily readable as 12px text on the hover
@@ -118,15 +189,15 @@ r.styles = m`
118
189
  find. --dc-color-accent-text lets a consumer supply the readable
119
190
  variant; falling back to the fill accent keeps every existing consumer
120
191
  rendering exactly as before. */
121
- button[aria-current='page'] {
192
+ .item[aria-current='page'] {
122
193
  border-left-color: var(--dc-color-accent, #2563eb);
123
194
  color: var(--dc-color-accent-text, var(--dc-color-accent, #2563eb));
124
195
  font-weight: var(--dc-font-weight-medium, 500);
125
196
  }
126
- button:hover {
197
+ .item:hover {
127
198
  background: var(--dc-color-surface-hover, #ececed);
128
199
  }
129
- button:focus-visible {
200
+ .item:focus-visible {
130
201
  outline: 2px solid var(--dc-color-accent, #2563eb);
131
202
  outline-offset: -2px;
132
203
  }
@@ -135,29 +206,43 @@ r.styles = m`
135
206
  width: 1.25em;
136
207
  text-align: center;
137
208
  }
209
+ .caret {
210
+ margin-left: auto;
211
+ transition: transform 0.15s;
212
+ }
213
+ .group-toggle[aria-expanded='false'] .caret {
214
+ transform: rotate(-90deg);
215
+ }
138
216
  .footer {
139
217
  border-top: 1px solid var(--dc-color-border, #e2e2e4);
140
218
  }
141
219
  `;
142
- s([
143
- d({ type: Array })
144
- ], r.prototype, "items", 2);
145
- s([
146
- d({ type: Array, attribute: "bottom-items" })
147
- ], r.prototype, "bottomItems", 2);
148
- s([
149
- d({ attribute: "active-id" })
150
- ], r.prototype, "activeId", 2);
151
- s([
152
- d()
153
- ], r.prototype, "header", 2);
154
- s([
155
- d({ type: Boolean, reflect: !0 })
156
- ], r.prototype, "collapsed", 2);
157
- r = s([
158
- g("dp-sidebar")
159
- ], r);
220
+ d([
221
+ h({ type: Array })
222
+ ], n.prototype, "items", 2);
223
+ d([
224
+ h({ type: Array, attribute: "bottom-items" })
225
+ ], n.prototype, "bottomItems", 2);
226
+ d([
227
+ h({ attribute: "active-id" })
228
+ ], n.prototype, "activeId", 2);
229
+ d([
230
+ h()
231
+ ], n.prototype, "header", 2);
232
+ d([
233
+ h({ attribute: "nav-label" })
234
+ ], n.prototype, "navLabel", 2);
235
+ d([
236
+ h({ type: Boolean, reflect: !0 })
237
+ ], n.prototype, "collapsed", 2);
238
+ d([
239
+ _()
240
+ ], n.prototype, "toggledGroups", 2);
241
+ n = d([
242
+ I("dp-sidebar")
243
+ ], n);
160
244
  export {
161
- r as DpSidebar,
162
- $ as DpSidebarSelectEvent
245
+ n as DpSidebar,
246
+ z as DpSidebarActionEvent,
247
+ D as DpSidebarSelectEvent
163
248
  };
package/dist/toolbar.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import { css as p, LitElement as g, nothing as h, html as d } from "lit";
2
- import { property as s, customElement as v } from "lit/decorators.js";
3
- var f = Object.defineProperty, b = Object.getOwnPropertyDescriptor, o = (l, r, i, a) => {
4
- for (var e = a > 1 ? void 0 : a ? b(r, i) : r, n = l.length - 1, c; n >= 0; n--)
5
- (c = l[n]) && (e = (a ? c(r, i, e) : c(e)) || e);
6
- return a && e && f(r, i, e), e;
2
+ import { property as r, customElement as b } from "lit/decorators.js";
3
+ var v = Object.defineProperty, f = Object.getOwnPropertyDescriptor, o = (l, a, i, s) => {
4
+ for (var t = s > 1 ? void 0 : s ? f(a, i) : a, n = l.length - 1, c; n >= 0; n--)
5
+ (c = l[n]) && (t = (s ? c(a, i, t) : c(t)) || t);
6
+ return s && t && v(a, i, t), t;
7
7
  };
8
8
  class u extends Event {
9
9
  constructor() {
10
10
  super("dp-toolbar-toggle", { bubbles: !0, composed: !0 });
11
11
  }
12
12
  }
13
- let t = class extends g {
13
+ let e = class extends g {
14
14
  constructor() {
15
- super(...arguments), this.heading = "", this.subtitle = "", this.showToggle = !1, this.dragRegion = !1;
15
+ super(...arguments), this.heading = "", this.subtitle = "", this.showToggle = !1, this.toggleLabel = "Toggle sidebar", this.dragRegion = !1;
16
16
  }
17
17
  connectedCallback() {
18
18
  super.connectedCallback(), this.setAttribute("role", "banner");
@@ -22,7 +22,7 @@ let t = class extends g {
22
22
  <div class="start">
23
23
  ${this.showToggle ? d`<button
24
24
  class="toggle"
25
- aria-label="Toggle sidebar"
25
+ aria-label=${this.toggleLabel}
26
26
  @click=${() => this.dispatchEvent(new u())}
27
27
  >
28
28
  ☰
@@ -34,7 +34,7 @@ let t = class extends g {
34
34
  `;
35
35
  }
36
36
  };
37
- t.styles = p`
37
+ e.styles = p`
38
38
  :host {
39
39
  display: flex;
40
40
  align-items: center;
@@ -91,21 +91,24 @@ t.styles = p`
91
91
  }
92
92
  `;
93
93
  o([
94
- s()
95
- ], t.prototype, "heading", 2);
94
+ r()
95
+ ], e.prototype, "heading", 2);
96
96
  o([
97
- s()
98
- ], t.prototype, "subtitle", 2);
97
+ r()
98
+ ], e.prototype, "subtitle", 2);
99
99
  o([
100
- s({ type: Boolean, attribute: "show-toggle" })
101
- ], t.prototype, "showToggle", 2);
100
+ r({ type: Boolean, attribute: "show-toggle" })
101
+ ], e.prototype, "showToggle", 2);
102
102
  o([
103
- s({ type: Boolean, reflect: !0, attribute: "drag-region" })
104
- ], t.prototype, "dragRegion", 2);
105
- t = o([
106
- v("dp-toolbar")
107
- ], t);
103
+ r({ attribute: "toggle-label" })
104
+ ], e.prototype, "toggleLabel", 2);
105
+ o([
106
+ r({ type: Boolean, reflect: !0, attribute: "drag-region" })
107
+ ], e.prototype, "dragRegion", 2);
108
+ e = o([
109
+ b("dp-toolbar")
110
+ ], e);
108
111
  export {
109
- t as DpToolbar,
112
+ e as DpToolbar,
110
113
  u as DpToolbarToggleEvent
111
114
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/desktop-patterns",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -57,10 +57,13 @@
57
57
  "build-storybook": "storybook build"
58
58
  },
59
59
  "dependencies": {
60
- "@iyulab/desktop-compact": "^0.2.0",
61
60
  "lit": "^3.2.1"
62
61
  },
62
+ "peerDependencies": {
63
+ "@iyulab/desktop-compact": "^0.2.0 || ^0.3.0"
64
+ },
63
65
  "devDependencies": {
66
+ "@iyulab/desktop-compact": "^0.3.0",
64
67
  "@open-wc/testing": "^4.0.0",
65
68
  "@storybook/addon-essentials": "^8.3.0",
66
69
  "@storybook/web-components": "^8.3.0",