Skip to content

Commit 9b8b844

Browse files
committed
feat(settings-dialog): Align title with navigation column
The settings dialog title now sits over a tinted navigation column on the inline-start edge of the dialog, replacing the centered header. Navigation links use the default button weight with a rounded inline-start stripe on the active item, mirroring the navigation-item redesign. Closes #7641 Signed-off-by: nfebe <fenn25.fn@gmail.com>
1 parent 9cf17af commit 9b8b844

2 files changed

Lines changed: 189 additions & 43 deletions

File tree

src/components/NcAppSettingsDialog/NcAppSettingsDialog.vue

Lines changed: 186 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import NcVNodes from '../NcVNodes/NcVNodes.vue'
1313
import NcAppSettingsDialogVersion from './NcAppSettingsDialogVersion.vue'
1414
import { useIsMobile } from '../../composables/useIsMobile/index.ts'
1515
import { t } from '../../l10n.ts'
16+
import { isLegacy34 } from '../../utils/legacy.ts'
1617
import { APP_SETTINGS_LEGACY_DESIGN_KEY, APP_SETTINGS_REGISTRATION_KEY } from './useAppSettingsDialog.ts'
1718
1819
export interface IAppSettingsSection {
@@ -215,6 +216,7 @@ function unregisterSection(id: string) {
215216
<NcDialog
216217
v-if="open"
217218
class="app-settings"
219+
:class="{ 'app-settings--legacy': isLegacy34 }"
218220
contentClasses="app-settings__content"
219221
navigationClasses="app-settings__navigation"
220222
:additionalTrapElements
@@ -225,6 +227,9 @@ function unregisterSection(id: string) {
225227
:name
226228
@update:open="handleCloseModal">
227229
<template v-if="hasNavigation" #navigation="{ isCollapsed }">
230+
<div v-if="!isLegacy34" class="app-settings__title">
231+
{{ name }}
232+
</div>
228233
<ul
229234
v-if="!isCollapsed"
230235
class="navigation-list">
@@ -258,68 +263,207 @@ function unregisterSection(id: string) {
258263
</template>
259264

260265
<style lang="scss" scoped>
261-
.app-settings {
266+
$navigation-width: 200px;
267+
$content-inset: calc(3 * var(--default-grid-baseline));
268+
269+
.app-settings:not(.app-settings--legacy) {
270+
--nav-tint: hsl(from var(--color-primary-element-light) h s calc(l * 1.045));
271+
--nav-tint-strong: var(--color-primary-element-light);
272+
273+
:deep(.modal-wrapper .modal-container) {
274+
padding-inline-start: 0 !important;
275+
padding-block-start: 0 !important;
276+
background-color: var(--nav-tint);
277+
overflow: hidden;
278+
max-width: 900px;
279+
}
280+
281+
// Title is rendered inside the navigation slot; hide the native h2 but
282+
// keep it in the a11y tree so the modal still has its accessible name.
283+
:deep(.dialog__name) {
284+
position: absolute;
285+
width: 1px;
286+
height: 1px;
287+
margin: -1px;
288+
padding: 0;
289+
overflow: hidden;
290+
clip-path: inset(100%);
291+
white-space: nowrap;
292+
border: 0;
293+
}
294+
262295
:deep(.app-settings__navigation) {
263-
min-width: 200px;
264-
margin-inline-end: calc(4 * var(--default-grid-baseline));
296+
min-width: $navigation-width;
297+
max-width: $navigation-width;
298+
flex: 0 0 $navigation-width;
299+
// Beat NcDialog's default 20px end-margin so the tint meets the content.
300+
margin-inline-end: 0 !important;
265301
overflow-x: hidden;
266302
overflow-y: auto;
267303
position: relative;
268304
}
269305
270306
:deep(.app-settings__content) {
271-
padding-inline: calc(4 * var(--default-grid-baseline));
307+
padding: $content-inset;
308+
background-color: var(--color-main-background);
309+
border-inline-start: 1px solid var(--color-border-dark);
310+
border-start-start-radius: var(--border-radius-element);
311+
border-end-start-radius: var(--border-radius-element);
272312
}
273-
}
274313
275-
.navigation-list {
276-
height: 100%;
277-
overflow-y: auto;
278-
padding: calc(3 * var(--default-grid-baseline));
279-
280-
&__link {
281-
display: flex;
282-
align-content: center;
283-
font-size: 16px;
284-
height: var(--default-clickable-area);
285-
margin: 4px 0;
286-
line-height: var(--default-clickable-area);
287-
border-radius: var(--border-radius-element);
288-
font-weight: bold;
289-
padding: 0 calc(4 * var(--default-grid-baseline));
290-
cursor: pointer;
291-
white-space: nowrap;
292-
text-overflow: ellipsis;
293-
overflow: hidden;
294-
background-color: transparent;
295-
border: none;
314+
.app-settings__title {
315+
box-sizing: border-box;
316+
padding: $content-inset;
317+
margin: 0;
318+
font-size: 20px;
319+
font-weight: 700;
320+
}
296321
297-
&:hover,
298-
&:focus {
299-
background-color: var(--color-background-hover);
300-
}
322+
.navigation-list {
323+
height: 100%;
324+
overflow-y: auto;
325+
padding: var(--default-grid-baseline);
326+
327+
&__link {
328+
position: relative;
329+
display: flex;
330+
align-items: center;
331+
font-size: var(--default-font-size);
332+
font-weight: 500;
333+
height: var(--default-clickable-area);
334+
margin: 2px 0;
335+
line-height: var(--default-clickable-area);
336+
border-radius: var(--border-radius-element);
337+
padding-inline: calc(2 * var(--default-grid-baseline));
338+
cursor: pointer;
339+
white-space: nowrap;
340+
text-overflow: ellipsis;
341+
overflow: hidden;
342+
background-color: transparent;
343+
border: none;
344+
color: var(--color-main-text);
345+
346+
&:hover,
347+
&:focus {
348+
background-color: var(--nav-tint-strong);
349+
}
301350
302-
&--active {
303-
background-color: var(--color-primary-element-light) !important;
351+
&--active {
352+
background-color: var(--nav-tint-strong);
353+
354+
&::before {
355+
content: '';
356+
position: absolute;
357+
inset-block: var(--default-grid-baseline);
358+
inset-inline-start: 0;
359+
width: 3px;
360+
background-color: var(--color-primary-element);
361+
border-radius: 999px;
362+
}
363+
}
364+
365+
&--icon {
366+
gap: var(--default-grid-baseline);
367+
}
368+
369+
&-icon {
370+
display: flex;
371+
justify-content: center;
372+
align-content: center;
373+
width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
374+
max-width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
375+
}
304376
}
377+
}
378+
379+
}
305380
306-
&--icon {
307-
padding-inline-start: calc(2 * var(--default-grid-baseline));
308-
gap: var(--default-grid-baseline);
381+
@media only screen and (max-width: $breakpoint-mobile) {
382+
.app-settings:not(.app-settings--legacy) {
383+
:deep(.modal-wrapper .modal-container) {
384+
padding-inline-start: 12px !important;
385+
padding-block-start: 4px !important;
386+
background-color: var(--color-main-background);
387+
}
388+
:deep(.dialog__name) {
389+
position: static;
390+
width: auto;
391+
height: auto;
392+
margin: 0 0 12px 0;
393+
padding-inline-end: var(--default-clickable-area);
394+
overflow: visible;
395+
clip-path: none;
396+
white-space: normal;
397+
border: 0;
398+
}
399+
:deep(.app-settings__content) {
400+
border: none;
401+
border-radius: 0;
309402
}
403+
}
404+
}
405+
406+
// Legacy design (NC < 34): keep the original centered-title layout.
407+
.app-settings.app-settings--legacy {
408+
:deep(.app-settings__navigation) {
409+
min-width: 200px;
410+
margin-inline-end: calc(4 * var(--default-grid-baseline));
411+
overflow-x: hidden;
412+
overflow-y: auto;
413+
position: relative;
414+
}
310415
311-
&-icon {
416+
:deep(.app-settings__content) {
417+
padding-inline: calc(4 * var(--default-grid-baseline));
418+
}
419+
420+
.navigation-list {
421+
height: 100%;
422+
overflow-y: auto;
423+
padding: calc(3 * var(--default-grid-baseline));
424+
425+
&__link {
312426
display: flex;
313-
justify-content: center;
314427
align-content: center;
315-
width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
316-
max-width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
428+
font-size: 16px;
429+
height: var(--default-clickable-area);
430+
margin: 4px 0;
431+
line-height: var(--default-clickable-area);
432+
border-radius: var(--border-radius-element);
433+
font-weight: bold;
434+
padding: 0 calc(4 * var(--default-grid-baseline));
435+
cursor: pointer;
436+
white-space: nowrap;
437+
text-overflow: ellipsis;
438+
overflow: hidden;
439+
background-color: transparent;
440+
border: none;
441+
442+
&:hover,
443+
&:focus {
444+
background-color: var(--color-background-hover);
445+
}
446+
447+
&--active {
448+
background-color: var(--color-primary-element-light) !important;
449+
}
450+
451+
&--icon {
452+
padding-inline-start: calc(2 * var(--default-grid-baseline));
453+
gap: var(--default-grid-baseline);
454+
}
455+
456+
&-icon {
457+
display: flex;
458+
justify-content: center;
459+
align-content: center;
460+
width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
461+
max-width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
462+
}
317463
}
318464
}
319-
}
320465
321-
@media only screen and (max-width: $breakpoint-small-mobile) {
322-
.app-settings {
466+
@media only screen and (max-width: $breakpoint-small-mobile) {
323467
:deep(.dialog__name) {
324468
padding-inline-start: 16px;
325469
}

src/utils/legacy.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44
*/
55

66
const [majorVersion] = window.OC?.config?.version?.split('.') ?? []
7-
export const isLegacy = Number.parseInt(majorVersion ?? '32') < 32
7+
const major = Number.parseInt(majorVersion ?? '32')
8+
export const isLegacy = major < 32
9+
export const isLegacy34 = major < 34

0 commit comments

Comments
 (0)