@iyulab/desktop-patterns 0.9.0 → 0.10.1

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
@@ -115,7 +115,10 @@ nav.items = [
115
115
  },
116
116
  ]
117
117
  nav.pinnedItems = [{ id: 'settings', icon: '⚙', label: 'Settings' }] // places kept at the foot of the rail
118
- nav.bottomItems = [{ id: 'sign-out', icon: '⎋', label: 'Sign out' }] // actions, not places
118
+ nav.bottomItems = [
119
+ { id: 'dense', icon: '▤', label: 'Dense mode', pressed: false }, // a toggle: aria-pressed, owned by you
120
+ { id: 'sign-out', icon: '⎋', label: 'Sign out' }, // actions, not places
121
+ ]
119
122
  nav.setAttribute('nav-label', 'Main') // names the navigation landmark
120
123
  ```
121
124
 
@@ -136,6 +139,11 @@ nav.setAttribute('nav-label', 'Main') // names t
136
139
  settings or help page shown there is marked as the current page.
137
140
  - **Bottom items are actions**: each click fires `dp-sidebar-action` (`itemId`) — every time, so a failed action can
138
141
  be retried — and never moves `aria-current`. (In 0.2.x they fired `dp-sidebar-select` and took the active mark.)
142
+ - **Toggle actions**: a bottom action with `pressed` (`{ id, icon, label, pressed: true | false }`) is a setting it
143
+ turns on and off. The button carries `aria-pressed`, and an on toggle gets a quiet ground and an accent icon
144
+ (`--dp-sidebar-pressed-bg`, `--dp-sidebar-pressed-icon-color`) that still shows in the collapsed rail. Name it after
145
+ the setting ("Dense mode"), not the click ("Turn dense mode on"). The sidebar does not flip it — change the value
146
+ on `dp-sidebar-action` and set `bottomItems` again.
139
147
 
140
148
  Every component takes its user-facing text as a plain attribute/property or slot — there is no
141
149
  built-in i18n layer. See each component's Storybook story (`npm run storybook`) for its full API.
@@ -12,6 +12,19 @@ export interface SidebarItem {
12
12
  label: string;
13
13
  href?: string;
14
14
  }
15
+ /**
16
+ * One bottom action. With `pressed` it is a toggle — a setting the action turns on and off (a dense
17
+ * or touch mode, a theme): the button carries `aria-pressed` and, when on, a quiet ground and an accent
18
+ * icon. Its `label` then names the setting, not what a click would do. The sidebar does not flip it;
19
+ * the consumer owns the state, changes it on `dp-sidebar-action`, and passes the new value back.
20
+ */
21
+ export interface SidebarAction {
22
+ id: string;
23
+ /** Text fallback for the `icon-<id>` slot. */
24
+ icon: string;
25
+ label: string;
26
+ pressed?: boolean;
27
+ }
15
28
  /** A named set of items under one disclosure. */
16
29
  export interface SidebarGroup {
17
30
  id: string;
@@ -68,7 +81,7 @@ export declare class DpSidebar extends LitElement {
68
81
  */
69
82
  pinnedItems: SidebarItem[];
70
83
  /** Actions, not places — see `DpSidebarActionEvent`. A place belongs in `pinnedItems`. */
71
- bottomItems: SidebarItem[];
84
+ bottomItems: SidebarAction[];
72
85
  activeId: string;
73
86
  header: string;
74
87
  /** Accessible name of the navigation landmark. Unset leaves it unnamed. */
package/dist/sidebar.js CHANGED
@@ -146,6 +146,17 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
146
146
  .item[aria-current='page']:hover {
147
147
  background: var(--dc-selection-bg, var(--dc-color-surface-hover, #ececed));
148
148
  }
149
+ /* A toggle that is on. Not a place, so not the rail marker or the current-page colour of the label:
150
+ a quiet ground (--dp-sidebar-pressed-bg) and the accent on the icon, so it still reads in the
151
+ collapsed rail, where only the icon shows. Declared after :hover so hovering keeps the ground. */
152
+ .item[aria-pressed='true'],
153
+ .item[aria-pressed='true']:hover {
154
+ background: var(--dp-sidebar-pressed-bg, var(--dc-selection-bg, var(--dc-color-surface-hover, #ececed)));
155
+ color: var(--dc-color-text, #1d1d1f);
156
+ }
157
+ .item[aria-pressed='true'] .icon {
158
+ color: var(--dp-sidebar-pressed-icon-color, var(--dc-color-accent-text, var(--dc-color-accent, #2563eb)));
159
+ }
149
160
  .item:focus-visible {
150
161
  outline: 2px solid var(--dc-color-accent, #2563eb);
151
162
  outline-offset: -2px;
@@ -162,6 +173,12 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
162
173
  .group-toggle[aria-expanded='false'] .caret {
163
174
  transform: rotate(-90deg);
164
175
  }
176
+ /* The turn is decoration: with reduced motion the caret takes its new angle at once. */
177
+ @media (prefers-reduced-motion: reduce) {
178
+ .caret {
179
+ transition: none;
180
+ }
181
+ }
165
182
  .footer {
166
183
  border-top: 1px solid var(--dc-color-border, #e2e2e4);
167
184
  }
@@ -228,6 +245,7 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
228
245
  <button
229
246
  class="item"
230
247
  title=${this.collapsed ? e.label : i}
248
+ aria-pressed=${e.pressed === void 0 ? i : e.pressed ? "true" : "false"}
231
249
  @click=${() => this.dispatchEvent(new d(e.id))}
232
250
  >
233
251
  ${this.#r(e.id, e.icon)} ${this.collapsed ? i : r`<span class="label">${e.label}</span>`}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/desktop-patterns",
3
- "version": "0.9.0",
3
+ "version": "0.10.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {