@xleddyl/443-components-vue 0.9.2 → 0.9.3

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
@@ -509,7 +509,7 @@ A large dialog (60rem) with a section nav on the left and the content on the rig
509
509
  - Built-in sections, used when no `#section-<id>` slot fills them: `account` (profile card, your `#account-fields`, a sign out button) and `appearance` (`AppearanceSettings`: theme cards light, dark, system and preset cards; `presets` limits or hides them).
510
510
  - `@sign-out` adds a Sign out item at the bottom of the nav and in the account section.
511
511
  - Labels: `title` (accessible name of the dialog, default `Settings`), `closeLabel`, `navLabel`, `signOutLabel`, `accountLabel`, `accountText`, `appearanceLabel`, `appearanceText`, `sessionLabel`, `sessionText`, `themeLabel`, `themeText`, `presetLabel`, `presetText`.
512
- - Subpages: `#section-<id>` and `#actions-<id>` get `page`, `pages`, `openPage({ id, label })` and `back()`. With a page open, a breadcrumb from the section to the page shows below the header (the header keeps the section title and description); a click on a breadcrumb goes back to it. `v-model:pages` binds the stack (it also works unbound). Changing section clears it. Render the detail when `page` is set, the list otherwise.
512
+ - Subpages: `#section-<id>` and `#actions-<id>` get `page`, `pages`, `openPage({ id, label })` and `back()`. With a page open, the header title becomes the path (`Members > Grace Hopper`, same size, only the last part in the text color, earlier parts are buttons that go back to them), the section description stays, and a Back button (`backLabel`, default `common.back`) shows on the right before `#actions-<id>`. `v-model:pages` binds the stack (it also works unbound). Changing section clears it. Render the detail when `page` is set, the list otherwise.
513
513
  - `hide-session` hides the Session group (sign out) in the account section; the Sign out item in the nav stays. `beforeClose` works as on Modal.
514
514
  - Accessibility: native modal `<dialog>` (focus trap, Escape, focus returns to the trigger), the nav is a labelled `nav` of buttons with `aria-current` and `aria-controls`, the content is a `section` labelled by its heading.
515
515
 
@@ -99,21 +99,44 @@
99
99
  <header class="k-settings-modal-header">
100
100
  <div class="k-settings-modal-heading">
101
101
  <h2 :id="`${baseId}-title`" class="k-settings-modal-title">
102
- {{ active.label }}
102
+ <template v-if="currentPage">
103
+ <template v-for="(crumb, index) in trail" :key="index">
104
+ <button
105
+ type="button"
106
+ class="k-settings-modal-crumb"
107
+ @click="goTo(index)"
108
+ >
109
+ {{ crumb }}
110
+ </button>
111
+ <Icon name="chevron-right" class="k-settings-modal-crumb-separator" />
112
+ </template>
113
+ <span class="k-settings-modal-crumb is-current">
114
+ {{ currentPage.label }}
115
+ </span>
116
+ </template>
117
+ <template v-else>{{ active.label }}</template>
103
118
  </h2>
104
119
  <p v-if="active.description" class="k-settings-modal-description">
105
120
  {{ active.description }}
106
121
  </p>
107
122
  </div>
108
- <div v-if="$slots[`actions-${active.id}`]" class="k-settings-modal-actions">
123
+ <div
124
+ v-if="currentPage || $slots[`actions-${active.id}`]"
125
+ class="k-settings-modal-actions"
126
+ >
127
+ <Button
128
+ v-if="currentPage"
129
+ variant="ghost"
130
+ tone="neutral"
131
+ size="sm"
132
+ icon="arrow-left"
133
+ @click="back"
134
+ >
135
+ {{ backText }}
136
+ </Button>
109
137
  <slot :name="`actions-${active.id}`" v-bind="slotProps(active, close)" />
110
138
  </div>
111
139
  </header>
112
- <Breadcrumbs
113
- v-if="currentPage"
114
- class="k-settings-modal-breadcrumbs"
115
- :items="breadcrumbItems"
116
- />
117
140
  <div
118
141
  ref="contentBody"
119
142
  class="k-settings-modal-body"
@@ -186,7 +209,6 @@ import Icon from "../core/Icon.vue";
186
209
  import Avatar from "../data/Avatar.vue";
187
210
  import Badge from "../data/Badge.vue";
188
211
  import Modal from "../overlays/Modal.vue";
189
- import Breadcrumbs from "../layout/Breadcrumbs.vue";
190
212
  import AppearanceSettings from "./AppearanceSettings.vue";
191
213
  import SettingsGroup from "./SettingsGroup.vue";
