Skip to content

Commit 1ab6511

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 and bold label treatment. Tabs keep a small gap between each other to eliminate the hover radius artifact, and the tab icon slot now receives the active state so consumers can render filled/outlined icon variants. Signed-off-by: nfebe <fenn25.fn@gmail.com>
1 parent ea71fe9 commit 1ab6511

3 files changed

Lines changed: 33 additions & 22 deletions

File tree

src/components/NcAppSidebar/NcAppSidebarTabs.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ export default {
253253
&__nav {
254254
display: flex;
255255
justify-content: stretch;
256+
gap: var(--default-grid-baseline);
256257
margin: 10px 8px 0 8px;
257258
border-bottom: 1px solid var(--color-border);
258259
}

src/components/NcAppSidebar/NcAppSidebarTabsButton.vue

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defineProps<{
2929
:tabindex="selected ? 0 : -1"
3030
@click="selected = true">
3131
<span :class="$style.sidebarTabsButton__icon">
32-
<NcVNodes :vnodes="tab.renderIcon()">
32+
<NcVNodes :vnodes="tab.renderIcon(selected)">
3333
<span :class="[$style.sidebarTabsButton__legacyIcon, tab.icon]" />
3434
</NcVNodes>
3535
</span>
@@ -41,29 +41,41 @@ defineProps<{
4141

4242
<style module lang="scss">
4343
.sidebarTabsButton {
44+
position: relative;
4445
border: none;
45-
border-bottom: var(--default-grid-baseline) solid transparent !important;
46-
border-radius: var(--border-radius-small);
47-
background-color: var(--color-main-background);
46+
border-radius: var(--border-radius-element);
47+
background-color: transparent;
4848
color: var(--color-main-text);
4949
font-size: var(--default-font-size);
5050
cursor: pointer;
5151
display: flex;
5252
flex-direction: column;
5353
gap: var(--default-grid-baseline);
5454
padding: var(--border-radius-small);
55-
transition:
56-
background-color var(--animation-quick),
57-
border-bottom-color var(--animation-quick);
55+
padding-block-end: calc(var(--border-radius-small) + var(--default-grid-baseline));
56+
transition: background-color var(--animation-quick);
5857
min-width: var(--default-clickable-area);
5958
59+
&::after {
60+
content: '';
61+
position: absolute;
62+
bottom: 2px;
63+
left: 50%;
64+
width: 0;
65+
height: 4px;
66+
border-radius: 999px;
67+
background-color: var(--color-primary-element);
68+
transform: translateX(-50%);
69+
transition: width var(--animation-quick);
70+
}
71+
6072
&:hover {
61-
background-color: var(--color-background-hover) !important;
73+
background-color: var(--color-background-hover);
6274
}
6375
64-
&:active,
65-
&:focus {
66-
background-color: var(--color-main-background) !important;
76+
&:focus-visible {
77+
outline: 2px solid var(--color-main-text);
78+
outline-offset: 2px;
6779
}
6880
6981
* {
@@ -72,14 +84,15 @@ defineProps<{
7284
}
7385
7486
.sidebarTabsButton_selected {
75-
border-bottom-color: var(--color-primary-element) !important;
76-
border-bottom-left-radius: 0px;
77-
border-bottom-right-radius: 0px;
87+
background-color: var(--color-background-hover);
7888
cursor: default;
7989
90+
&::after {
91+
width: 80%;
92+
}
93+
8094
&:hover {
81-
background-color: var(--color-primary-element-light-hover) !important;
82-
color: var(--color-primary-element-light-text) !important;
95+
background-color: var(--color-background-dark);
8396
}
8497
8598
* {
@@ -94,10 +107,6 @@ defineProps<{
94107
text-wrap: nowrap;
95108
}
96109
97-
.sidebarTabsButton_selected .sidebarTabsButton__name {
98-
font-weight: bold;
99-
}
100-
101110
.sidebarTabsButton__icon {
102111
display: inline-flex;
103112
align-items: center;

src/components/NcAppSidebarTab/NcAppSidebarTab.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,11 @@ export default {
114114
/**
115115
* Render tab's icon slot if any
116116
*
117+
* @param {boolean} selected Whether the tab is the active one
117118
* @return {import('vue').VNode[]}
118119
*/
119-
renderIcon() {
120-
return this.$slots.icon?.()
120+
renderIcon(selected = false) {
121+
return this.$slots.icon?.({ selected })
121122
},
122123
},
123124
}

0 commit comments

Comments
 (0)