create a draft navigation

This commit is contained in:
2025-03-06 16:57:25 +01:00
parent ea5ec721d9
commit ad8fa067f4
9 changed files with 191 additions and 5 deletions
+1
View File
@@ -4,6 +4,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="app\" /> <Folder Include="app\" />
<Folder Include="src\utils\" />
<Folder Include="src\views\" /> <Folder Include="src\views\" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+38 -2
View File
@@ -1,11 +1,47 @@
<template> <template>
<aside class="sidebar"> <aside class="menu">
<img class="logo" src="/just.svg" :alt="$t('app.name')" /> <img class="logo" src="/just.svg" :alt="$t('app.name')" />
<nav class="navigation">
<navigation-item name="Shopping" symbol="ListTodo" :active="true" :count="7" />
<navigation-item name="Work" symbol="ListTodo" :count="702" />
<navigation-item name="Apartment" symbol="ListTodo" />
<navigation-item name="Add a list" symbol="ListPlus" :minor="true" />
</nav>
<div class="menu-bottom">
<navigation-item name="Settings" symbol="Bolt" :minor="true" />
</div>
</aside> </aside>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import NavigationItem from '@/components/navigation-item.vue';
import { posts } from '@/db'; import { posts } from '@/db';
let items = posts.find().fetch(); let items = posts.find().fetch();
console.info(items); console.info(items);
</script> </script>
<style lang="scss" scoped>
.menu
{
width: 260px;
margin: 10px;
border-radius: 8px;
background: var(--color-menu-bg);
height: calc(100vh - 20px);
overflow-y: auto;
padding: 16px;
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
}
.logo
{
width: 30px;
}
.navigation
{
margin-top: 12px;
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import { type App } from 'vue';
import uiIcon from './ui-icon.vue';
export function createComponents (app: App)
{
app.component('ui-icon', uiIcon);
}
+106
View File
@@ -0,0 +1,106 @@
<template>
<button type="button" class="navigation-item" :class="classes">
<ui-icon :symbol="symbol" class="navigation-item-icon" />
<span class="navigation-item-text" v-text="name"></span>
<span class="navigation-item-count" v-if="count > 0" v-text="count"></span>
</button>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
interface Props {
symbol: string,
name: string,
count?: number,
active?: boolean,
minor?: boolean
}
const { symbol, name, count = 0, active, minor } = defineProps<Props>();
const classes = reactive({
'is-active': active,
'is-list': !minor
})
</script>
<style scoped lang="scss">
.navigation-item
{
appearance: none;
height: 38px;
border-radius: 6px;
display: grid;
grid-template-columns: auto minmax(0, auto) 1fr;
text-decoration: none;
align-items: center;
gap: 8px;
background: transparent;
padding: 0 12px;
width: 100%;
border: 1px solid transparent;
cursor: pointer;
//transition: background-color 0.2s ease;
&.is-active, &:hover
{
background: var(--color-menu-item-hover-bg);
.navigation-item-count
{
background: var(--color-menu-item-hover-count-bg);
}
}
}
.navigation:has(.navigation-item:not(.is-active):hover)
{
.navigation-item.is-active
{
background: transparent;
}
.navigation-item.is-active .navigation-item-count
{
background: var(--color-menu-item-count-bg);
}
}
.navigation-item-icon
{
height: 20px;
stroke-width: 1.5px;
color: var(--color-text-dim);
margin-right: 8px;
}
.navigation-item-text
{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--color-text-dim);
.navigation-item.is-list &
{
font-weight: 500;
color: var(--color-text);
}
}
.navigation-item-count
{
height: 16px;
justify-self: start;
min-width: 16px;
padding: 0 6px;
display: inline-flex;
justify-content: center;
align-items: center;
border-radius: 8px;
font-size: 0.6em;
background: var(--color-menu-item-count-bg);
color: var(--color-text-dim);
//transition: background-color 0.2s ease;
}
</style>
+26
View File
@@ -0,0 +1,26 @@
<template>
<component
:is="icon"
:size="size"
:color="color"
:stroke-width="strokeWidth" :default-class="defaultClass"
/>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import * as icons from "lucide-vue-next";
const props = defineProps({
symbol: {
type: String,
required: true
},
size: Number,
color: String,
strokeWidth: Number,
defaultClass: String
})
const icon = computed(() => icons[props.symbol]);
</script>
+2
View File
@@ -1,6 +1,7 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import { createComponents } from '@/components'
import './styles/styles.scss' import './styles/styles.scss'
import App from './App.vue' import App from './App.vue'
@@ -8,6 +9,7 @@ import App from './App.vue'
import en_translations from './locales/en.json' import en_translations from './locales/en.json'
const app = createApp(App) const app = createApp(App)
createComponents(app)
app.use(createPinia()) app.use(createPinia())
app.use(createI18n<[typeof en_translations], 'en'>({ app.use(createI18n<[typeof en_translations], 'en'>({
locale: 'en', locale: 'en',
+1 -1
View File
@@ -11,7 +11,7 @@ body
{ {
color: var(--color-text); color: var(--color-text);
font-family: 'inter', sans-serif; font-family: 'inter', sans-serif;
font-size: 16px; font-size: 14px;
line-height: 1.5; line-height: 1.5;
background: var(--color-layout-bg); background: var(--color-layout-bg);
} }
+8
View File
@@ -18,6 +18,14 @@
--color-layout-icons-fg: var(--color-fg-shade-3); --color-layout-icons-fg: var(--color-fg-shade-3);
--color-layout-icons-hover-fg: var(--color-fg-shade-2); --color-layout-icons-hover-fg: var(--color-fg-shade-2);
// menu shades
--color-menu-bg: var(--color-bg-shade-3);
--color-menu-item-hover-bg: var(--color-bg-shade-4);
--color-menu-item-count-bg: var(--color-bg-shade-4);
--color-menu-item-hover-count-bg: var(--color-bg-shade-5);
// general text shades // general text shades
--color-text: var(--color-fg-shade-1); --color-text: var(--color-fg-shade-1);
--color-text-dim: var(--color-fg-shade-2);
--color-text-dim-one: var(--color-fg-shade-3);
} }
+2 -2
View File
@@ -7,8 +7,8 @@ import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
vue() vue(),
//vueDevTools(), //vueDevTools()
], ],
resolve: { resolve: {
alias: { alias: {