192
214
  const props = defineProps({
@@ -195,6 +217,7 @@ const props = defineProps({
195
217
  presets: { type: [Array, Boolean], required: false, default: () => THEME_PRESETS },
196
218
  title: { type: String, required: false },
197
219
  closeLabel: { type: String, required: false },
220
+ backLabel: { type: String, required: false },
198
221
  navLabel: { type: String, required: false },
199
222
  signOutLabel: { type: String, required: false },
200
223
  sessionLabel: { type: String, required: false },
@@ -219,6 +242,7 @@ const pages = defineModel("pages", { type: Array, ...{ default: () => [] } });
219
242
  const { t } = useLocale();
220
243
  const titleText = computed(() => props.title ?? t("settings.title"));
221
244
  const closeText = computed(() => props.closeLabel ?? t("settings.close"));
245
+ const backText = computed(() => props.backLabel ?? t("common.back"));
222
246
  const navText = computed(() => props.navLabel ?? t("settings.sections"));
223
247
  const signOutText = computed(() => props.signOutLabel ?? t("settings.signOut"));
224
248
  const sessionLabelText = computed(() => props.sessionLabel ?? t("settings.session"));
@@ -276,12 +300,9 @@ function openPage(page) {
276
300
  function back() {
277
301
  goTo(pages.value.length - 1);
278
302
  }
279
- const breadcrumbItems = computed(() => [
280
- { label: active.value?.label ?? "", onClick: () => goTo(0) },
281
- ...pages.value.map((page, index) => ({
282
- label: page.label,
283
- onClick: index < pages.value.length - 1 ? () => goTo(index + 1) : void 0
284
- }))
303
+ const trail = computed(() => [
304
+ active.value?.label ?? "",
305
+ ...pages.value.slice(0, -1).map((page) => page.label)
285
306
  ]);
286
307
  function slotProps(item, close) {
287
308
  return { section: item, close, page: currentPage.value, pages: pages.value, openPage, back };
@@ -16,6 +16,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
16
16
  presets?: readonly ThemePreset[] | false;
17
17
  title?: string | undefined;
18
18
  closeLabel?: string;
19
+ backLabel?: string;
19
20
  navLabel?: string;
20
21
  signOutLabel?: string;
21
22
  sessionLabel?: string;
@@ -257,6 +258,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
257
258
  presets?: readonly ThemePreset[] | false;
258
259
  title?: string | undefined;
259
260
  closeLabel?: string;
261
+ backLabel?: string;
260
262
  navLabel?: string;
261
263
  signOutLabel?: string;
262
264
  sessionLabel?: string;
@@ -161,11 +161,6 @@
161
161
  min-width: 0;
162
162
  }
163
163
 
164
- .k-settings-modal-breadcrumbs {
165
- flex: none;
166
- padding: 0 1.5rem 0.75rem;
167
- }
168
-
169
164
  .k-settings-modal-title {
170
165
  font-size: 0.9375rem;
171
166
  font-weight: var(--k-font-weight-strong, 600);
@@ -174,6 +169,44 @@
174
169
  color: var(--k-text);
175
170
  }
176
171
 
172
+ .k-settings-modal-title:has(> .k-settings-modal-crumb) {
173
+ display: flex;
174
+ flex-wrap: wrap;
175
+ align-items: center;
176
+ gap: 0.25rem;
177
+ }
178
+
179
+ .k-settings-modal-crumb {
180
+ padding: 0;
181
+ font: inherit;
182
+ letter-spacing: inherit;
183
+ color: var(--k-text-muted);
184
+ background: none;
185
+ border: 0;
186
+ border-radius: var(--k-radius-xs);
187
+ cursor: pointer;
188
+ transition: color var(--k-duration) var(--k-ease);
189
+ }
190
+
191
+ .k-settings-modal-crumb:hover {
192
+ color: var(--k-text);
193
+ }
194
+
195
+ .k-settings-modal-crumb:focus-visible {
196
+ outline: 2px solid var(--k-ring);
197
+ outline-offset: 2px;
198
+ }
199
+
200
+ .k-settings-modal-crumb.is-current {
201
+ color: var(--k-text);
202
+ cursor: default;
203
+ }
204
+
205
+ .k-settings-modal-crumb-separator {
206
+ --k-icon-size: 0.875rem;
207
+ color: var(--k-text-dimmed);
208
+ }
209
+
177
210
  .k-settings-modal-description {
178
211
  font-size: 0.8125rem;
179
212
  line-height: 1.4;
@@ -478,10 +511,6 @@
478
511
  padding: 1rem 1rem 0.75rem;
479
512
  }
480
513
 
481
- .k-settings-modal-breadcrumbs {
482
- padding-inline: 1rem;
483
- }
484
-
485
514
  .k-settings-modal-body {
486
515
  padding: 1rem;
487
516
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xleddyl/443-components-vue",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Compact, scoped dashboard components for Vue and Nuxt",
5
5
  "license": "MIT",
6
6
  "author": "Edoardo Alberti (https://github.com/xleddyl)",