Implement Fluid Emerald app redesign
linter / quality (pull_request) Successful in 1m18s
tests / ci (8.4) (pull_request) Successful in 1m54s

This commit is contained in:
2026-07-18 16:45:54 +02:00
parent 59817ad30f
commit a46695c2eb
62 changed files with 2165 additions and 1434 deletions
+141 -5
View File
@@ -1,11 +1,18 @@
<script setup lang="ts">
import { Link, usePage } from '@inertiajs/vue3';
import {
ArrowLeft,
BellRing,
BookOpen,
CirclePlus,
Folder,
FolderGit2,
KanbanSquare,
LayoutGrid,
Layers3,
ListTodo,
SlidersHorizontal,
Tags,
Shield,
Users,
} from 'lucide-vue-next';
@@ -26,12 +33,88 @@ import {
import { dashboard } from '@/routes';
import { index as adminUsers } from '@/routes/admin/users';
import { index as projectTemplatesIndex } from '@/routes/project-templates';
import { index as projectsIndex } from '@/routes/projects';
import {
create as projectsCreate,
index as projectsIndex,
show as projectShow,
} from '@/routes/projects';
import { index as projectBacklog } from '@/routes/projects/backlog';
import { index as projectBoard } from '@/routes/projects/board';
import {
board as projectSettingsBoard,
general as projectSettingsGeneral,
metadata as projectSettingsMetadata,
notifications as projectSettingsNotifications,
repositories as projectSettingsRepositories,
} from '@/routes/projects/settings';
import { index as teamsIndex } from '@/routes/teams';
import type { NavItem } from '@/types';
import type { AppSidebarProps, NavItem } from '@/types';
const props = defineProps<AppSidebarProps>();
const page = usePage();
const isProjectSettings = computed(() => page.url.includes('/settings/'));
const projectNavItems = computed<NavItem[]>(() => {
if (!props.project) {
return [];
}
return [
{
title: 'Overview',
href: projectShow(props.project.id),
icon: LayoutGrid,
isActive: page.url === projectShow.url(props.project.id),
},
{
title: 'Board',
href: projectBoard(props.project.id),
icon: KanbanSquare,
},
{
title: 'Backlog',
href: projectBacklog(props.project.id),
icon: ListTodo,
},
];
});
const projectSettingsNavItems = computed<NavItem[]>(() => {
if (!props.project || !isProjectSettings.value) {
return [];
}
return [
{
title: 'General',
href: projectSettingsGeneral(props.project.id),
icon: SlidersHorizontal,
},
{
title: 'Board',
href: projectSettingsBoard(props.project.id),
icon: KanbanSquare,
},
{
title: 'Metadata',
href: projectSettingsMetadata(props.project.id),
icon: Tags,
},
{
title: 'Repositories',
href: projectSettingsRepositories(props.project.id),
icon: FolderGit2,
},
{
title: 'Notifications',
href: projectSettingsNotifications(props.project.id),
icon: BellRing,
},
];
});
const mainNavItems = computed<NavItem[]>(() => {
const items: NavItem[] = [
{
@@ -88,12 +171,12 @@ const footerNavItems: NavItem[] = [
</script>
<template>
<Sidebar collapsible="icon" variant="inset">
<Sidebar collapsible="icon" variant="sidebar" class="border-sidebar-border">
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" as-child>
<Link :href="dashboard()">
<Link :href="project ? projectsIndex() : dashboard()">
<AppLogo />
</Link>
</SidebarMenuButton>
@@ -102,7 +185,60 @@ const footerNavItems: NavItem[] = [
</SidebarHeader>
<SidebarContent>
<NavMain :items="mainNavItems" />
<template v-if="project">
<div
class="border-sidebar-border bg-sidebar-accent/60 mx-3 mb-3 rounded-lg border p-3 group-data-[collapsible=icon]:hidden"
>
<div
class="text-sidebar-foreground/55 text-[0.65rem] font-bold uppercase tracking-[0.12em]"
>
{{ project.key }}
</div>
<div class="mt-1 truncate text-sm font-semibold">
{{ project.name }}
</div>
</div>
<NavMain :items="projectNavItems" label="Project" />
<NavMain
v-if="projectSettingsNavItems.length > 0"
:items="projectSettingsNavItems"
label="Project settings"
/>
<div class="mt-auto px-3 pb-3">
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton as-child tooltip="All projects">
<Link :href="projectsIndex()">
<ArrowLeft />
<span>All projects</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</div>
</template>
<template v-else>
<NavMain :items="mainNavItems" label="Workspace" />
<div
v-if="page.props.auth.permissions.projectCreate"
class="px-3 pt-3 group-data-[collapsible=icon]:px-2"
>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
as-child
tooltip="New project"
class="bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground"
>
<Link :href="projectsCreate()">
<CirclePlus />
<span>New project</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</div>
</template>
</SidebarContent>
<SidebarFooter>