Skip to content

Commit 9853a91

Browse files
committed
feat(sidebar-tabs): Redesign active tab as rounded filled pill
The active sidebar tab now renders as a fully-rounded filled pill with an inset, rounded blue indicator that grows into place when selected, replacing the previous full-width bottom border treatment on Nextcloud 34+. Older Nextcloud versions keep the legacy border styling. Backport of #8447 to stable8. Signed-off-by: nfebe <fenn25.fn@gmail.com>
1 parent a3a1c1d commit 9853a91

2 files changed

Lines changed: 95 additions & 17 deletions

File tree

src/components/NcAppSidebar/NcAppSidebarTabs.vue

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
v-if="hasMultipleTabs || showForSingleTab"
1414
role="tablist"
1515
class="app-sidebar-tabs__nav"
16+
:class="{ 'app-sidebar-tabs__nav--legacy': isLegacy34 }"
1617
@keydown.left.exact.prevent.stop="focusPreviousTab"
1718
@keydown.right.exact.prevent.stop="focusNextTab"
1819
@keydown.tab.exact.prevent.stop="focusActiveTabContent"
@@ -59,6 +60,7 @@
5960
<script>
6061
import NcCheckboxRadioSwitch from '../NcCheckboxRadioSwitch/index.js'
6162
import NcVNodes from '../NcVNodes/index.js'
63+
import { isLegacy34 } from '../../utils/legacy.ts'
6264
6365
export default {
6466
name: 'NcAppSidebarTabs',
@@ -109,6 +111,7 @@ export default {
109111
* Local active (open) tab's ID. It allows to use component without active.sync
110112
*/
111113
activeTab: '',
114+
isLegacy34,
112115
}
113116
},
114117
@@ -269,23 +272,96 @@ export default {
269272
margin: 10px 8px 0 8px;
270273
border-bottom: 1px solid var(--color-border);
271274
272-
// Override checkbox-radio-switch styles so that it looks like tabs
273-
& :deep(.checkbox-radio-switch--button-variant) {
274-
border: unset !important;
275-
border-radius: 0 !important;
276-
.checkbox-content {
277-
padding: var(--default-grid-baseline);
278-
border-radius: var(--default-grid-baseline) var(--default-grid-baseline) 0 0 !important;
279-
margin: 0 !important;
280-
border-bottom: var(--default-grid-baseline) solid transparent !important;
281-
.checkbox-content__icon > * {
282-
color: var(--color-main-text) !important;
275+
// New design (NC34+): rounded pill tabs with a small primary indicator
276+
// under the active tab.
277+
&:not(&--legacy) {
278+
gap: var(--default-grid-baseline);
279+
padding-block-end: var(--default-grid-baseline);
280+
281+
& :deep(.checkbox-radio-switch--button-variant) {
282+
position: relative;
283+
border: unset !important;
284+
border-radius: var(--border-radius-element) !important;
285+
background-color: var(--color-main-background);
286+
min-width: var(--default-clickable-area);
287+
transition: background-color var(--animation-quick);
288+
289+
.checkbox-content {
290+
padding: var(--default-grid-baseline);
291+
padding-block-end: calc(var(--default-grid-baseline) * 2);
292+
border-radius: var(--border-radius-element) !important;
293+
margin: 0 !important;
294+
.checkbox-content__icon > * {
295+
color: var(--color-main-text) !important;
296+
}
297+
}
298+
299+
.checkbox-content__text {
300+
font-weight: var(--font-weight-element, normal);
301+
}
302+
303+
&::after {
304+
content: '';
305+
position: absolute;
306+
bottom: 0;
307+
left: 50%;
308+
width: 0;
309+
height: 6px;
310+
border-radius: 999px;
311+
background-color: var(--color-primary-element);
312+
opacity: 0;
313+
transform: translateX(-50%);
314+
transition: width var(--animation-quick), opacity var(--animation-quick);
315+
}
316+
317+
&:hover {
318+
background-color: var(--color-background-hover);
319+
}
320+
321+
&:focus-visible {
322+
outline: 2px solid var(--color-main-text);
323+
outline-offset: 2px;
324+
}
325+
326+
&.checkbox-radio-switch--checked {
327+
background-color: var(--color-background-hover) !important;
328+
.checkbox-radio-switch__content {
329+
background: transparent !important;
330+
color: var(--color-main-text) !important;
331+
}
332+
&::after {
333+
width: 80%;
334+
opacity: 1;
335+
}
336+
&:hover {
337+
background-color: var(--color-background-dark) !important;
338+
}
283339
}
284340
}
285-
&.checkbox-radio-switch--checked .checkbox-radio-switch__content{
286-
background: transparent !important;
287-
color: var(--color-main-text) !important;
288-
border-bottom: var(--default-grid-baseline) solid var(--color-primary-element) !important;
341+
}
342+
343+
// Legacy design (NC < 34): full-width primary border under the active tab.
344+
&--legacy {
345+
& :deep(.checkbox-radio-switch--button-variant) {
346+
border: unset !important;
347+
border-radius: 0 !important;
348+
.checkbox-content {
349+
padding: var(--default-grid-baseline);
350+
border-radius: var(--default-grid-baseline) var(--default-grid-baseline) 0 0 !important;
351+
margin: 0 !important;
352+
border-bottom: var(--default-grid-baseline) solid transparent !important;
353+
.checkbox-content__icon > * {
354+
color: var(--color-main-text) !important;
355+
}
356+
}
357+
&.checkbox-radio-switch--checked .checkbox-radio-switch__content{
358+
background: transparent !important;
359+
color: var(--color-main-text) !important;
360+
border-bottom: var(--default-grid-baseline) solid var(--color-primary-element) !important;
361+
}
362+
&.checkbox-radio-switch--checked .checkbox-content__text {
363+
font-weight: var(--font-weight-element, bold);
364+
}
289365
}
290366
}
291367
}

src/utils/legacy.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
const version = window.OC?.config?.version?.split('.')[0] || '32'
7-
export const isLegacy32 = Number.parseInt(version) < 32
6+
const version = window.OC?.config?.version?.split('.')[0] || '34'
7+
const major = Number.parseInt(version)
8+
export const isLegacy32 = major < 32
9+
export const isLegacy34 = major < 34

0 commit comments

Comments
 (0)