diff --git a/DESIGN.md b/DESIGN.md index e06ad51e1c..bb968934b5 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -37,8 +37,9 @@ change. - **One accent.** Coolify purple in both themes (`#6b16ed`, hover `#7317ff`, pressed `#5a12c7`, depth `#4a0fa3`, light text and icons `#a391ff`). Yellow is only for real warnings. The dark sidebar, including the logo cell, is - purple-black (`#120e1a`) with a faint brand wash. The dark command palette - has a light purple tint. The page canvas stays neutral. + quiet neutral near-black (`#0d0d0d`), so the content keeps the focus; only + the current item's tile is purple. The dark command palette has a + light purple tint. The page canvas stays neutral. - **Quiet text.** Sentence case. A clear text ladder: primary, dim, faint. No em dashes in UI copy. @@ -126,7 +127,7 @@ follow the theme. --ui-accent-edge: #4a0fa3; --ui-accent-fg: #ffffff; --ui-accent-light: #a391ff; - --ui-sidebar: #120e1a; + --ui-sidebar: #0d0d0d; --ui-card: #121212; --ui-success: oklch(72.27% 0.192 149.58); --ui-warning: oklch(88.13% 0.1507 91.7); @@ -143,9 +144,8 @@ Rules for the tokens: - Floating surfaces (menus, popovers, tooltips, modals) must be opaque. Use `--ui-menu-bg`, never a translucent value, or the content behind shows through. -- Keep the page canvas, cards, menus, and logs pure neutral (chroma 0). The - dark sidebar, the logo cell above it, and the dark command palette are the - tinted surfaces. +- Keep the page canvas, cards, menus, logs, and the sidebar pure neutral + (chroma 0). The dark command palette is the only tinted surface. - **Dark lightness level.** The canvas is at 14.48% and the header panel at 19.13%. To change the level, move every dark surface and border token by the same @@ -154,6 +154,25 @@ Rules for the tokens: hover fill can become darker than its menu. - Primary buttons, focus rings, and active navigation use purple in both themes. Warning yellow is not an accent. +- Do not hard-code the brand purple (`#6b16ed`, `rgb(107 22 237 / …)`, + `rgb(163 145 255 / …)`, `#8a4dff`), the dark canvas (`#0a0a0a`), or the + card color (`#121212`) in component CSS. Use the tokens: `--color-brand`, + `-hover`, `-press`, `-depth`, `-light`, `-ring`, `-foreground`, + `--color-sidebar`, `--color-app`, and `--color-card`. For a translucent tint, use + `color-mix(in srgb, var(--color-brand) 14%, transparent)`. A custom theme + (`html[data-theme="custom"]`) overrides only these tokens, so a hard-coded + value stays purple when the user picks another color. +- The custom theme derives every token from the picked color: the brand fill + and its hover, press, depth, and ring shades; `--color-brand-foreground` + (the computed `--theme-accent-foreground`, so text stays readable on a light + color such as yellow); `--color-card` (the tinted surface step); and + `--color-sidebar` (between the tinted canvas and panel). When you add a + dark-theme color token, give it a custom-theme value in the same block. +- A translucent fill on a control that sits directly on the page (not in a + card or table) shows the floating-navigation dots through it. Mix the tint + with the canvas instead: + `color-mix(in srgb, var(--color-brand) 6%, var(--color-app))`. Controls in + cards keep the translucent tint, so they blend with the card. ## P3. Scales @@ -198,13 +217,13 @@ Class names below are examples. Keep the values and structure. for the header row and `--ui-panel` for the rows. - In light mode the sidebar is the canvas color and has a 1px `--ui-chrome-border` right edge. In dark mode the sidebar column, including - the logo cell, is `#120e1a` with a faint lavender right edge - (`rgb(163 145 255 / 0.10)`). The nav has a brand-purple wash that starts at - 9% and fades out; the logo cell has a flat 9% wash, so the two read as one - surface. + the logo cell, is a flat neutral `#0d0d0d` (one step above the `#0a0a0a` + canvas) with a faint `rgb(255 255 255 / 0.06)` right edge. Do not add a + brand tint or wash to the sidebar: a colored sidebar competes with the + content for attention. - The top bar matches the canvas. It has no bottom border at rest. After the - page scrolls under it, dark mode draws a lavender hairline - (`rgb(163 145 255 / 0.12)`), a translucent bar, blur, and a soft shadow. + page scrolls under it, dark mode draws a neutral hairline + (`rgb(255 255 255 / 0.06)`), a translucent bar, blur, and a soft shadow. The logo cell stays the solid sidebar color. - Keep the chrome borders faint. A strong border on near-black looks like a line drawn on the page. @@ -259,9 +278,9 @@ Class names below are examples. Keep the values and structure. transition: transform 80ms, box-shadow 80ms, border-color 120ms, background-color 120ms; } .dark .nav-tile { - border-color: rgb(163 145 255 / 0.13); - background: rgb(107 22 237 / 0.07); - color: #b9adff; + border-color: rgb(255 255 255 / 0.07); + background: rgb(255 255 255 / 0.03); + color: oklch(72% 0 0); } .nav-item:hover .nav-tile { transform: translateY(-1px); box-shadow: 0 3px 0 var(--ui-depth-color); } .nav-item:active .nav-tile { transform: translateY(2px); box-shadow: none; } @@ -279,18 +298,15 @@ Class names below are examples. Keep the values and structure. - Rows with a submenu end in a 12px chevron. In dark mode the chevron is hidden until the row is hovered, focused, or current. - Group rows under section labels (11px in light mode; 10.5px uppercase muted - lavender in dark mode), and separate groups with a 1px divider. + gray in dark mode), and separate groups with a 1px divider. - Do not put a glow (a blurred `box-shadow`) on a tile. The current row clips it, so it shows as a dim square behind the tile. - In the collapsed sidebar, Search is a tile like the other items: no row fill and no frame around it. Only the expanded sidebar shows Search as an input. - A menu that replaces another menu in place starts with a back row: a - centered label and a 12px chevron on the side of the direction. The back row - points left (`‹ Dashboard`). The row that opens the resource menu again from - the main menu points right (`adonisjs ›`) and shows the resource name. -- Keep the menu items in the same place on every page. When a page has no - resource menu, keep an empty row of the same height where the resource row - would be. + centered label and a 12px left chevron (`‹ Dashboard`). +- The main menu has no row above its items. Dashboard is the first item, right + under Search, on every page. ### Card (outer box, title row, well) @@ -655,18 +671,18 @@ lift off the content: - **Topbar chrome** uses the canvas color in dark (`#0a0a0a`) and `bg-white` in light. It has no bottom border until the page scrolls under it. Scrolling adds `is-scrolled` on `` (see `layouts/app.blade.php`) and the dark bar - becomes `rgb(10 10 10 / 0.72)` with blur and a lavender hairline. In dark + becomes `rgb(10 10 10 / 0.72)` with blur and a neutral hairline. In dark mode, top-level card wells and table rows use `--color-card` (`#121212`), not the top bar. - **Desktop sidebar and the topbar brand block** (Coolify name and version) use the canvas color in light mode. In dark mode they use `--color-sidebar` - (`#120e1a`): a vertical brand wash on the nav, a flat 9% wash on the logo - cell (the same color as the top of the nav wash), and a lavender right - edge. Section labels are 10.5px uppercase mono in - muted lavender. Chevrons are hidden until the row is hovered, focused, or - current. The Admin icon stays neutral. The footer is transparent so the - wash continues. Do not use `dark:border-white/[0.06]` on these chrome edges; - a global rule forces that utility to the solid hairline grey. + (`#0d0d0d`), flat and neutral, with a `rgb(255 255 255 / 0.06)` right edge. + Inactive icon tiles, Search, the account button in the footer, and section + labels (10.5px uppercase mono, `--color-nav-muted`) are neutral gray. Only + the current item's tile uses the brand purple, so the sidebar does not + compete with the content. Chevrons are hidden until the row is hovered, + focused, or current. Do not use `dark:border-white/[0.06]` on these chrome + edges; a global rule forces that utility to the solid hairline grey. Dark surface tokens are exact oklch equivalents of chosen sRGB steps. oklch lightness compresses toward pure black below ~15%, so check the rendered sRGB @@ -676,8 +692,9 @@ value. The dark ladder is `--color-app` 10, `--color-panel` 20, Temperature: the page canvas, cards, menus, listboxes, modals, and logs stay **pure neutral gray** (r=g=b). Do not tint those. The dark sidebar -(`--color-sidebar`, `#120e1a`) and the dark command palette are the exceptions: -they carry a faint brand-purple wash. The light page canvas uses `bg-neutral-50` (not +(`--color-sidebar`, `#0d0d0d`) is neutral too. The dark command palette is the +only exception: it carries a faint brand-purple wash. A custom theme tints all +of these surfaces with the picked color (see the token rules in P2). The light page canvas uses `bg-neutral-50` (not `bg-gray-50`, which is faintly cool) so it matches the neutral cards and chrome. The only intentional color is the purple brand accent. Yellow is for warnings. - **Layer cards** use the outer box and inset well from section 5. @@ -775,12 +792,9 @@ state because it can disappear after polling or a Livewire morph. From `xl`, the resource menu replaces the main menu in the main sidebar (`x-main-nav-menu`, `registerMainNavContext()`, `components/navbar.blade.php`). Its back row (`‹ Dashboard`, `‹ Servers`, `‹ Service`) shows the menu one depth -lower, without a page load. The main menu then starts with a row that opens the -deepest resource menu again: the resource name with a right chevron -(`adonisjs ›`). Pass the name as `name` to `registerMainNavContext()` or -``; without a name the row says "Resource menu". Pages -with no resource menu keep an invisible row of the same height, so the main -menu items do not move between pages. +lower, without a page load. The main menu has no row that opens the resource +menu again; to get back to it, open the resource again. Dashboard is always the +first item under Search. The global topbar owns the current resource identity, its compact status badges, configuration warnings (`#configuration-warning-hud-slot`), and the diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 5ea7adb125..48aa00a907 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -4626,12 +4626,11 @@ function wireNavigate(): string * Registers a resource menu that the main sidebar shows in place of its main menu on wide screens * (see components/navbar.blade.php). The menu teleports itself into #main-nav-context-{depth}. * Back on a menu shows the menu one depth lower, and Back at depth 0 shows the main menu. - * The main menu then shows a row (labelled with $name) that opens the deepest resource menu again. */ -function registerMainNavContext(int $depth, string $label, string $backTitle, ?string $name = null): void +function registerMainNavContext(int $depth, string $label, string $backTitle): void { $levels = request()->attributes->get('mainNavContext', []); - $levels[$depth] = ['label' => $label, 'backTitle' => $backTitle, 'name' => $name]; + $levels[$depth] = ['label' => $label, 'backTitle' => $backTitle]; ksort($levels); request()->attributes->set('mainNavContext', $levels); diff --git a/resources/css/app.css b/resources/css/app.css index f55b9237b1..da197cb93d 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -109,15 +109,15 @@ } .dark .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) { - --button-depth-color: rgb(107 22 237 / 0.35); - background-color: rgb(107 22 237 / 0.14); - border-color: rgb(163 145 255 / 0.24); - color: #ece8ff; + --button-depth-color: color-mix(in srgb, var(--color-brand) 35%, transparent); + background-color: color-mix(in srgb, var(--color-brand) 14%, transparent); + border-color: color-mix(in srgb, var(--color-brand-light) 24%, transparent); + color: oklch(from var(--color-brand-light) 93.5% 0.03 h); } .dark .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):hover { - background-color: rgb(107 22 237 / 0.18); - border-color: rgb(163 145 255 / 0.34); + background-color: color-mix(in srgb, var(--color-brand) 18%, transparent); + border-color: color-mix(in srgb, var(--color-brand-light) 34%, transparent); } .dark .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) svg { @@ -129,7 +129,7 @@ .dark .button[isHighlighted]:not(:disabled) { background: var(--color-brand); border-color: transparent; - color: #fff; + color: var(--color-brand-foreground); --button-depth-color: var(--color-brand-depth); } @@ -1298,6 +1298,9 @@ html:not(.dark) .application-console-shell[data-console-theme="system"] .termina 4.46, recessed 4.24, fill 3.76) to 50% so muted text clears 4.5:1 on every light surface above white. Dark stays 70.8% (already passes). */ --coollabs-subtle: oklch(50% 0 0); + /* Border of brand fills and the text on them. A custom theme overrides both. */ + --color-brand-ring: #8a4dff; + --color-brand-foreground: #fff; } .dark { @@ -1307,7 +1310,7 @@ html:not(.dark) .application-console-shell[data-console-theme="system"] .termina /* Cards sit one step above the #0a0a0a canvas. The top bar uses the canvas, not this color. The sidebar uses --color-sidebar. */ --color-card: #121212; - --color-sidebar: #120e1a; + --color-sidebar: #0d0d0d; /* Dark surface ladder in hex (sRGB), not oklch: oklch lightness compresses to near-black below ~15%, so oklch(15%) rendered as sRGB 11 and cards could not lift off the content canvas (sRGB 10). These give clear, @@ -1384,11 +1387,19 @@ html[data-theme="custom"] { --color-coollabs-300: color-mix(in oklab, var(--theme-bright-color) 72%, oklch(0% 0 0)); /* Legacy dark-theme accent utilities use warning as the brand color. */ --color-warning: var(--theme-bright-color); - /* Accent text, icons, and rings (brand-light) follow the picked color in the - readable foreground band. --color-brand stays purple here because the - brand button gradient (hover/press/depth) is not themed; brand fills and - tints are remapped per element below. */ + /* Brand fills, tints, and accent text follow the picked color. Text on a + brand fill uses the computed foreground, so light colors stay readable. */ + --color-brand: var(--theme-bright-color); + --color-brand-hover: color-mix(in oklab, var(--theme-bright-color) 88%, oklch(100% 0 0)); + --color-brand-press: color-mix(in oklab, var(--theme-bright-color) 85%, oklch(0% 0 0)); + --color-brand-depth: color-mix(in oklab, var(--theme-bright-color) 65%, oklch(0% 0 0)); + --color-brand-ring: color-mix(in oklab, var(--theme-bright-color) 75%, oklch(100% 0 0)); + --color-brand-foreground: var(--theme-accent-foreground); --color-brand-light: var(--theme-fg-on-surface); + /* Card wells, tables, and tiles (#121212 in the neutral dark theme). */ + --color-card: var(--color-surface); + /* Sidebar: one step above the canvas, like the neutral dark theme. */ + --color-sidebar: color-mix(in oklab, var(--color-app) 70%, var(--color-panel)); --color-accent-foreground: var(--theme-accent-foreground); --color-app: color-mix(in oklab, var(--theme-base-color) 12%, oklch(14.03% 0.0022 286.11)); --color-panel: color-mix(in oklab, var(--theme-base-color) 14%, oklch(15.48% 0.0021 286.15)); @@ -1537,17 +1548,6 @@ html[data-theme="custom"] :is( color: var(--theme-fg-on-surface) !important; } -/* Brand fills and tints (chips, selected rows, checked boxes, active app tabs) - take the picked color. Scoped to the elements that use them so the purple - brand buttons keep their matching hover/press/depth tokens. */ -html[data-theme="custom"] :is( - [class*=":bg-brand"], - [class*=":border-brand"], - .application-heading-actions .app-tab -) { - --color-brand: var(--theme-bright-color); -} - html.dark[data-theme="custom"] [class~="dark:bg-brand"] { color: var(--theme-accent-foreground) !important; } @@ -5832,8 +5832,8 @@ html:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-a } html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item-active, .menu-subitem-active) .menu-item-icon:not(.text-error) { - color: #fff; - border-color: #8a4dff !important; + color: var(--color-brand-foreground); + border-color: var(--color-brand-ring) !important; background: linear-gradient(180deg, var(--color-brand-hover) 0%, var(--color-brand-press) 100%) !important; --button-depth-color: var(--color-brand-depth) !important; box-shadow: 0 2px 0 var(--color-brand-depth) !important; @@ -5944,10 +5944,10 @@ html:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):not(.si box-shadow: none; } -html.dark:where(:not([data-nav-items="flat"])) :is(.app-sidebar, .mobile-sidebar-sheet) :is(.menu-item, .menu-subitem):not(.sidebar-toggle):not(.menu-search):not(.nav-admin):not(.menu-item-active):not(.menu-subitem-active) .menu-item-icon { - border-color: rgb(163 145 255 / 0.13); - background: rgb(107 22 237 / 0.07); - color: #b9adff; +html.dark:where(:not([data-nav-items="flat"])) :is(.app-sidebar, .mobile-sidebar-sheet) :is(.menu-item, .menu-subitem):not(.sidebar-toggle):not(.menu-search):not(.menu-item-active):not(.menu-subitem-active) .menu-item-icon { + border-color: rgb(255 255 255 / 0.07); + background: rgb(255 255 255 / 0.03); + color: oklch(72% 0 0); --button-depth-color: rgb(255 255 255 / 0.05); } @@ -5963,13 +5963,6 @@ html.dark:where(:not([data-nav-items="flat"])) :is(.menu-item, .menu-subitem):no color: #fff; } -/* Admin stays a neutral tile unless it is the current page. */ -html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .nav-admin:not(.menu-item-active) .menu-item-icon { - color: oklch(72% 0 0); - background: rgb(255 255 255 / 0.03); - border-color: rgb(255 255 255 / 0.07); -} - /* Search keeps its original input look while the sidebar is expanded (always on mobile, where the rail never collapses). Only the collapsed rail shows the 3D tile. The icon resets use .menu-search.menu-item to beat the html.dark tile rules. */ @@ -6257,22 +6250,20 @@ html.dark .canvas-zoom-max { } } -/* Brand shell (dark): black canvas and top bar, purple-black sidebar, scroll hairline. - Light mode keeps the neutral shell. Floating navigation keeps its own frame. */ +/* Brand shell (dark): black canvas and top bar, quiet neutral sidebar, scroll hairline. + The sidebar stays neutral so the content keeps the focus; only the current item + uses the brand purple. Light mode keeps the neutral shell. Floating navigation + keeps its own frame. */ html.dark .app-sidebar nav.sidebar-nav, html.dark .mobile-sidebar-sheet [role="dialog"] { background-color: var(--color-sidebar); - background-image: linear-gradient(180deg, rgb(107 22 237 / 0.09), transparent 520px); - border-right-color: rgb(163 145 255 / 0.10); - --color-nav-text: oklch(80% 0.02 300); - --color-nav-muted: oklch(58% 0.04 300); + border-right-color: rgb(255 255 255 / 0.06); } -/* Same color as the top of the sidebar gradient, so the brand and sidebar read as one surface. */ +/* Same color as the sidebar, so the brand and sidebar read as one surface. */ html.dark .app-topbar-brand { background-color: var(--color-sidebar); - background-image: linear-gradient(rgb(107 22 237 / 0.09), rgb(107 22 237 / 0.09)); - border-right-color: rgb(163 145 255 / 0.10); + border-right-color: rgb(255 255 255 / 0.06); } /* The drawer carries the brand surface; its nav must not paint over it. */ @@ -6285,21 +6276,24 @@ html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer { } html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search { - background-color: rgb(163 145 255 / 0.06) !important; - box-shadow: inset 0 0 0 1px rgb(163 145 255 / 0.10) !important; + box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.06) !important; } -html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search:hover { - background-color: rgb(163 145 255 / 0.10) !important; +/* The account button is a .button, which is purple in dark mode; keep it neutral in the sidebar. */ +html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) { + --button-depth-color: rgb(255 255 255 / 0.05); + background-color: rgb(255 255 255 / 0.04); + border-color: rgb(255 255 255 / 0.08); + color: var(--color-nav-text); } -html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search kbd { - border-color: rgb(163 145 255 / 0.18) !important; +html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):hover { + background-color: rgb(255 255 255 / 0.07); + border-color: rgb(255 255 255 / 0.12); } -/* Group dividers use the lavender sidebar edge: the neutral hairline looks olive on the purple-black sidebar. */ -html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-nav :is([class~="dark:border-white/[0.06]"], [class~="dark:border-white/[0.07]"], [class~="dark:border-white/[0.08]"]) { - border-color: rgb(163 145 255 / 0.10) !important; +html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) svg { + color: var(--color-nav-muted); } /* The collapsed rail shows Search as a tile like the other items: no row frame (the fill is @@ -6309,9 +6303,9 @@ html.dark .app-sidebar nav.sidebar-collapsed .menu-search { } html.dark:where(:not([data-nav-items="flat"])) .app-sidebar nav.sidebar-collapsed .menu-search.menu-item .menu-item-icon { - border-color: rgb(163 145 255 / 0.13); - background: rgb(107 22 237 / 0.07); - color: #b9adff; + border-color: rgb(255 255 255 / 0.07); + background: rgb(255 255 255 / 0.03); + color: oklch(72% 0 0); --button-depth-color: rgb(255 255 255 / 0.05); } @@ -6321,7 +6315,7 @@ html.dark :is(.app-sidebar, .mobile-sidebar-sheet) nav:not(.sidebar-collapsed) . font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; - color: rgb(163 145 255 / 0.55); + color: var(--color-nav-muted); opacity: 1; } @@ -6334,7 +6328,7 @@ html.dark .app-sidebar .menu-item:not(:hover):not(:focus-visible):not(.menu-item } html.dark:not([data-nav-style="floating"]) .app-topbar { - background-color: #0a0a0a; + background-color: var(--color-app); backdrop-filter: none; transition: background-color 180ms ease; } @@ -6345,7 +6339,7 @@ html.dark:not([data-nav-style="floating"]) .app-topbar > div:not(.app-topbar-bra } html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar { - background-color: rgb(10 10 10 / 0.72); + background-color: color-mix(in srgb, var(--color-app) 72%, transparent); backdrop-filter: blur(12px) saturate(140%); } @@ -6354,8 +6348,8 @@ html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar > .app-topbar } html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar > div:not(.app-topbar-brand) { - border-bottom-color: rgb(163 145 255 / 0.12); - box-shadow: 0 10px 30px -14px rgb(0 0 0 / 0.95), 0 1px 0 rgb(107 22 237 / 0.06); + border-bottom-color: rgb(255 255 255 / 0.06); + box-shadow: 0 10px 30px -14px rgb(0 0 0 / 0.95); } /* Canvases (default navigation): the canvas runs under a clear top bar, and the @@ -6398,12 +6392,12 @@ html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar > div:not(.ap html.dark .view-toggle { gap: 2px; padding: 2px; - background-color: rgb(107 22 237 / 0.06); - border-color: rgb(163 145 255 / 0.16); + background-color: color-mix(in srgb, var(--color-brand) 6%, transparent); + border-color: color-mix(in srgb, var(--color-brand-light) 16%, transparent); } html.dark .view-toggle > :is(a, button) { - color: oklch(80% 0.02 300); + color: oklch(from var(--color-brand-light) 80% 0.02 h); } html.dark .view-toggle > :is(a, button) svg { @@ -6411,23 +6405,23 @@ html.dark .view-toggle > :is(a, button) svg { } html.dark .view-toggle > :is(a, button):not(.is-selected):hover { - background-color: rgb(107 22 237 / 0.14); + background-color: color-mix(in srgb, var(--color-brand) 14%, transparent); color: #fff; } html.dark .view-toggle > .is-selected { background: linear-gradient(180deg, var(--color-brand-hover), var(--color-brand-press)); - color: #fff; - box-shadow: 0 1px 0 var(--color-brand-depth), inset 0 0 0 1px #8a4dff; + color: var(--color-brand-foreground); + box-shadow: 0 1px 0 var(--color-brand-depth), inset 0 0 0 1px var(--color-brand-ring); } html.dark .view-toggle > .is-selected svg { - color: #fff; + color: var(--color-brand-foreground); } html.dark .view-toggle .bg-coollabs { - background-color: rgb(163 145 255 / 0.18); - color: #d9d0ff; + background-color: color-mix(in srgb, var(--color-brand-light) 18%, transparent); + color: oklch(from var(--color-brand-light) 87.5% 0.06 h); } /* Toasts: a faint edge that blends into the toast background. */ @@ -6443,18 +6437,8 @@ html.dark .toast-card { /* Command palette: the purple brand tint of the dark shell. */ html.dark .command-palette { - background: color-mix(in oklab, #6b16ed 10%, var(--coollabs-elevated)); - box-shadow: 0 0 0 1px rgb(163 145 255 / 0.22), var(--shadow-dropdown); -} - -/* Sidebar account menu: the purple tint of the sidebar it opens from. */ -html.dark .listbox-panel.top-user-menu-panel-sidebar { - background: color-mix(in oklab, #6b16ed 10%, var(--coollabs-elevated)); - border-color: rgb(163 145 255 / 0.22); -} - -html.dark .top-user-menu-panel-sidebar .listbox-option:hover { - background: rgb(163 145 255 / 0.10); + background: color-mix(in oklab, var(--color-brand) 10%, var(--coollabs-elevated)); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-brand-light) 22%, transparent), var(--shadow-dropdown); } html.dark .command-palette-header { @@ -6466,12 +6450,12 @@ html.dark .command-palette-header-icon:not(.is-loading) { } html.dark .command-palette-input::placeholder { - color: oklch(72% 0.05 300); + color: oklch(from var(--color-brand-light) 72% 0.05 h); } html.dark .command-palette-body { - background: color-mix(in oklab, #6b16ed 6%, var(--coollabs-base)); - box-shadow: 0 0 0 1px rgb(163 145 255 / 0.12); + background: color-mix(in oklab, var(--color-brand) 6%, var(--coollabs-base)); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-brand-light) 12%, transparent); } html.dark .command-palette-item:is(:focus, :focus-visible) :is(.command-palette-quickcommand, .command-palette-type-badge, .command-palette-item-chevron, .command-palette-item-icon) { @@ -6479,8 +6463,8 @@ html.dark .command-palette-item:is(:focus, :focus-visible) :is(.command-palette- } html.dark .resource-glyph { - border-color: rgb(163 145 255 / 0.20); - background: rgb(107 22 237 / 0.10); + border-color: color-mix(in srgb, var(--color-brand-light) 20%, transparent); + background: color-mix(in srgb, var(--color-brand) 10%, transparent); color: var(--color-brand-light); } @@ -6489,7 +6473,7 @@ html.dark .card-icon-button { } html.dark .card-icon-button:hover { - background-color: rgb(107 22 237 / 0.16); + background-color: color-mix(in srgb, var(--color-brand) 16%, transparent); color: #fff; } @@ -6500,7 +6484,7 @@ html.dark .app-main :is(article.group, a.group).rounded-xl { } html.dark .app-main :is(article.group, a.group).rounded-xl:hover { - border-color: rgb(163 145 255 / 0.30) !important; + border-color: color-mix(in srgb, var(--color-brand-light) 30%, transparent) !important; box-shadow: none; } @@ -6540,7 +6524,7 @@ html.dark .project-card-stats-dot { .dark .application-settings-workspace :is(.input, select, textarea):focus, .dark .application-settings-workspace :is(.input, select, textarea):focus-visible { border-color: var(--color-brand); - box-shadow: 0 0 0 3px rgb(107 22 237 / 0.25) !important; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-brand) 25%, transparent) !important; } /* One page of results: the bar is noise. !important beats the flex utility and Alpine x-show. */ @@ -6579,8 +6563,8 @@ html.dark .project-card-stats-dot { html.dark .app-main [class*="dark:bg-white/[0.09]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 9%, var(--color-app)) !important; } html.dark .app-main [class*="dark:bg-white/[0.14]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 14%, var(--color-app)) !important; } html.dark .app-main [class*="dark:bg-white/[0.1]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } - html.dark .app-main .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: rgb(107 22 237 / 0.14) !important; border-color: rgb(163 145 255 / 0.24) !important; color: #ece8ff !important; } - html.dark .app-main .view-toggle:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: rgb(107 22 237 / 0.06) !important; border-color: rgb(163 145 255 / 0.16) !important; } + html.dark .app-main .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in srgb, var(--color-brand) 14%, var(--color-app)) !important; border-color: color-mix(in srgb, var(--color-brand-light) 24%, transparent) !important; color: oklch(from var(--color-brand-light) 93.5% 0.03 h) !important; } + html.dark .app-main .view-toggle:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { background-color: color-mix(in srgb, var(--color-brand) 6%, var(--color-app)) !important; border-color: color-mix(in srgb, var(--color-brand-light) 16%, transparent) !important; } html.dark .app-main [class*="dark:hover:bg-white/10"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.025]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 2.5%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.035]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 3.5%, var(--color-app)) !important; } @@ -6592,11 +6576,11 @@ html.dark .project-card-stats-dot { html.dark .app-main [class*="dark:hover:bg-white/[0.08]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 8%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.12]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 12%, var(--color-app)) !important; } html.dark .app-main [class*="dark:hover:bg-white/[0.1]"]:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in oklab, #fff 10%, var(--color-app)) !important; } - html.dark .app-main .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: rgb(107 22 237 / 0.18) !important; border-color: rgb(163 145 255 / 0.34) !important; } + html.dark .app-main .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *):hover { background-color: color-mix(in srgb, var(--color-brand) 18%, var(--color-app)) !important; border-color: color-mix(in srgb, var(--color-brand-light) 34%, transparent) !important; } /* Collection shells are #121212. Same selector as the 5% mix, plus .rounded-xl, so it wins. */ html.dark .app-main [class*="dark:bg-white/[0.05]"].rounded-xl:not(:is([class*="dark:bg-"]:not(.app-main), .button, .view-toggle, .application-settings-section, .application-settings-section-body, .box, .coolbox, .data-table, .resource-view, .empty-state, .loading-state-card, .runtime-log-shell, .logs-viewer) *) { - background-color: #121212 !important; + background-color: var(--color-card) !important; border-color: rgb(255 255 255 / 0.08) !important; } } diff --git a/resources/views/components/application/configuration-sidebar.blade.php b/resources/views/components/application/configuration-sidebar.blade.php index 6497a0b521..5d927443de 100644 --- a/resources/views/components/application/configuration-sidebar.blade.php +++ b/resources/views/components/application/configuration-sidebar.blade.php @@ -228,7 +228,7 @@ @php // The main sidebar shows this menu on wide screens (see components/navbar.blade.php). - registerMainNavContext(0, 'Dashboard', 'Back to the main menu', $application->name); + registerMainNavContext(0, 'Dashboard', 'Back to the main menu'); @endphp {{-- Rendered twice: in the page (below xl), and teleported into the main sidebar (xl and up). diff --git a/resources/views/components/database/configuration-sidebar.blade.php b/resources/views/components/database/configuration-sidebar.blade.php index 514b71b574..c11eaa05b1 100644 --- a/resources/views/components/database/configuration-sidebar.blade.php +++ b/resources/views/components/database/configuration-sidebar.blade.php @@ -60,7 +60,7 @@ @php // The main sidebar shows this menu on wide screens (see components/navbar.blade.php). - registerMainNavContext(0, 'Dashboard', 'Back to the main menu', $database->name); + registerMainNavContext(0, 'Dashboard', 'Back to the main menu'); @endphp {{-- Rendered twice: in the page (below xl), and teleported into the main sidebar (xl and up). diff --git a/resources/views/components/main-nav-menu.blade.php b/resources/views/components/main-nav-menu.blade.php index aeba3fdae1..3dc4687d2e 100644 --- a/resources/views/components/main-nav-menu.blade.php +++ b/resources/views/components/main-nav-menu.blade.php @@ -1,7 +1,7 @@ -@props(['backLabel', 'backTitle' => 'Back to the main menu', 'depth' => 0, 'name' => null, 'navOnly' => false]) +@props(['backLabel', 'backTitle' => 'Back to the main menu', 'depth' => 0, 'navOnly' => false]) @php // The main sidebar replaces its menu with this one on wide screens (see components/navbar.blade.php). - registerMainNavContext($depth, $backLabel, $backTitle, $name); + registerMainNavContext($depth, $backLabel, $backTitle); @endphp {{-- A page menu, rendered twice: in the page (below xl, CSS hides it on xl), and teleported into the main sidebar (xl and up). The slot must not contain Livewire components (they would render twice). diff --git a/resources/views/components/navbar.blade.php b/resources/views/components/navbar.blade.php index a7d8efa5e1..205029c7f3 100644 --- a/resources/views/components/navbar.blade.php +++ b/resources/views/components/navbar.blade.php @@ -178,7 +178,6 @@ // components/main-nav-menu.blade.php). Each one teleports itself into #main-nav-context-{depth}; // only the desktop sidebar has the slots. $navContext = $desktop ? request()->attributes->get('mainNavContext', []) : []; - $navContextName = collect($navContext)->pluck('name')->filter()->last() ?? 'Resource menu'; @endphp {{-- Wide screens on a resource page: the deepest resource menu replaces the main menu. Back shows the menu one depth lower, and then the main menu (or its submenu), without leaving the page. --}} @@ -256,25 +255,6 @@ @endforeach
  • $navContext]) :class="{ 'xl:hidden': navLevel !== -1 }">