|
1 | 1 | <script lang="ts" setup>
|
2 |
| -// TODO |
| 2 | +import { NAnchor, NAnchorLink, NCard, NLayout, NLayoutSider } from 'naive-ui'; |
| 3 | +
|
| 4 | +import { onDeactivated, type Ref, ref } from 'vue'; |
| 5 | +
|
| 6 | +import { useI18n } from '~/utils'; |
| 7 | +
|
| 8 | +const i18n = useI18n('settings'); |
| 9 | +
|
| 10 | +type Section = { |
| 11 | + title: string; |
| 12 | + reference: Ref<[InstanceType<typeof NCard>] | undefined>; |
| 13 | +}; |
| 14 | +
|
| 15 | +const sections: Section[] = [ |
| 16 | + { title: 'menu__account', reference: ref() }, |
| 17 | + { title: 'menu__cache', reference: ref() }, |
| 18 | + { title: 'menu__tabs', reference: ref() }, |
| 19 | + { title: 'menu__logs', reference: ref() }, |
| 20 | + { title: 'menu__links', reference: ref() }, |
| 21 | +]; |
| 22 | +
|
| 23 | +const focus = ref(false); |
| 24 | +const target = ref(); |
| 25 | +
|
| 26 | +const scrollTo = (section: Section) => { |
| 27 | + target.value = section; |
| 28 | + focus.value = true; |
| 29 | + section.reference?.value?.[0]?.$el?.scrollIntoView({ |
| 30 | + behavior: 'smooth', |
| 31 | + block: 'center', |
| 32 | + }); |
| 33 | +}; |
| 34 | +
|
| 35 | +onDeactivated(() => { |
| 36 | + target.value = undefined; |
| 37 | + focus.value = false; |
| 38 | +}); |
3 | 39 | </script>
|
4 | 40 |
|
5 | 41 | <template>
|
6 |
| - <span>This is a settings component</span> |
| 42 | + <NLayout class="container" has-sider> |
| 43 | + <NLayoutSider |
| 44 | + class="menu" |
| 45 | + bordered |
| 46 | + collapse-mode="width" |
| 47 | + width="5.125rem" |
| 48 | + :collapsed-width="0" |
| 49 | + :native-scrollbar="false" |
| 50 | + show-trigger="bar" |
| 51 | + inverted |
| 52 | + > |
| 53 | + <NAnchor :show-rail="false" type="block"> |
| 54 | + <NAnchorLink |
| 55 | + v-for="section in sections" |
| 56 | + :key="section.title" |
| 57 | + :title="i18n(section.title)" |
| 58 | + :class="{ 'n-anchor-link--active': target?.title === section.title }" |
| 59 | + @click="scrollTo(section)" |
| 60 | + /> |
| 61 | + </NAnchor> |
| 62 | + </NLayoutSider> |
| 63 | + <NLayout |
| 64 | + class="content" |
| 65 | + :native-scrollbar="false" |
| 66 | + :content-style="{ |
| 67 | + padding: '1rem 1rem', |
| 68 | + }" |
| 69 | + > |
| 70 | + <NCard |
| 71 | + v-for="section in sections" |
| 72 | + :id="section.title" |
| 73 | + :ref="section.reference" |
| 74 | + :key="section.title" |
| 75 | + class="card" |
| 76 | + :class="{ target: focus && target?.title === section.title }" |
| 77 | + :title="i18n(section.title)" |
| 78 | + @mouseenter="target = section" |
| 79 | + @mouseleave="focus = false" |
| 80 | + > |
| 81 | + card Content |
| 82 | + </NCard> |
| 83 | + </NLayout> |
| 84 | + </NLayout> |
7 | 85 | </template>
|
8 | 86 |
|
9 | 87 | <style lang="scss" scoped>
|
10 |
| -// TODO |
| 88 | +@use '~/styles/mixin' as mixin; |
| 89 | +@use '~/styles/layout' as layout; |
| 90 | +
|
| 91 | +.container { |
| 92 | + width: 100%; |
| 93 | + height: 100dvh; |
| 94 | + margin-top: -#{layout.$header-navbar-height}; |
| 95 | + background: transparent; |
| 96 | +
|
| 97 | + .card { |
| 98 | + @include mixin.hover-background($from: var(--bg-black-50), $to: var(--bg-color-80)); |
| 99 | +
|
| 100 | + min-height: 20rem; |
| 101 | +
|
| 102 | + &:not(:last-child) { |
| 103 | + margin-bottom: 1rem; |
| 104 | + } |
| 105 | +
|
| 106 | + &.target { |
| 107 | + border-color: var(--n-color-target); |
| 108 | + } |
| 109 | + } |
| 110 | +
|
| 111 | + .menu { |
| 112 | + @include mixin.hover-background; |
| 113 | +
|
| 114 | + padding: 0.5rem; |
| 115 | + } |
| 116 | +
|
| 117 | + .content { |
| 118 | + background: transparent; |
| 119 | + } |
| 120 | +
|
| 121 | + .menu, |
| 122 | + .content .card:first-child { |
| 123 | + margin-top: layout.$header-navbar-height; |
| 124 | + } |
| 125 | +} |
11 | 126 | </style>
|
0 commit comments