@xleddyl/443-components-vue 0.9.1 → 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
|
|
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
|
|
|
@@ -98,19 +98,42 @@
|
|
|
98
98
|
>
|
|
99
99
|
<header class="k-settings-modal-header">
|
|
100
100
|
<div class="k-settings-modal-heading">
|
|
101
|
-
<Breadcrumbs
|
|
102
|
-
v-if="currentPage"
|
|
103
|
-
class="k-settings-modal-breadcrumbs"
|
|
104
|
-
:items="breadcrumbItems"
|
|
105
|
-
/>
|
|
106
101
|
<h2 :id="`${baseId}-title`" class="k-settings-modal-title">
|
|
107
|
-
|
|
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>
|
|
108
118
|
</h2>
|
|
109
|
-
<p v-if="
|
|
110
|
-
{{
|
|
119
|
+
<p v-if="active.description" class="k-settings-modal-description">
|
|
120
|
+
{{ active.description }}
|
|
111
121
|
</p>
|
|
112
122
|
</div>
|
|
113
|
-
<div
|
|
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>
|
|
114
137
|
<slot :name="`actions-${active.id}`" v-bind="slotProps(active, close)" />
|
|
115
138
|
</div>
|
|
116
139
|
</header>
|
|
@@ -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"));
|
|
@@ -267,9 +291,6 @@ const activeId = computed(() => {
|
|
|
267
291
|
});
|
|
268
292
|
const active = computed(() => sectionList.value.find((item) => item.id === activeId.value));
|
|
269
293
|
const currentPage = computed(() => pages.value.at(-1));
|
|
270
|
-
const headingDescription = computed(
|
|
271
|
-
() => currentPage.value ? currentPage.value.description : active.value?.description
|
|
272
|
-
);
|
|
273
294
|
function goTo(depth) {
|
|
274
295
|
pages.value = pages.value.slice(0, depth);
|
|
275
296
|
}
|
|
@@ -279,12 +300,9 @@ function openPage(page) {
|
|
|
279
300
|
function back() {
|
|
280
301
|
goTo(pages.value.length - 1);
|
|
281
302
|
}
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
...pages.value.map((page
|
|
285
|
-
label: page.label,
|
|
286
|
-
onClick: index < pages.value.length - 1 ? () => goTo(index + 1) : void 0
|
|
287
|
-
}))
|
|
303
|
+
const trail = computed(() => [
|
|
304
|
+
active.value?.label ?? "",
|
|
305
|
+
...pages.value.slice(0, -1).map((page) => page.label)
|
|
288
306
|
]);
|
|
289
307
|
function slotProps(item, close) {
|
|
290
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,10 +161,6 @@
|
|
|
161
161
|
min-width: 0;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
.k-settings-modal-breadcrumbs {
|
|
165
|
-
margin-bottom: 0.25rem;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
164
|
.k-settings-modal-title {
|
|
169
165
|
font-size: 0.9375rem;
|
|
170
166
|
font-weight: var(--k-font-weight-strong, 600);
|
|
@@ -173,6 +169,44 @@
|
|
|
173
169
|
color: var(--k-text);
|
|
174
170
|
}
|
|
175
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
|
+
|
|
176
210
|
.k-settings-modal-description {
|
|
177
211
|
font-size: 0.8125rem;
|
|
178
212
|
line-height: 1.4;
|
package/package.json
CHANGED