From a46695c2eb0d4ef1740b42ef38cb2f93edb1de56 Mon Sep 17 00:00:00 2001 From: Twyco Date: Sat, 18 Jul 2026 16:45:54 +0200 Subject: [PATCH] Implement Fluid Emerald app redesign --- .../Projects/BuildProjectBoardPayload.php | 1 + resources/css/app.css | 166 ++-- resources/js/app.ts | 2 +- resources/js/components/AppContent.vue | 9 +- resources/js/components/AppHeader.vue | 40 +- resources/js/components/AppShell.vue | 8 +- resources/js/components/AppSidebar.vue | 146 +++- resources/js/components/AppSidebarHeader.vue | 21 +- resources/js/components/AppearanceTabs.vue | 8 +- resources/js/components/Heading.vue | 19 +- resources/js/components/NavFooter.vue | 2 +- resources/js/components/NavMain.vue | 16 +- resources/js/components/UserInfo.vue | 20 +- resources/js/components/ui/alert/index.ts | 39 +- .../js/components/ui/avatar/UserAvatar.vue | 34 +- resources/js/components/ui/badge/index.ts | 44 +- resources/js/components/ui/button/index.ts | 67 +- resources/js/components/ui/card/Card.vue | 30 +- .../js/components/ui/dialog/DialogContent.vue | 91 ++- .../js/components/ui/dialog/DialogOverlay.vue | 35 +- .../ui/dropdown-menu/DropdownMenuContent.vue | 64 +- resources/js/components/ui/input/Input.vue | 46 +- .../js/components/ui/select/SelectContent.vue | 87 +- .../js/components/ui/select/SelectTrigger.vue | 57 +- .../js/components/ui/sheet/SheetContent.vue | 95 +-- .../js/components/ui/sheet/SheetOverlay.vue | 35 +- resources/js/components/ui/sidebar/index.ts | 105 +-- resources/js/components/ui/sidebar/utils.ts | 21 +- resources/js/layouts/AppLayout.vue | 12 +- resources/js/layouts/AuthLayout.vue | 8 +- resources/js/layouts/app/AppSidebarLayout.vue | 12 +- resources/js/layouts/auth/AuthCardLayout.vue | 56 +- resources/js/layouts/settings/Layout.vue | 35 +- resources/js/pages/Dashboard.vue | 163 +++- resources/js/pages/Welcome.vue | 750 ++++++++---------- resources/js/pages/admin/users/Create.vue | 30 +- resources/js/pages/admin/users/Edit.vue | 2 +- resources/js/pages/admin/users/Index.vue | 7 +- .../js/pages/project-templates/Create.vue | 56 +- resources/js/pages/project-templates/Edit.vue | 88 +- .../js/pages/project-templates/Index.vue | 53 +- resources/js/pages/projects/Access.vue | 9 +- resources/js/pages/projects/Backlog.vue | 27 +- resources/js/pages/projects/Board.vue | 125 ++- resources/js/pages/projects/Create.vue | 125 ++- resources/js/pages/projects/Index.vue | 22 +- resources/js/pages/projects/Show.vue | 126 +-- resources/js/pages/projects/Ticket.vue | 80 +- resources/js/pages/projects/TicketCreate.vue | 104 ++- .../js/pages/projects/settings/Board.vue | 13 +- .../js/pages/projects/settings/General.vue | 157 +++- .../js/pages/projects/settings/Metadata.vue | 16 +- .../pages/projects/settings/Notifications.vue | 97 ++- .../pages/projects/settings/Repositories.vue | 28 +- resources/js/pages/settings/Applications.vue | 5 +- .../js/pages/settings/GitConnections.vue | 10 +- resources/js/pages/teams/Index.vue | 7 +- resources/js/types/index.ts | 1 + resources/js/types/layout.ts | 41 + resources/js/types/ui.ts | 12 + resources/views/app.blade.php | 6 +- .../Projects/ProjectBoardControllerTest.php | 8 + 62 files changed, 2165 insertions(+), 1434 deletions(-) create mode 100644 resources/js/types/layout.ts diff --git a/app/Actions/Projects/BuildProjectBoardPayload.php b/app/Actions/Projects/BuildProjectBoardPayload.php index 1afb503..4c08b65 100644 --- a/app/Actions/Projects/BuildProjectBoardPayload.php +++ b/app/Actions/Projects/BuildProjectBoardPayload.php @@ -29,6 +29,7 @@ class BuildProjectBoardPayload 'ticketStatuses', 'tickets' => fn ($query) => $query ->with([ + 'assignee', 'ticketPriority', 'ticketStatus.allowedTargetStatuses.boardColumn', 'ticketStatus.boardColumn', diff --git a/resources/css/app.css b/resources/css/app.css index c24c18d..9543c5b 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -37,8 +37,8 @@ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --radius-sm: 0.125rem; - --radius-md: 0.375rem; + --radius-sm: 0.25rem; + --radius-md: 0.25rem; --radius-lg: 0.5rem; --radius-xl: 0.75rem; @@ -51,11 +51,11 @@ --text-headline-lg: 1.5rem; --text-headline-lg--line-height: 2rem; --text-headline-lg--font-weight: 600; - --text-headline-lg--letter-spacing: 0; + --text-headline-lg--letter-spacing: -0.025em; --text-headline-md: 1.125rem; --text-headline-md--line-height: 1.5rem; --text-headline-md--font-weight: 600; - --text-headline-md--letter-spacing: 0; + --text-headline-md--letter-spacing: -0.015em; --text-headline-lg-mobile: 1.25rem; --text-headline-lg-mobile--line-height: 1.75rem; --text-headline-lg-mobile--font-weight: 600; @@ -275,50 +275,50 @@ } .dark { - --background: #0f172a; - --foreground: #eff1f3; - --card: #111827; - --card-foreground: #eff1f3; - --popover: #111827; - --popover-foreground: #eff1f3; - --primary: #4ae176; + --background: #0b1326; + --foreground: #e5eaf5; + --card: #131b2e; + --card-foreground: #e5eaf5; + --popover: #171f33; + --popover-foreground: #e5eaf5; + --primary: #4be277; --primary-foreground: #002109; - --secondary: #1f2937; - --secondary-foreground: #eff1f3; - --muted: #1e293b; - --muted-foreground: #cbd5e1; - --accent: #1e293b; - --accent-foreground: #eff1f3; - --destructive: #f87171; - --destructive-foreground: #ffffff; - --border: #334155; - --input: #334155; - --ring: #4ae176; - --chart-1: #4ae176; + --secondary: #222a3d; + --secondary-foreground: #e5eaf5; + --muted: #171f33; + --muted-foreground: #aeb8cd; + --accent: #222a3d; + --accent-foreground: #f3f6fc; + --destructive: #ffb4ab; + --destructive-foreground: #690005; + --border: #3b4358; + --input: #4a5268; + --ring: #4be277; + --chart-1: #4be277; --chart-2: #60a5fa; --chart-3: #fbbf24; --chart-4: #f87171; --chart-5: #b7c8e1; - --surface: #0f172a; - --surface-dim: #020617; - --surface-bright: #111827; - --surface-container-lowest: #111827; - --surface-container-low: #1e293b; - --surface-container: #263445; - --surface-container-high: #334155; - --surface-container-highest: #475569; - --surface-variant: #334155; - --surface-tint: #4ae176; - --on-surface: #eff1f3; - --on-surface-variant: #cbd5e1; - --on-background: #eff1f3; - --outline: #94a3b8; - --outline-variant: #334155; - --primary-container: #14532d; + --surface: #0b1326; + --surface-dim: #060e20; + --surface-bright: #2d3449; + --surface-container-lowest: #060e20; + --surface-container-low: #131b2e; + --surface-container: #171f33; + --surface-container-high: #222a3d; + --surface-container-highest: #2d3449; + --surface-variant: #2d3449; + --surface-tint: #4be277; + --on-surface: #e5eaf5; + --on-surface-variant: #aeb8cd; + --on-background: #e5eaf5; + --outline: #8993aa; + --outline-variant: #3b4358; + --primary-container: #136c35; --on-primary: #002109; --on-primary-container: #bbf7d0; --primary-fixed: #6bff8f; - --primary-fixed-dim: #4ae176; + --primary-fixed-dim: #4be277; --on-primary-fixed: #002109; --on-primary-fixed-variant: #005321; --secondary-container: #1e3a5f; @@ -343,15 +343,15 @@ --inverse-surface: #eff1f3; --inverse-on-surface: #191c1e; --inverse-primary: #006e2f; - --sidebar-background: #111827; - --sidebar-foreground: #eff1f3; - --sidebar-primary: #4ae176; + --sidebar-background: #060e20; + --sidebar-foreground: #e5eaf5; + --sidebar-primary: #4be277; --sidebar-primary-foreground: #002109; - --sidebar-accent: #1e293b; - --sidebar-accent-foreground: #eff1f3; - --sidebar-border: #334155; - --sidebar-ring: #4ae176; - --sidebar: #111827; + --sidebar-accent: #171f33; + --sidebar-accent-foreground: #f3f6fc; + --sidebar-border: #2d3449; + --sidebar-ring: #4be277; + --sidebar: #060e20; } @layer base { @@ -359,6 +359,74 @@ @apply border-border outline-ring/50; } body { - @apply bg-background text-foreground; + @apply min-h-screen bg-background text-foreground antialiased; + letter-spacing: -0.006em; + } + + ::selection { + background: color-mix(in srgb, var(--primary) 24%, transparent); + color: var(--foreground); + } + + textarea, + select { + @apply border-input bg-surface-container-lowest text-foreground rounded-md border px-3 py-2 text-sm shadow-xs outline-none transition-[border-color,box-shadow,background-color]; + background-color: var(--surface-container-lowest) !important; + } + + textarea:focus-visible, + select:focus-visible { + @apply border-ring ring-ring/25 ring-3; + } + + textarea:disabled, + select:disabled { + @apply cursor-not-allowed opacity-55; + } + + table { + @apply w-full border-separate border-spacing-0; + } + + thead { + @apply bg-surface-container-low text-on-surface-variant; + } + + tbody tr { + @apply transition-colors hover:bg-primary/3; + } + + th { + @apply text-label-uppercase font-bold tracking-[0.08em]; + } +} + +@layer components { + .app-page { + @apply mx-auto flex w-full max-w-[96rem] flex-1 flex-col gap-6 px-4 py-5 sm:px-6 sm:py-7 lg:px-8; + } + + .app-page-narrow { + @apply mx-auto flex w-full max-w-5xl flex-1 flex-col gap-6 px-4 py-5 sm:px-6 sm:py-7 lg:px-8; + } + + .page-actions { + @apply flex flex-wrap items-center gap-2; + } + + .status-success { + @apply border-primary/25 bg-primary/8 text-on-primary-container rounded-lg border px-4 py-3 text-sm dark:text-primary-fixed; + } + + .empty-state { + @apply border-outline-variant bg-surface-container-low text-on-surface-variant rounded-lg border border-dashed px-5 py-8 text-center text-sm; + } + + .table-shell { + @apply border-outline-variant bg-surface-container-lowest overflow-hidden rounded-xl border; + } + + .eyebrow { + @apply text-label-uppercase text-primary font-bold uppercase tracking-[0.12em]; } } diff --git a/resources/js/app.ts b/resources/js/app.ts index c098682..e4a6cf4 100644 --- a/resources/js/app.ts +++ b/resources/js/app.ts @@ -20,7 +20,7 @@ createInertiaApp({ .mount(el); }, progress: { - color: '#4B5563', + color: '#22c55e', }, }); diff --git a/resources/js/components/AppContent.vue b/resources/js/components/AppContent.vue index 314002e..1598df3 100644 --- a/resources/js/components/AppContent.vue +++ b/resources/js/components/AppContent.vue @@ -1,14 +1,9 @@