mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-04 10:42:23 +00:00
style(ui): refine canvas layouts and rollback settings
This commit is contained in:
1 parent
c454f84545
commit
eeaeacbe3f
6 files changed
+124
-40
No files matched your search
@@ -195,8 +195,10 @@ Class names below are examples. Keep the values and structure.
|
||||
table rows are the darker content layer below them.
|
||||
- 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 brand-purple wash at the top (about 9%,
|
||||
fading out) and a faint lavender right edge (`rgb(163 145 255 / 0.10)`).
|
||||
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 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.
|
||||
@@ -204,6 +206,38 @@ Class names below are examples. Keep the values and structure.
|
||||
- Keep the chrome borders faint. A strong border on near-black looks like a
|
||||
line drawn on the page.
|
||||
|
||||
### App header (logo cell)
|
||||
|
||||
- The logo cell is the top of the sidebar column, in the 48px top bar. It is
|
||||
as wide as the sidebar: 224px expanded, 64px collapsed.
|
||||
- Expanded: the wordmark (15px semibold, tight tracking, `--ui-fg`), then the
|
||||
version on the same baseline (10.5px medium, `--ui-fg-faint`), with 6px
|
||||
between them and 16px side padding. An update badge sits at the right end.
|
||||
- Collapsed: only the 20px logo mark, centered. The cell gets a bottom border
|
||||
so that it lines up with the top bar edge.
|
||||
- The update badge is a small pill: 18px high, 6px side padding, 9.5px
|
||||
semibold text, fully rounded, a 10% fill, and a 25% inset ring of the same
|
||||
color. It is purple in light mode and warning yellow in dark mode. While an
|
||||
update runs, the same pill says "Updating". It hides when the sidebar is
|
||||
collapsed.
|
||||
- The mobile drawer starts with the same wordmark and version in a 48px row
|
||||
with a bottom border, and a 32px close button on the right. It has no update
|
||||
badge.
|
||||
|
||||
### Mobile header
|
||||
|
||||
- Below the desktop breakpoint (1024px) a sticky top bar replaces the desktop
|
||||
top bar and sidebar. It is about 56px high (12px vertical padding, 16px side
|
||||
padding, 24px from 640px), translucent (95% of `--ui-panel`) with a small
|
||||
blur, and has a faint bottom border.
|
||||
- Left: the logo mark (18px) in a 32px tile with an 8px radius and a neutral
|
||||
fill (`rgb(255 255 255 / 6%)` in dark mode), then the team switcher. The
|
||||
team name truncates.
|
||||
- Right, with 4px gaps: status indicators (configuration warnings, active
|
||||
deployments), the update badge, the user menu, and a 36px sidebar button
|
||||
(the same sidebar glyph as the desktop collapse toggle). The sidebar button
|
||||
opens the drawer from the right.
|
||||
|
||||
### Sidebar navigation
|
||||
|
||||
```css
|
||||
@@ -622,8 +656,9 @@ lift off the content:
|
||||
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 radial wash on the logo
|
||||
cell, and a lavender right edge. Section labels are 10.5px uppercase mono in
|
||||
(`#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;
|
||||
@@ -690,8 +725,31 @@ color. Row-hover states keep the lighter `dark:hover:bg-white/[0.025]`.
|
||||
rows; yellow washes look muddy on dark UI.
|
||||
- Nested items sit behind a thin 1px guide line (`.nav-children`) and use the
|
||||
same selected pill, not a thick box border.
|
||||
- The update badge sits on the version row and uses a tiny fully rounded
|
||||
primary-action pill.
|
||||
- The logo cell (`.app-topbar-brand` in `layouts/app.blade.php`) is `w-56`
|
||||
expanded and `w-16` collapsed. Expanded, it shows the `Coolify` wordmark
|
||||
(`text-[15px] font-semibold tracking-tight`), `<x-version>`
|
||||
(`text-[10.5px]`, `text-fg-faint` in dark), and the update badge
|
||||
(`livewire:upgrade`, instance admins on self-hosted only) at `ml-auto`.
|
||||
Collapsed, it shows only `/coolify-logo.svg` at `size-5` and adds
|
||||
`border-b`.
|
||||
- The update badge sits on the version row: an 18px fully rounded pill with
|
||||
9.5px semibold text. It is `bg-coollabs/10 text-coollabs ring-coollabs/25` in
|
||||
light mode and the warning pill (`dark:bg-warning/15 dark:text-warning
|
||||
dark:ring-warning/25`) in dark mode, because an update is a real warning.
|
||||
While an upgrade runs it says "Updating". Both open the upgrade modal.
|
||||
- The mobile drawer header (`data-mobile-sidebar-brand`) repeats the wordmark
|
||||
and version in an `h-12` row with a bottom border and a close button. It
|
||||
does not show the update badge.
|
||||
- The mobile top bar (`MOBILE TOP BAR` in `layouts/app.blade.php`, `lg:hidden`)
|
||||
is `sticky top-0 z-40`, `px-4 py-3 sm:px-6`, `bg-white/95 dark:bg-panel/95
|
||||
backdrop-blur-sm` with `border-neutral-200/60 dark:border-white/[0.06]`.
|
||||
Left: `/coolify-logo.svg` (18px) in a `size-8 rounded-lg bg-neutral-100
|
||||
dark:bg-white/[0.06]` tile, then `livewire:switch-team`. Right (`gap-1`):
|
||||
`#configuration-warning-hud-slot-mobile`, `deployments-indicator
|
||||
variant="mobile"`, the update badge (`livewire:upgrade key="mobile-upgrade"`,
|
||||
instance admins on self-hosted only), `x-top-user-menu`, and a `size-9`
|
||||
button that toggles the drawer. Keep these in the same order as the desktop
|
||||
top bar.
|
||||
- Submenu chevrons (the right chevron on rows that open a submenu and the back
|
||||
chevron) are `text-coollabs` in light mode and grey in dark mode
|
||||
(`dark:text-fg-faint` right, `dark:text-fg-dim` back).
|
||||
|
||||
+39
-1
@@ -6023,9 +6023,10 @@ html.dark .mobile-sidebar-sheet [role="dialog"] {
|
||||
--color-nav-muted: oklch(58% 0.04 300);
|
||||
}
|
||||
|
||||
/* Same color as the top of the sidebar gradient, so the brand and sidebar read as one surface. */
|
||||
html.dark .app-topbar-brand {
|
||||
background-color: var(--color-sidebar);
|
||||
background-image: radial-gradient(140% 260% at 0% 0%, rgb(107 22 237 / 0.12), transparent 70%);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -6102,6 +6103,43 @@ html.dark.is-scrolled:not([data-nav-style="floating"]) .app-topbar > div:not(.ap
|
||||
box-shadow: 0 10px 30px -14px rgb(0 0 0 / 0.95), 0 1px 0 rgb(107 22 237 / 0.06);
|
||||
}
|
||||
|
||||
/* Canvases (default navigation): the canvas runs under a clear top bar, and the
|
||||
canvas root paints the dots (set by the canvas JS) behind it, like the
|
||||
floating navigation does. */
|
||||
@media (min-width: 1024px) {
|
||||
html:not([data-nav-style="floating"]) .app-main.app-main-full:has(:is([data-ec-root], .cv-root)) {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
html:not([data-nav-style="floating"]) .app-main-full :is([data-ec-root], .cv-root) {
|
||||
padding-top: calc(3rem + 0.5rem);
|
||||
}
|
||||
|
||||
/* The deploy canvas (.cv-root) paints its own dots. */
|
||||
html:not([data-nav-style="floating"]) .app-main-full [data-ec-root] {
|
||||
background-image: var(--canvas-dots-image, radial-gradient(circle, rgb(0 0 0 / 0.13) 1px, transparent 1px));
|
||||
background-size: var(--canvas-dots-size, 20px 20px);
|
||||
background-position: var(--canvas-dots-position, 0 0);
|
||||
}
|
||||
|
||||
html.dark:not([data-nav-style="floating"]) .app-main-full [data-ec-root] {
|
||||
background-image: var(--canvas-dots-image, radial-gradient(circle, rgb(255 255 255 / 0.09) 1px, transparent 1px));
|
||||
}
|
||||
|
||||
html:not([data-nav-style="floating"]) .app-main-full [data-ec-viewport] {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
html:not([data-nav-style="floating"]):has(.app-main-full :is([data-ec-root], .cv-root)) .app-topbar {
|
||||
background-color: transparent;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
html:not([data-nav-style="floating"]):has(.app-main-full :is([data-ec-root], .cv-root)) .app-topbar > div:not(.app-topbar-brand) {
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
html.dark .view-toggle {
|
||||
gap: 2px;
|
||||
padding: 2px;
|
||||
|
||||
@@ -233,14 +233,6 @@
|
||||
],
|
||||
['id' => 'healthcheck-timing-section', 'label' => 'Timing and retries'],
|
||||
],
|
||||
'project.application.rollback' => [
|
||||
['id' => 'rollback-retention-section', 'label' => 'Image retention'],
|
||||
['id' => 'rollback-images-section', 'label' => 'Available images'],
|
||||
],
|
||||
'project.application.resource-limits' => [
|
||||
['id' => 'cpu-limits-section', 'label' => 'CPU'],
|
||||
['id' => 'memory-limits-section', 'label' => 'Memory'],
|
||||
],
|
||||
'project.application.resource-operations' => [
|
||||
['id' => 'clone-destination-section', 'label' => 'Clone destination'],
|
||||
['id' => 'clone-environment-section', 'label' => 'Clone environment'],
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
x-transition:leave-start="translate-x-0" x-transition:leave-end="translate-x-full"
|
||||
class="relative flex h-full w-72 max-w-[85vw] min-w-0 flex-col overflow-hidden rounded-l-2xl border-l border-neutral-200 bg-white shadow-[-8px_0_30px_-6px_rgba(0,0,0,0.18)] dark:border-white/[0.12] dark:bg-panel dark:shadow-[-8px_0_30px_-4px_rgba(0,0,0,0.5)]">
|
||||
<div data-mobile-sidebar-brand
|
||||
class="flex h-12 shrink-0 items-center justify-between gap-1.5 border-b border-neutral-200 px-4 dark:border-white/[0.06]">
|
||||
class="flex h-12 shrink-0 items-center justify-between gap-1.5 border-b border-neutral-200 px-4 dark:border-white/[0.06] dark:bg-panel">
|
||||
<div class="flex min-w-0 items-baseline gap-1.5">
|
||||
<a href="/" {{ wireNavigate() }} title="Coolify"
|
||||
class="text-[15px] font-semibold tracking-tight text-black transition-opacity hover:opacity-80 dark:text-white">
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<div class="flex flex-col gap-6" x-init="$wire.loadImages">
|
||||
<form wire:submit="saveSettings" class="application-settings-form flex flex-col">
|
||||
<x-unsaved-bar action="saveSettings" />
|
||||
<x-application.settings-section id="rollback-retention-section" title="Image retention"
|
||||
helper="Keep previously built Docker images available for fast rollbacks.">
|
||||
<x-application.settings-section title="Rollback images"
|
||||
helper="Keep previously built Docker images available for fast rollbacks. Rollback uses an existing image without rebuilding the application. Images in the Docker registry are pulled to the server first." flush>
|
||||
<x-slot:actions>
|
||||
@can('view', $application)
|
||||
<x-forms.button wire:click="loadImages(true)">
|
||||
Reload images
|
||||
</x-forms.button>
|
||||
@endcan
|
||||
</x-slot:actions>
|
||||
|
||||
<form wire:submit="saveSettings"
|
||||
class="flex flex-col gap-4 border-b border-neutral-200 px-4 py-3.5 dark:border-white/[0.07]">
|
||||
<x-unsaved-bar action="saveSettings" />
|
||||
@if ($serverRetentionDisabled)
|
||||
<div class="mb-4">
|
||||
<x-callout type="warning" title="Disabled by the server">
|
||||
Image retention is disabled at the server level. This setting has no effect until a server
|
||||
administrator enables it.
|
||||
</x-callout>
|
||||
</div>
|
||||
<x-callout type="warning" title="Disabled by the server">
|
||||
Image retention is disabled at the server level. This setting has no effect until a server
|
||||
administrator enables it.
|
||||
</x-callout>
|
||||
@endif
|
||||
|
||||
<div class="max-w-sm">
|
||||
@@ -18,18 +25,7 @@
|
||||
helper="Set to 0 to keep only the running image. Pull request images are always removed during cleanup."
|
||||
canGate="update" :canResource="$application" :disabled="$serverRetentionDisabled" />
|
||||
</div>
|
||||
</x-application.settings-section>
|
||||
</form>
|
||||
|
||||
<x-application.settings-section id="rollback-images-section" title="Available images"
|
||||
helper="Rollback uses an existing image without rebuilding the application. Images in the Docker registry are pulled to the server first." flush>
|
||||
<x-slot:actions>
|
||||
@can('view', $application)
|
||||
<x-forms.button wire:click="loadImages(true)">
|
||||
Reload images
|
||||
</x-forms.button>
|
||||
@endcan
|
||||
</x-slot:actions>
|
||||
</form>
|
||||
|
||||
<div wire:target="loadImages" wire:loading.remove>
|
||||
@forelse ($images as $image)
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
<label for="service-force-https-{{ $appId }}-trigger" class="mb-0! whitespace-nowrap text-[12px]!">Redirect HTTP to HTTPS</label>
|
||||
<x-helper helper="Disable only when Cloudflare Tunnel or another proxy connects to Coolify over HTTP. Keep enabled when Cloudflare uses Full or Full (Strict) SSL." />
|
||||
<x-forms.listbox canGate="update" :canResource="$service" id="forceHttpsRedirects.{{ $appId }}"
|
||||
htmlId="service-force-https-{{ $appId }}" preserveValue
|
||||
htmlId="service-force-https-{{ $appId }}" preserveValue portal
|
||||
onChange="updateForceHttps"
|
||||
:onChangeArgs="[(int) $appId]"
|
||||
:options="[
|
||||
@@ -193,7 +193,7 @@
|
||||
<label for="service-permanent-redirect-{{ $appId }}-trigger" class="mb-0! whitespace-nowrap text-[12px]!">Redirect type</label>
|
||||
<x-helper helper="Applies to the HTTP to HTTPS and www redirects. Permanent (301/308) is better for SEO, but browsers cache it. Use Temporary (302/307) while you test a redirect." />
|
||||
<x-forms.listbox canGate="update" :canResource="$service" id="permanentRedirects.{{ $appId }}"
|
||||
htmlId="service-permanent-redirect-{{ $appId }}" preserveValue
|
||||
htmlId="service-permanent-redirect-{{ $appId }}" preserveValue portal
|
||||
onChange="updatePermanentRedirect"
|
||||
:onChangeArgs="[(int) $appId]"
|
||||
:options="[
|
||||
|
||||
Reference in new issue
Block a user