Skip to content

Commit 1e0a51f

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 1e0a51f

2 files changed

Lines changed: 188 additions & 43 deletions

File tree

src/components/NcAppSettingsDialog/NcAppSettingsDialog.vue

Lines changed: 185 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,206 @@ 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+
background-color: transparent !important;
385+
overflow: visible !important;
386+
}
387+
:deep(.dialog__name) {
388+
position: static;
389+
width: auto;
390+
height: auto;
391+
margin: 0 0 12px 0;
392+
padding: 0;
393+
overflow: visible;
394+
clip-path: none;
395+
white-space: normal;
396+
border: 0;
397+
}
398+
:deep(.app-settings__content) {
399+
border: none;
400+
border-radius: 0;
309401
}
402+
}
403+
}
404+
405+
// Legacy design (NC < 34): keep the original centered-title layout.
406+
.app-settings.app-settings--legacy {
407+
:deep(.app-settings__navigation) {
408+
min-width: 200px;
409+
margin-inline-end: calc(4 * var(--default-grid-baseline));
410+
overflow-x: hidden;
411+
overflow-y: auto;
412+
position: relative;
413+
}
310414
311-
&-icon {
415+
:deep(.app-settings__content) {
416+
padding-inline: calc(4 * var(--default-grid-baseline));
417+
}
418+
419+
.navigation-list {
420+
height: 100%;
421+
overflow-y: auto;
422+
padding: calc(3 * var(--default-grid-baseline));
423+
424+
&__link {
312425
display: flex;
313-
justify-content: center;
314426
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));
427+
font-size: 16px;
428+
height: var(--default-clickable-area);
429+
margin: 4px 0;
430+
line-height: var(--default-clickable-area);
431+
border-radius: var(--border-radius-element);
432+
font-weight: bold;
433+
padding: 0 calc(4 * var(--default-grid-baseline));
434+
cursor: pointer;
435+
white-space: nowrap;
436+
text-overflow: ellipsis;
437+
overflow: hidden;
438+
background-color: transparent;
439+
border: none;
440+
441+
&:hover,
442+
&:focus {
443+
background-color: var(--color-background-hover);
444+
}
445+
446+
&--active {
447+
background-color: var(--color-primary-element-light) !important;
448+
}
449+
450+
&--icon {
451+
padding-inline-start: calc(2 * var(--default-grid-baseline));
452+
gap: var(--default-grid-baseline);
453+
}
454+
455+
&-icon {
456+
display: flex;
457+
justify-content: center;
458+
align-content: center;
459+
width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
460+
max-width: calc(var(--default-clickable-area) - 2 * var(--default-grid-baseline));
461+
}
317462
}
318463
}
319-
}
320464
321-
@media only screen and (max-width: $breakpoint-small-mobile) {
322-
.app-settings {
465+
@media only screen and (max-width: $breakpoint-small-mobile) {
323466
:deep(.dialog__name) {
324467
padding-inline-start: 16px;
325468
}

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)