Skip to content

Commit 1974680

Browse files
committed
fix(responsive): toggle between label or icon in small screens
1 parent 295fa51 commit 1974680

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

src/components/common/navbar/NavbarComponent.vue

+46-7
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import {
44
SwipeDirection,
55
type SwipeDirections,
66
} from '@dvcol/common-utils/common/touch';
7-
import { NTab, NTabs } from 'naive-ui';
7+
import { NFlex, NIcon, NTab, NTabs } from 'naive-ui';
88
import { computed, ref, toRefs, useSlots } from 'vue';
99
import { useRoute, useRouter } from 'vue-router';
1010
1111
import NavbarSettingsDropdown from '~/components/common/navbar/NavbarSettingsDopdown.vue';
1212
13-
import { Route } from '~/models/router.model';
13+
import { getRouteIcon, Route } from '~/models/router.model';
1414
import { Logger } from '~/services/logger.service';
1515
import { NavbarService } from '~/services/navbar.service';
1616
import { useExtensionSettingsStoreRefs } from '~/stores/settings/extension.store';
@@ -47,11 +47,14 @@ const navigate = (to: Route) => {
4747
router.push({ name: to });
4848
};
4949
50-
const { enabledRoutes } = useExtensionSettingsStoreRefs();
50+
const { enabledRoutes, iconOnly } = useExtensionSettingsStoreRefs();
5151
5252
const isCompact = watchMedia('(max-width: 500px)');
5353
const isTiny = watchMedia('(max-width: 400px)');
54-
const threshold = computed(() => (isTiny.value ? 3 : 4));
54+
const threshold = computed(() => {
55+
if (iconOnly.value) return 6;
56+
return isTiny.value ? 3 : 4;
57+
});
5558
const visibleRoutes = computed(() =>
5659
isCompact.value ? enabledRoutes.value.slice(0, threshold.value) : enabledRoutes.value,
5760
);
@@ -213,9 +216,16 @@ const onTouchEnd = (e: TouchEvent) => {
213216
type="segment"
214217
@click="navigate(_route)"
215218
>
216-
<span>
217-
{{ i18n(_route.toLowerCase()) }}
218-
</span>
219+
<NFlex
220+
align="center"
221+
class="tab-label"
222+
:class="{ icon: iconOnly, overflow: enabledRoutes.length > 4 }"
223+
>
224+
<NIcon :component="getRouteIcon(_route)" size="1em" />
225+
<span class="text">
226+
{{ i18n(_route.toLowerCase()) }}
227+
</span>
228+
</NFlex>
219229
</NTab>
220230
</template>
221231
<NTab
@@ -294,6 +304,35 @@ nav {
294304
justify-content: center;
295305
min-height: layout.$header-navbar-height;
296306
307+
.tab-label {
308+
i {
309+
margin-top: 0.1rem;
310+
margin-right: -0.25rem;
311+
}
312+
313+
&.overflow {
314+
@media (width < 700px) {
315+
&:not(.icon) i {
316+
display: none;
317+
}
318+
319+
&.icon .text {
320+
display: none;
321+
}
322+
}
323+
}
324+
325+
@media (width < 550px) {
326+
&:not(.icon) i {
327+
display: none;
328+
}
329+
330+
&.icon .text {
331+
display: none;
332+
}
333+
}
334+
}
335+
297336
:deep(.n-tabs-capsule) {
298337
height: calc(#{layout.$header-navbar-height} - 0.75rem) !important;
299338
border-radius: 0.5rem !important;

src/components/views/settings/SettingsTabs.vue

+9
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const {
5353
backgroundColor,
5454
loadingHysteresis,
5555
navbarPosition,
56+
iconOnly,
5657
} = useExtensionSettingsStoreRefs();
5758
5859
const { getIcon, fetchLists } = useListsStore();
@@ -222,6 +223,14 @@ const onColor = () => {
222223
</div>
223224
</SettingsFormItem>
224225

226+
<!-- Icon Only -->
227+
<SettingsFormItem :label="i18n('label_icon_only')">
228+
<NSwitch v-model:value="iconOnly" class="form-switch">
229+
<template #checked>{{ i18n('on', 'common', 'button') }}</template>
230+
<template #unchecked>{{ i18n('off', 'common', 'button') }}</template>
231+
</NSwitch>
232+
</SettingsFormItem>
233+
225234
<!-- Restore tab -->
226235
<SettingsFormItem :label="i18n('label_restore_tab')">
227236
<NSwitch v-model:value="restoreRoute" class="form-switch">

src/i18n/en/settings/settings-tabs.json

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
"message": "Navbar Position",
1616
"description": "Label for the 'Navbar Position' setting"
1717
},
18+
"settings__tabs__label_icon_only": {
19+
"message": "Display icon tabs for small screens",
20+
"description": "Label for the 'Display icon tabs in small screens' setting"
21+
},
1822
"settings__tabs__label_restore_tab": {
1923
"message": "Restore active tab on startup",
2024
"description": "Label for the 'Restore active tab on startup' setting"

src/stores/settings/extension.store.ts

+11
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type ExtensionSettings = {
5252
backgroundColor: string;
5353
loadingHysteresis: number;
5454
navbarPosition: NavbarPositions;
55+
iconOnly: boolean;
5556
};
5657

5758
const ExtensionSettingsConstants = {
@@ -73,6 +74,7 @@ export const useExtensionSettingsStore = defineStore(ExtensionSettingsConstants.
7374
const backgroundColor = ref('transparent');
7475
const loadingHysteresis = ref(-1);
7576
const navbarPosition = ref<NavbarPositions>(NavbarPosition.Auto);
77+
const iconOnly = ref(true);
7678

7779
const clearState = () => {
7880
Object.assign(cacheRetention, DefaultCacheRetention);
@@ -97,6 +99,7 @@ export const useExtensionSettingsStore = defineStore(ExtensionSettingsConstants.
9799
backgroundColor: backgroundColor.value,
98100
loadingHysteresis: loadingHysteresis.value,
99101
navbarPosition: navbarPosition.value,
102+
iconOnly: iconOnly.value,
100103
}),
101104
500,
102105
);
@@ -132,6 +135,7 @@ export const useExtensionSettingsStore = defineStore(ExtensionSettingsConstants.
132135
if (restored?.backgroundColor !== undefined) backgroundColor.value = restored.backgroundColor;
133136
if (restored?.loadingHysteresis !== undefined) loadingHysteresis.value = restored.loadingHysteresis;
134137
if (restored?.navbarPosition !== undefined) navbarPosition.value = restored.navbarPosition;
138+
if (restored?.iconOnly !== undefined) iconOnly.value = restored.iconOnly;
135139

136140
if (!chromeRuntimeId) routeDictionary[Route.Progress] = false;
137141
};
@@ -255,6 +259,13 @@ export const useExtensionSettingsStore = defineStore(ExtensionSettingsConstants.
255259
saveState().catch(err => Logger.error('Failed to save navbar position extension settings', { value, err }));
256260
},
257261
}),
262+
iconOnly: computed({
263+
get: () => iconOnly.value,
264+
set: (value: boolean) => {
265+
iconOnly.value = value;
266+
saveState().catch(err => Logger.error('Failed to save icon only extension settings', { value, err }));
267+
},
268+
}),
258269
};
259270
});
260271

0 commit comments

Comments
 (0)