feat(ui): WCAG contrast, neutral oklch surface system, and mobile nav overhaul
Design tokens - Fix WCAG AA text failures: darken light muted text and lighten dark tertiary text so 13-14px copy clears 4.5:1 on every surface. - Rebuild the dark surface ladder in correct values (oklch compresses to near-black below ~15%), giving visible steps: content, chrome, cards. - Establish a 3-layer shell (deep content, lighter sidebar/topbar chrome, lifted cards) with crisp hairline rings and a restrained card shadow. - Unify every surface to one neutral temperature (pure gray); neutralize the cool-tinted sidebar text and legacy surface tokens. - Convert all color tokens to oklch (neutrals + brand). - Unify inputs to the recessed token; fix invisible dark placeholders. - One shared --shadow-dropdown for all menus/listboxes/command palette. Settings sidebar - Sticky contained-card rail with subtle scrollbar; collapsible sub-section groups (active open by default), cross-page section links. - Mobile: collapsible disclosure with animated open, outside/Escape dismiss, press feedback, and reduced-motion support. Mobile - Consolidate the resource header (title + status + links on one row). - Tighten settings-page vertical rhythm. - Rebuild the main sidebar as an animated shadcn-style sheet (slide/fade, Escape, scroll lock, in-panel close, close-on-navigate). Fixes - #11532: selected server invisible in the light-mode terminal toolbar. Docs: update DESIGN.md tokens, shell layering, and temperature rules.
This commit is contained in:
parent
ba30c64d7d
commit
d91d2fa35d
59 changed files with 467 additions and 272 deletions
48
DESIGN.md
48
DESIGN.md
|
|
@ -34,7 +34,9 @@ ## 1. Visual direction
|
|||
|
||||
- near-neutral layered surfaces instead of large bordered boxes;
|
||||
- 13–14px UI typography and 32px controls;
|
||||
- hairline rings instead of heavy borders;
|
||||
- crisp hairline rings plus a restrained card lift (single 1px ring +
|
||||
`0 1px 2px rgb(0 0 0 / 0.05)`) so cards and tables separate from the canvas,
|
||||
never heavy borders or a strong floating shadow;
|
||||
- full-width data tables for dense collections;
|
||||
- outline Reicon glyphs through `<x-reicon>`;
|
||||
- the Coolify purple brand accent in light mode;
|
||||
|
|
@ -89,14 +91,14 @@ ## 3. Tokens and color behavior
|
|||
|
||||
| Token | Light | Dark | Use |
|
||||
|---|---|---|---|
|
||||
| `--coollabs-canvas` | near white | 10% neutral | page canvas |
|
||||
| `--coollabs-canvas` | 97% off-white | 10% neutral | page canvas (kept below card fills so cards lift) |
|
||||
| `--coollabs-elevated` | 98% neutral | 15% neutral | shells and card headers |
|
||||
| `--coollabs-base` | white | 17% neutral | nested card bodies |
|
||||
| `--coollabs-recessed` | 96% neutral | 20% neutral | inputs and listboxes |
|
||||
| `--coollabs-fill` | 92.2% neutral | 26.9% neutral | dividers and passive fills |
|
||||
| `--coollabs-line` | translucent dark | 32% neutral | control borders |
|
||||
| `--coollabs-hairline` | 93.5% neutral | 26.9% neutral | shell rings |
|
||||
| `--coollabs-subtle` | 55.6% neutral | 70.8% neutral | labels and muted titles |
|
||||
| `--coollabs-hairline` | 85.5% neutral | 32% neutral | shell rings (crisp enough to read as a card edge, ~1.5:1) |
|
||||
| `--coollabs-subtle` | 50% neutral | 70.8% neutral | labels and muted titles (light darkened for WCAG AA 4.5:1) |
|
||||
|
||||
Accent behavior is intentionally theme-aware:
|
||||
|
||||
|
|
@ -116,6 +118,38 @@ ## 3. Tokens and color behavior
|
|||
The filled top-level action/tab treatment uses the same palette at a restrained
|
||||
opacity rather than a fully saturated fill.
|
||||
|
||||
### Shell layering
|
||||
|
||||
The app shell is three distinct surface layers, not one flat color. Chrome
|
||||
lifts, content is the base, cards lift off the content:
|
||||
|
||||
- **Content canvas** is the base layer: `bg-app` in dark (deepest,
|
||||
`--color-app` `#0a0a0b`), `bg-gray-50` in light. The `<main>` content area
|
||||
and page body use it.
|
||||
- **Sidebar and topbar chrome** use `bg-panel` in dark (`--color-panel`
|
||||
`#141418`, a clear step lighter than the content canvas) and `bg-white` in
|
||||
light, so the chrome reads as a separate panel from the content.
|
||||
|
||||
Dark surface tokens are hex, not oklch. oklch lightness compresses toward pure
|
||||
black below ~15% (oklch(10%) renders as sRGB 3, oklch(15%) as sRGB 11), so oklch
|
||||
values there give no visible step between layers. The dark ladder is
|
||||
`--color-app` 10, `--coollabs-elevated` 22, `--coollabs-base` 28,
|
||||
`--coollabs-recessed` 34 (sRGB), which reads as distinct surfaces.
|
||||
|
||||
Temperature: every panel is **pure neutral gray** (r=g=b), one consistent
|
||||
temperature across the sidebar, tables, cards, inputs, dividers, borders, and
|
||||
text, in both modes. Do not give one surface a cool (blue) or warm cast while
|
||||
the others stay neutral. 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/yellow brand accent.
|
||||
- **Cards, tables, and collection tiles** lift off the content canvas with
|
||||
`dark:bg-white/[0.05]` plus the crisp `--coollabs-hairline` ring; in light
|
||||
they are `bg-white` with the ring and the restrained card lift.
|
||||
|
||||
Do not paint the content area with the same `bg-panel` as the sidebar, and do
|
||||
not drop card fills below `dark:bg-white/[0.05]`; both make surfaces read as one
|
||||
color. Row-hover states keep the lighter `dark:hover:bg-white/[0.025]`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Page shells and navigation
|
||||
|
|
@ -419,6 +453,12 @@ ### Dropdowns
|
|||
the option content left-aligned and size the panel to its content or trigger;
|
||||
do not create an unnecessarily wide menu.
|
||||
|
||||
Every dropdown, menu, listbox panel, and the command palette uses the shared
|
||||
`--shadow-dropdown` token (`0 4px 12px rgb(0 0 0 / 0.12), 0 2px 4px
|
||||
rgb(0 0 0 / 0.08)`) for a restrained, consistent lift. Do not hand-roll a
|
||||
heavier `shadow-lg` / `0 18px 50px` / `0.45`-alpha drop shadow on a menu.
|
||||
Reserve the stronger `--shadow-modal` for actual modals, dialogs, and toasts.
|
||||
|
||||
Toolbar filter and sort buttons keep static labels (`Filter`, `Sort`). The
|
||||
selected option is indicated inside the menu, not repeated on the trigger.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,51 +20,63 @@ @theme {
|
|||
--font-geist-sans: 'Geist Sans', Inter, sans-serif;
|
||||
--font-logs: 'Geist Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
|
||||
--color-base: #101010;
|
||||
--color-warning: #fcd452;
|
||||
--color-warning-50: #fefce8;
|
||||
--color-warning-100: #fef9c3;
|
||||
--color-warning-200: #fef08a;
|
||||
--color-warning-300: #fde047;
|
||||
--color-warning-400: #fcd452;
|
||||
--color-warning-500: #facc15;
|
||||
--color-warning-600: #ca8a04;
|
||||
--color-warning-700: #a16207;
|
||||
--color-warning-800: #854d0e;
|
||||
--color-warning-900: #713f12;
|
||||
--color-success: #22C55E;
|
||||
--color-error: #dc2626;
|
||||
--color-coollabs-50: #f5f0ff;
|
||||
--color-coollabs: #6b16ed;
|
||||
--color-coollabs-100: #7317ff;
|
||||
--color-coollabs-200: #5a12c7;
|
||||
--color-coollabs-300: #4a0fa3;
|
||||
--color-coolgray-100: #181818;
|
||||
--color-coolgray-200: #202020;
|
||||
--color-coolgray-300: #242424;
|
||||
--color-coolgray-400: #282828;
|
||||
--color-coolgray-500: #323232;
|
||||
--color-base: oklch(17.3% 0 0);
|
||||
--color-warning: oklch(88.13% 0.1507 91.7);
|
||||
--color-warning-50: oklch(98.73% 0.0262 102.21);
|
||||
--color-warning-100: oklch(97.29% 0.0693 103.19);
|
||||
--color-warning-200: oklch(94.51% 0.1243 101.54);
|
||||
--color-warning-300: oklch(90.52% 0.1657 98.11);
|
||||
--color-warning-400: oklch(88.13% 0.1507 91.7);
|
||||
--color-warning-500: oklch(86.06% 0.1731 91.94);
|
||||
--color-warning-600: oklch(68.06% 0.1423 75.83);
|
||||
--color-warning-700: oklch(55.38% 0.1207 66.44);
|
||||
--color-warning-800: oklch(47.62% 0.1034 61.91);
|
||||
--color-warning-900: oklch(42.1% 0.0897 57.71);
|
||||
--color-success: oklch(72.27% 0.192 149.58);
|
||||
--color-error: oklch(57.71% 0.2152 27.33);
|
||||
--color-coollabs-50: oklch(96.33% 0.0206 301.15);
|
||||
--color-coollabs: oklch(49.65% 0.2709 289.33);
|
||||
--color-coollabs-100: oklch(52.34% 0.287 289.16);
|
||||
--color-coollabs-200: oklch(43.76% 0.2369 289.82);
|
||||
--color-coollabs-300: oklch(38.04% 0.2031 290.47);
|
||||
--color-coolgray-100: oklch(20.9% 0 0);
|
||||
--color-coolgray-200: oklch(24.35% 0 0);
|
||||
--color-coolgray-300: oklch(26.03% 0 0);
|
||||
--color-coolgray-400: oklch(27.68% 0 0);
|
||||
--color-coolgray-500: oklch(31.71% 0 0);
|
||||
|
||||
/* Graphite design language (ported from ref/frontend). Layered neutral
|
||||
surfaces + translucent hairlines. See DESIGN.md. */
|
||||
--color-app: #0c0c0d;
|
||||
/* Canvas: neutral near-black (oklch), not pure black */
|
||||
--color-panel: oklch(10% 0 0);
|
||||
--color-surface: #161618;
|
||||
--color-raised: #1c1c1e;
|
||||
--color-selected: #26262a;
|
||||
--color-fg: #f2f2f2;
|
||||
--color-fg-dim: #b4b4b8;
|
||||
--color-fg-faint: #6e6e74;
|
||||
--color-accent: #6b16ed;
|
||||
--color-accent-foreground: #ffffff;
|
||||
--color-hairline: rgba(255, 255, 255, 0.08);
|
||||
--color-nav-text: #525252;
|
||||
--color-nav-muted: #666666;
|
||||
--color-nav-active: #171717;
|
||||
--color-log: #0d0d0d;
|
||||
/* Content canvas: the darkest shell layer (sRGB ~10). Hex, not oklch:
|
||||
oklch lightness compresses to near-black below ~15%, so oklch(7.5%)
|
||||
renders as sRGB 1 with no visible step. */
|
||||
--color-app: oklch(14.48% 0 0);
|
||||
/* Sidebar + topbar chrome (sRGB ~20): a clear step lighter than the content
|
||||
canvas so the shell chrome separates from the content area. */
|
||||
--color-panel: oklch(19.13% 0 0);
|
||||
/* Pure neutral (r=g=b). Were cool-tinted (#161618/#1c1c1e/#26262a, b>r),
|
||||
which clashed with the neutral panel ladder. */
|
||||
--color-surface: oklch(20.02% 0 0);
|
||||
--color-raised: oklch(22.64% 0 0);
|
||||
--color-selected: oklch(26.86% 0 0);
|
||||
--color-fg: oklch(96.12% 0 0);
|
||||
--color-fg-dim: oklch(76.99% 0 0);
|
||||
/* Tertiary text. Raised from #6e6e74 (3.78:1 on base, failed WCAG AA)
|
||||
to #7e7e84 so 13-14px text clears 4.5:1 on the dark surface ladder. */
|
||||
--color-fg-faint: oklch(59.31% 0 0);
|
||||
--color-accent: oklch(49.65% 0.2709 289.33);
|
||||
--color-accent-foreground: oklch(100.0% 0 0);
|
||||
--color-hairline: oklch(100.0% 0 0 / 0.08);
|
||||
--color-nav-text: oklch(43.86% 0 0);
|
||||
--color-nav-muted: oklch(51.03% 0 0);
|
||||
--color-nav-active: oklch(20.46% 0 0);
|
||||
--color-log: oklch(15.91% 0 0);
|
||||
|
||||
--shadow-modal: 0 24px 64px rgba(0, 0, 0, 0.55), 0 4px 16px rgba(0, 0, 0, 0.4);
|
||||
/* One restrained lift shared by every dropdown/menu/listbox panel and the
|
||||
command palette. Lighter and consistent, replacing the old scattered
|
||||
0.45 / 0.35 / shadow-lg / shadow-sm mix. Modals keep --shadow-modal. */
|
||||
--shadow-dropdown: 0 4px 12px rgb(0 0 0 / 0.12), 0 2px 4px rgb(0 0 0 / 0.08);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -258,7 +270,7 @@ @layer components {
|
|||
*/
|
||||
html,
|
||||
body {
|
||||
@apply w-full min-h-full bg-gray-50 dark:bg-app dark:text-fg-dim;
|
||||
@apply w-full min-h-full bg-neutral-50 dark:bg-app dark:text-fg-dim;
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
@ -505,8 +517,8 @@ .terminal-fullscreen-shell::before {
|
|||
|
||||
.application-console-shell[data-console-theme="system"],
|
||||
.terminal-fullscreen-shell[data-console-theme="system"] {
|
||||
--console-theme-background: #fff;
|
||||
--console-theme-border: #d4d4d8;
|
||||
--console-theme-background: oklch(100.0% 0 0);
|
||||
--console-theme-border: oklch(87.11% 0.0055 286.29);
|
||||
--console-theme-opacity: 1;
|
||||
}
|
||||
|
||||
|
|
@ -517,13 +529,20 @@ html:not(.dark) .application-console-shell[data-console-theme="system"] .applica
|
|||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
html:not(.dark) .application-console-shell[data-console-theme="system"] .application-console-header [class*="text-white"] {
|
||||
html:not(.dark) .application-console-shell[data-console-theme="system"] .application-console-header [class*="text-white"],
|
||||
/* Session toolbar (selected-target trigger + label) sits over the white
|
||||
system console in light mode. Without this its text-white/* stayed white on
|
||||
white and the selected server was invisible (issue #11532). */
|
||||
html:not(.dark) .application-console-shell[data-console-theme="system"] .terminal-session-toolbar[class*="text-white"],
|
||||
html:not(.dark) .application-console-shell[data-console-theme="system"] .terminal-session-toolbar [class*="text-white"],
|
||||
html:not(.dark) .terminal-fullscreen-shell[data-console-theme="system"] .terminal-session-toolbar[class*="text-white"],
|
||||
html:not(.dark) .terminal-fullscreen-shell[data-console-theme="system"] .terminal-session-toolbar [class*="text-white"] {
|
||||
color: #52525b !important;
|
||||
}
|
||||
|
||||
html.dark .application-console-shell[data-console-theme="system"],
|
||||
html.dark .terminal-fullscreen-shell[data-console-theme="system"] {
|
||||
--console-theme-background: #121214;
|
||||
--console-theme-background: oklch(18.31% 0.004 285.99);
|
||||
--console-theme-border: rgb(255 255 255 / 0.08);
|
||||
}
|
||||
|
||||
|
|
@ -851,7 +870,7 @@ html:not(.dark) .application-console-shell[data-console-theme="system"] .termina
|
|||
color: #52525b;
|
||||
background: #fff;
|
||||
border-color: #d4d4d8;
|
||||
box-shadow: 0 18px 50px rgb(0 0 0 / 0.18);
|
||||
box-shadow: var(--shadow-dropdown);
|
||||
}
|
||||
|
||||
html:not(.dark) .application-console-shell[data-console-theme="system"] .terminal-target-picker [class*="text-white"] {
|
||||
|
|
@ -924,37 +943,53 @@ .terminal-fullscreen-btn:hover {
|
|||
* utility classes placed in the card markup.
|
||||
*/
|
||||
:root {
|
||||
--coollabs-canvas: oklch(98.75% 0 0);
|
||||
/* Page canvas is a faint off-white so white/elevated cards lift off it
|
||||
(shadcn pattern), instead of card and page reading as one flat color. */
|
||||
--coollabs-canvas: oklch(97% 0 0);
|
||||
--coollabs-elevated: oklch(98% 0 0);
|
||||
--coollabs-recessed: oklch(96% 0 0);
|
||||
--coollabs-base: #ffffff;
|
||||
--coollabs-base: oklch(100.0% 0 0);
|
||||
--coollabs-fill: oklch(92.2% 0 0);
|
||||
--coollabs-line: oklch(14.5% 0 0 / 0.1);
|
||||
--coollabs-hairline: oklch(93.5% 0 0);
|
||||
--coollabs-subtle: oklch(55.6% 0 0);
|
||||
/* Card/table edge ring. Crisped from 93.5% (1.17:1 on canvas, invisible)
|
||||
to 85.5% (1.51:1) so surfaces read as bordered cards, not flat fills. */
|
||||
--coollabs-hairline: oklch(85.5% 0 0);
|
||||
/* Muted labels/titles. Darkened from 55.6% (failed WCAG AA on elevated
|
||||
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);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--color-accent: #fcd452;
|
||||
--coollabs-canvas: oklch(10% 0 0);
|
||||
/* elevated (card shells/headers) and recessed (input fills) sit a touch
|
||||
above the canvas so they read lighter than near-black */
|
||||
--coollabs-elevated: oklch(15% 0 0);
|
||||
--coollabs-recessed: oklch(20% 0 0);
|
||||
--coollabs-base: oklch(17% 0 0);
|
||||
--coollabs-fill: oklch(26.9% 0 0);
|
||||
--color-accent: oklch(88.13% 0.1507 91.7);
|
||||
/* 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,
|
||||
visible steps: content 10 -> elevated 22 -> base 28 -> recessed 34.
|
||||
Pure neutral (r=g=b), matching the neutral borders/text and the light
|
||||
ladder, so every panel shares one temperature (no blue cast). */
|
||||
--coollabs-canvas: oklch(14.48% 0 0);
|
||||
--coollabs-elevated: oklch(20.02% 0 0);
|
||||
--coollabs-recessed: oklch(25.2% 0 0);
|
||||
--coollabs-base: oklch(22.64% 0 0);
|
||||
--coollabs-fill: oklch(29.31% 0 0);
|
||||
--coollabs-line: oklch(32% 0 0);
|
||||
--coollabs-hairline: oklch(26.9% 0 0);
|
||||
/* Crisped from 26.9% (1.36:1 on canvas) to 32% (1.63:1) so dark cards
|
||||
and tables show a visible edge instead of blending into the canvas. */
|
||||
--coollabs-hairline: oklch(32% 0 0);
|
||||
--coollabs-subtle: oklch(70.8% 0 0);
|
||||
--color-nav-text: #a8a8b0;
|
||||
--color-nav-muted: #7a7a84;
|
||||
--color-nav-active: #f2f2f2;
|
||||
/* Neutral (was #a8a8b0 / #7a7a84, both cool-tinted). Sidebar text now shares
|
||||
the same neutral temperature as the content text, so the sidebar no longer
|
||||
reads cooler than the panels/cards. */
|
||||
--color-nav-text: oklch(73.8% 0 0);
|
||||
--color-nav-muted: oklch(58.97% 0 0);
|
||||
--color-nav-active: oklch(96.12% 0 0);
|
||||
}
|
||||
|
||||
/* Theme surfaces are derived from one brand color. Changing
|
||||
--theme-base-color is enough to generate a complete dark surface ladder. */
|
||||
html[data-theme="custom"] {
|
||||
--theme-base-color: #6b16ed;
|
||||
--theme-base-color: oklch(49.65% 0.2709 289.33);
|
||||
--theme-bright-color: color-mix(in srgb, var(--theme-base-color) 85%, white);
|
||||
--theme-scrollbar-thumb: color-mix(in srgb, var(--theme-bright-color) 70%, var(--theme-accent-foreground));
|
||||
--theme-border-color: color-mix(in oklab, var(--theme-base-color) 42%, #52525b);
|
||||
|
|
@ -985,14 +1020,14 @@ html[data-theme="custom"] {
|
|||
--coollabs-fill: color-mix(in oklab, var(--theme-base-color) 32%, #18181a);
|
||||
--coollabs-line: var(--theme-border-color);
|
||||
--coollabs-hairline: color-mix(in srgb, var(--theme-border-color) 55%, var(--color-panel));
|
||||
--color-nav-text: #e4dfea;
|
||||
--color-nav-muted: #d8d2df;
|
||||
--color-nav-active: #ffffff;
|
||||
--color-nav-text: oklch(91.08% 0.0157 306.4);
|
||||
--color-nav-muted: oklch(87.24% 0.0188 306.63);
|
||||
--color-nav-active: oklch(100.0% 0 0);
|
||||
--color-log: color-mix(in oklab, var(--theme-base-color) 20%, #080809);
|
||||
--color-log-toolbar: color-mix(in oklab, var(--theme-base-color) 26%, #101011);
|
||||
--color-fg-dim: #e4dfea;
|
||||
--color-fg-faint: #d8d2df;
|
||||
--coollabs-subtle: #d8d2df;
|
||||
--color-fg-dim: oklch(91.08% 0.0157 306.4);
|
||||
--color-fg-faint: oklch(87.24% 0.0188 306.63);
|
||||
--coollabs-subtle: oklch(87.24% 0.0188 306.63);
|
||||
}
|
||||
|
||||
html[data-theme="custom"] .control-selected,
|
||||
|
|
@ -1349,7 +1384,9 @@ .application-settings-section {
|
|||
border-radius: 8px;
|
||||
border: none;
|
||||
background: var(--coollabs-elevated);
|
||||
box-shadow: 0 0 0 1px var(--coollabs-hairline);
|
||||
/* crisp ring + a restrained lift so the card separates from the canvas
|
||||
(shadcn-style), not a heavy floating shadow */
|
||||
box-shadow: 0 0 0 1px var(--coollabs-hairline), 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
/* keep anchored scrolls (scrollIntoView) clear of the fixed topbar + layer-2 nav */
|
||||
scroll-margin-top: 7rem;
|
||||
}
|
||||
|
|
@ -1471,16 +1508,49 @@ .server-settings-workspace > :not(.application-settings-navigation) {
|
|||
@media (min-width: 1280px) {
|
||||
.application-settings-navigation {
|
||||
position: sticky;
|
||||
top: calc(3rem + 1.75rem);
|
||||
top: calc(3rem + 1rem);
|
||||
align-self: start;
|
||||
max-height: calc(100dvh - 5.5rem);
|
||||
padding-right: 0.375rem;
|
||||
max-height: calc(100dvh - 5rem);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
/* Thin, subtle overlay scrollbar so it does not fight the card's rounded
|
||||
edge. Gutter stays stable so content does not shift when it appears. */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--coollabs-fill) transparent;
|
||||
scrollbar-gutter: stable;
|
||||
/* Contained card: a distinct elevated surface with a hairline ring and a
|
||||
restrained lift, so the settings nav reads as a structured panel that
|
||||
floats above the content canvas instead of loose links on the page. */
|
||||
padding: 0.5rem;
|
||||
background: var(--coollabs-elevated);
|
||||
border: 1px solid var(--coollabs-hairline);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 2px rgb(0 0 0 / 0.05);
|
||||
}
|
||||
|
||||
.application-settings-navigation::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.application-settings-navigation::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.application-settings-navigation::-webkit-scrollbar-thumb {
|
||||
border-radius: 9999px;
|
||||
background: var(--coollabs-fill);
|
||||
}
|
||||
|
||||
.application-settings-navigation::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--coollabs-line);
|
||||
}
|
||||
|
||||
/* Resource settings rail: pinned as a stacked second sidebar, flush to the
|
||||
main sidebar's right edge (left tracks its collapsed width via --rail-left).
|
||||
A subtle step lighter than the main sidebar chrome, with a hairline divider,
|
||||
so the two rails read as a cohesive stacked pair and the content is the
|
||||
distinct surface to their right. */
|
||||
/* Resource pages have a second fixed header row below the main header. */
|
||||
.application-settings-workspace > .application-settings-navigation {
|
||||
top: 4rem;
|
||||
|
|
@ -1494,6 +1564,17 @@ @media (min-width: 1280px) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Honor reduced-motion for the settings nav disclosure/accordion and the mobile
|
||||
sidebar sheet: keep open/close functional but drop the height/slide/fade. */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.application-settings-navigation,
|
||||
.application-settings-navigation *,
|
||||
.mobile-sidebar-sheet * {
|
||||
transition-duration: 0.01ms !important;
|
||||
animation-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Field labels */
|
||||
.application-settings-workspace label,
|
||||
.application-settings-form label {
|
||||
|
|
@ -1603,7 +1684,7 @@ .resource-heading-tabs::-webkit-scrollbar {
|
|||
* Circular chevrons sit over gradient fades when more tabs are off-screen.
|
||||
*/
|
||||
.resource-heading-tabs-scroller {
|
||||
--resource-heading-tabs-fade: #f5f5f5; /* neutral-100, matches pill track */
|
||||
--resource-heading-tabs-fade: oklch(97.02% 0 0); /* neutral-100, matches pill track */
|
||||
}
|
||||
|
||||
.dark .resource-heading-tabs-scroller {
|
||||
|
|
@ -1944,7 +2025,7 @@ .listbox-panel {
|
|||
border-radius: 10px;
|
||||
border: 1px solid var(--coollabs-line);
|
||||
background: var(--coollabs-recessed);
|
||||
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
||||
box-shadow: var(--shadow-dropdown);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ @utility input-focus {
|
|||
|
||||
/* input, select before */
|
||||
@utility input-select {
|
||||
@apply block h-9 px-3 py-1.5 w-full text-sm text-black rounded-md border border-neutral-200 bg-white dark:bg-surface dark:text-fg dark:border-white/[0.08] transition-colors disabled:bg-neutral-100 disabled:text-neutral-400 dark:disabled:bg-white/[0.03] dark:disabled:text-fg-faint;
|
||||
@apply block h-9 px-3 py-1.5 w-full text-sm text-black rounded-md border border-neutral-200 bg-[var(--coollabs-recessed)] dark:text-fg dark:border-white/[0.08] transition-colors disabled:bg-neutral-100 disabled:text-neutral-400 dark:disabled:bg-white/[0.03] dark:disabled:text-fg-faint;
|
||||
box-shadow: none;
|
||||
|
||||
&:where(.dark, .dark *) {
|
||||
|
|
@ -77,7 +77,7 @@ @utility input-select {
|
|||
|
||||
/* Readonly */
|
||||
@utility input {
|
||||
@apply dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/40 placeholder:text-neutral-300 dark:placeholder:text-neutral-700 read-only:text-neutral-500 read-only:bg-neutral-200;
|
||||
@apply dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/40 placeholder:text-neutral-400 dark:placeholder:text-neutral-500 read-only:text-neutral-500 read-only:bg-neutral-200;
|
||||
@apply input-select;
|
||||
@apply focus-visible:outline-none;
|
||||
|
||||
|
|
|
|||
|
|
@ -124,3 +124,16 @@ window.scrollToSettingsSection = function scrollToSettingsSection(id) {
|
|||
|
||||
rafId = window.requestAnimationFrame(tick);
|
||||
};
|
||||
|
||||
// When a settings sub-section link navigates across pages (href="route#section-id"),
|
||||
// scroll to that section once the destination page has rendered.
|
||||
function scrollToHashSettingsSection() {
|
||||
const hash = window.location.hash;
|
||||
if (!hash || hash.length < 2) {
|
||||
return;
|
||||
}
|
||||
const id = decodeURIComponent(hash.slice(1));
|
||||
window.requestAnimationFrame(() => window.scrollToSettingsSection?.(id));
|
||||
}
|
||||
document.addEventListener('livewire:navigated', scrollToHashSettingsSection);
|
||||
document.addEventListener('DOMContentLoaded', scrollToHashSettingsSection);
|
||||
|
|
|
|||
|
|
@ -238,52 +238,98 @@
|
|||
];
|
||||
@endphp
|
||||
|
||||
@php
|
||||
$activeMenuLabel = collect($groupedMenuItems)->flatMap(fn ($items) => $items)->firstWhere('active', true)['label'] ?? 'Settings';
|
||||
@endphp
|
||||
<aside @class([
|
||||
'application-settings-navigation min-w-0 xl:self-start',
|
||||
'is-flush' => $flush,
|
||||
])>
|
||||
<nav aria-label="Configuration sections"
|
||||
class="grid grid-cols-2 gap-0.5 border-y border-neutral-200 py-3 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-1 xl:border-y-0 xl:py-0 dark:border-white/[0.06]">
|
||||
])
|
||||
x-data="{
|
||||
menuOpen: false,
|
||||
desktop: window.matchMedia('(min-width: 1280px)').matches,
|
||||
init() {
|
||||
const mq = window.matchMedia('(min-width: 1280px)');
|
||||
mq.addEventListener('change', (e) => { this.desktop = e.matches; if (e.matches) { this.menuOpen = false; } });
|
||||
},
|
||||
}"
|
||||
x-on:click.outside="menuOpen = false"
|
||||
x-on:keydown.escape.window="menuOpen = false">
|
||||
{{-- Mobile disclosure: tap to reveal the full grouped nav; hidden at xl (the pinned rail). --}}
|
||||
<button type="button" x-show="!desktop" x-cloak x-on:click="menuOpen = !menuOpen"
|
||||
:aria-expanded="menuOpen" aria-label="Configuration menu"
|
||||
:class="menuOpen && 'ring-1 ring-black/10 dark:ring-white/15'"
|
||||
class="flex h-10 w-full items-center justify-between gap-2 rounded-xl border border-neutral-200 bg-white px-3 text-[13px] font-medium text-black transition-transform duration-100 ease-out hover:bg-neutral-50 active:scale-[0.985] dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg dark:hover:bg-white/[0.08]">
|
||||
<span class="flex min-w-0 items-center gap-2">
|
||||
<x-reicon name="settings" class="size-4 shrink-0 text-nav-muted" />
|
||||
<span class="truncate">{{ $activeMenuLabel }}</span>
|
||||
</span>
|
||||
<svg class="size-3.5 shrink-0 text-nav-muted transition-transform duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]"
|
||||
:class="menuOpen && 'rotate-180'" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="m3.5 4.75 2.5 2.5 2.5-2.5" stroke="currentColor" stroke-width="1.25"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<nav aria-label="Configuration sections" x-show="desktop || menuOpen" x-collapse.duration.200ms x-cloak
|
||||
class="mt-2 flex flex-col gap-0.5 rounded-xl border border-neutral-200 bg-white p-2 shadow-[var(--shadow-dropdown)] dark:border-white/[0.08] dark:bg-white/[0.03] xl:mt-0 xl:rounded-none xl:border-0 xl:bg-transparent xl:p-0 xl:shadow-none xl:dark:bg-transparent">
|
||||
@foreach ($groupedMenuItems as $groupLabel => $groupItems)
|
||||
@unless ($loop->first)
|
||||
<div class="hidden xl:block my-2 border-t border-neutral-200 dark:border-white/[0.06]" aria-hidden="true"></div>
|
||||
<div class="my-2 border-t border-neutral-200 dark:border-white/[0.06]" aria-hidden="true"></div>
|
||||
@endunless
|
||||
<div class="nav-section hidden xl:block">{{ $groupLabel }}</div>
|
||||
<div class="nav-section">{{ $groupLabel }}</div>
|
||||
@foreach ($groupItems as $menuItem)
|
||||
<a wire:key="application-settings-link-{{ str($menuItem['label'])->slug() }}"
|
||||
@class([
|
||||
'menu-item',
|
||||
'menu-item-active' => $menuItem['active'],
|
||||
])
|
||||
@if ($menuItem['navigate'] ?? true) {{ wireNavigate() }} @endif
|
||||
href="{{ route($menuItem['route'], $applicationRouteParameters) }}">
|
||||
<x-reicon :name="$menuIcons[$menuItem['label']] ?? 'settings'" class="menu-item-icon" />
|
||||
<span class="menu-item-label">{{ $menuItem['label'] }}</span>
|
||||
@if ($menuItem['badge'] ?? false)
|
||||
<span class="shrink-0">
|
||||
<livewire:project.application.server-status-badge :application="$application"
|
||||
:key="'application-server-status-'.$application->uuid" />
|
||||
</span>
|
||||
@php $sections = $pageSections[$menuItem['route']] ?? []; @endphp
|
||||
<div wire:key="application-settings-group-{{ str($menuItem['label'])->slug() }}"
|
||||
@if (filled($sections)) x-data="{ open: @js($menuItem['active']), activeSection: '' }" @endif
|
||||
class="relative">
|
||||
<a wire:key="application-settings-link-{{ str($menuItem['label'])->slug() }}"
|
||||
@class([
|
||||
'menu-item',
|
||||
'menu-item-active' => $menuItem['active'],
|
||||
'pr-9' => filled($sections),
|
||||
])
|
||||
@if ($menuItem['navigate'] ?? true) {{ wireNavigate() }} @endif
|
||||
href="{{ route($menuItem['route'], $applicationRouteParameters) }}"
|
||||
x-on:click="menuOpen = false">
|
||||
<x-reicon :name="$menuIcons[$menuItem['label']] ?? 'settings'" class="menu-item-icon" />
|
||||
<span class="menu-item-label">{{ $menuItem['label'] }}</span>
|
||||
@if ($menuItem['badge'] ?? false)
|
||||
<span class="shrink-0">
|
||||
<livewire:project.application.server-status-badge :application="$application"
|
||||
:key="'application-server-status-'.$application->uuid" />
|
||||
</span>
|
||||
@endif
|
||||
</a>
|
||||
@if (filled($sections))
|
||||
{{-- Expand/collapse the page's sub-sections. Active page opens by
|
||||
default; the label still navigates, the chevron only toggles. --}}
|
||||
<button type="button"
|
||||
class="absolute right-1 top-1 flex size-6 items-center justify-center rounded-md text-nav-muted transition-colors hover:bg-black/[0.04] hover:text-nav-active dark:hover:bg-white/[0.06]"
|
||||
x-on:click.stop.prevent="open = !open" :aria-expanded="open"
|
||||
aria-label="Toggle {{ $menuItem['label'] }} sections">
|
||||
<svg class="size-3.5 transition-transform duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]"
|
||||
:class="open && 'rotate-90'" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="m4.5 3 3 3-3 3" stroke="currentColor" stroke-width="1.25"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
<div>
|
||||
<div x-show="open" x-collapse x-cloak
|
||||
class="nav-children flex flex-col gap-0.5 py-1">
|
||||
@foreach ($sections as $section)
|
||||
<a class="menu-subitem"
|
||||
:class="activeSection === '{{ $section['id'] }}' && 'menu-subitem-active'"
|
||||
href="{{ route($menuItem['route'], $applicationRouteParameters) }}#{{ $section['id'] }}"
|
||||
{{ wireNavigate() }}
|
||||
x-on:click="menuOpen = false; if (document.getElementById('{{ $section['id'] }}')) { $event.preventDefault(); activeSection = '{{ $section['id'] }}'; history.replaceState(null, '', '#{{ $section['id'] }}'); window.scrollToSettingsSection?.('{{ $section['id'] }}'); }">
|
||||
<span class="menu-item-label text-left">{{ $section['label'] }}</span>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</a>
|
||||
@if ($menuItem['active'] && count($pageSections[$menuItem['route']] ?? []) >= 4)
|
||||
<div class="nav-children hidden flex-col gap-0.5 py-1 xl:flex"
|
||||
x-data="{
|
||||
activeSection: '',
|
||||
scrollToSection(id) {
|
||||
this.activeSection = id;
|
||||
window.scrollToSettingsSection?.(id);
|
||||
},
|
||||
}">
|
||||
@foreach ($pageSections[$menuItem['route']] as $section)
|
||||
<button type="button" class="menu-subitem"
|
||||
:class="activeSection === '{{ $section['id'] }}' && 'menu-subitem-active'"
|
||||
@click="scrollToSection('{{ $section['id'] }}')">
|
||||
<span class="menu-item-label text-left">{{ $section['label'] }}</span>
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<div class="mx-auto mb-6 w-full max-w-3xl">
|
||||
<div
|
||||
class="grid grid-cols-3 overflow-hidden rounded-[10px] border border-neutral-200 bg-white dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="grid grid-cols-3 overflow-hidden rounded-[10px] border border-neutral-200 bg-white dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
@for ($i = 1; $i <= $totalSteps; $i++)
|
||||
<div @class([
|
||||
'flex min-h-10 items-center justify-center gap-2 border-r border-neutral-200 px-3 text-[11px] font-medium last:border-r-0 dark:border-white/[0.08]',
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
]) x-cloak>
|
||||
<div @class([
|
||||
'border border-neutral-300 bg-white p-1 dark:border-coolgray-300',
|
||||
'shadow-sm dark:bg-coolgray-200' => ! $inline,
|
||||
'shadow-[var(--shadow-dropdown)] dark:bg-coolgray-200' => ! $inline,
|
||||
'border-0 bg-transparent shadow-none dark:border-0 dark:bg-transparent' => $inline,
|
||||
$panelClass,
|
||||
])>
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@
|
|||
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
class="absolute z-20 top-full mt-1 w-56 -ml-2 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-neutral-200 dark:border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
|
||||
class="absolute z-20 top-full mt-1 w-56 -ml-2 bg-white dark:bg-coolgray-100 rounded-md shadow-[var(--shadow-dropdown)] py-1 border border-neutral-200 dark:border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
|
||||
@foreach ($projects as $project)
|
||||
<a href="{{ route('project.show', ['project_uuid' => $project->uuid]) }}" {{ wireNavigate() }}
|
||||
class="block px-4 py-2 text-sm truncate hover:bg-neutral-100 dark:hover:bg-coolgray-200 {{ $project->uuid === $currentProjectUuid ? 'dark:text-warning font-semibold' : '' }}"
|
||||
|
|
@ -130,7 +130,7 @@ class="absolute z-20 top-full mt-1 left-0 sm:left-auto max-w-[calc(100vw-1rem)]"
|
|||
x-init="$nextTick(() => { const rect = $el.getBoundingClientRect(); if (rect.right > window.innerWidth) { $el.style.left = 'auto'; $el.style.right = '0'; } })">
|
||||
<!-- Environment List -->
|
||||
<div
|
||||
class="relative w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-neutral-200 dark:border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
|
||||
class="relative w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-[var(--shadow-dropdown)] py-1 border border-neutral-200 dark:border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
|
||||
@foreach ($environments as $environment)
|
||||
@php
|
||||
$envDatabases = collect()
|
||||
|
|
@ -205,7 +205,7 @@ class="flex items-center gap-2 px-4 py-2 text-sm hover:bg-neutral-100 dark:hover
|
|||
:style="'position: absolute; left: 100%; top: ' + (envPositions['{{ $environment->uuid }}'] || 0) + 'px; z-index: 30;'"
|
||||
class="flex flex-col sm:flex-row items-start pl-1">
|
||||
<div
|
||||
class="relative w-56 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-neutral-200 dark:border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
|
||||
class="relative w-56 bg-white dark:bg-coolgray-100 rounded-md shadow-[var(--shadow-dropdown)] py-1 border border-neutral-200 dark:border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
|
||||
@foreach ($envResources as $envResource)
|
||||
@php
|
||||
$resType = $envResource['type'];
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class="button button-highlighted">
|
|||
<div class="grid grid-cols-1 gap-3 p-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($tokens as $token)
|
||||
<a wire:key="{{ $provider }}-token-{{ $token->id }}"
|
||||
class="group flex min-h-28 min-w-0 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-28 min-w-0 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('server.create.token', ['type' => $routeType ?: $provider, 'token_uuid' => $token->uuid]) }}"
|
||||
{{ wireNavigate() }}>
|
||||
<div class="flex items-start gap-3">
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class="terminal-theme-trigger flex h-8 items-center gap-2 rounded-md px-2.5 text
|
|||
</button>
|
||||
|
||||
<div x-cloak x-show="themeOpen" x-transition.origin.top.right
|
||||
class="console-theme-selector absolute top-11 right-0 z-50 max-h-80 w-56 overflow-y-auto rounded-lg border border-neutral-200 bg-white p-1 shadow-[0_18px_50px_rgba(0,0,0,0.18)] dark:border-white/[0.1] dark:bg-[#111113] dark:shadow-[0_18px_50px_rgba(0,0,0,0.55)]">
|
||||
class="console-theme-selector absolute top-11 right-0 z-50 max-h-80 w-56 overflow-y-auto rounded-lg border border-neutral-200 bg-white p-1 shadow-[var(--shadow-dropdown)] dark:border-white/[0.1] dark:bg-[#111113]">
|
||||
@foreach ($themes as $theme)
|
||||
<button type="button"
|
||||
class="flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-[11px] text-neutral-600 transition-colors hover:bg-neutral-100 hover:text-neutral-950 dark:text-white/65 dark:hover:bg-white/[0.07] dark:hover:text-white"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<div class="w-full">
|
||||
<div
|
||||
class="grid grid-cols-4 overflow-hidden rounded-[10px] border border-neutral-200 bg-white dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="grid grid-cols-4 overflow-hidden rounded-[10px] border border-neutral-200 bg-white dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
@foreach ($steps as $stepNumber => $label)
|
||||
<div
|
||||
class="flex min-h-10 items-center justify-center gap-2 border-r border-neutral-200 px-2 text-[11px] font-medium last:border-r-0 dark:border-white/[0.08] sm:px-3"
|
||||
|
|
|
|||
|
|
@ -69,29 +69,42 @@ class="flex h-full items-center gap-0.5 min-w-0 flex-1 border-b border-neutral-2
|
|||
</div>
|
||||
</header>
|
||||
|
||||
{{-- ============ MOBILE SLIDE-OVER SIDEBAR ============ --}}
|
||||
<div class="relative z-[1000] lg:hidden" :class="open ? 'block' : 'hidden'" role="dialog" aria-modal="true">
|
||||
<div class="fixed inset-0 bg-black/80" x-on:click="open = false"></div>
|
||||
<div class="fixed inset-y-0 right-0 flex h-full">
|
||||
<div
|
||||
class="relative flex h-full w-full max-w-56 min-w-0 flex-col border-l border-neutral-200 bg-white shadow-xl dark:border-white/[0.12] dark:bg-panel">
|
||||
<div class="absolute top-0 right-full flex w-16 justify-center pt-5">
|
||||
<button type="button" class="-m-2.5 p-2.5" x-on:click="open = !open">
|
||||
<span class="sr-only">Close sidebar</span>
|
||||
<svg class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
{{-- ============ MOBILE SLIDE-OVER SIDEBAR (shadcn-style sheet) ============ --}}
|
||||
<div class="mobile-sidebar-sheet relative z-[1000] lg:hidden" role="dialog" aria-modal="true"
|
||||
x-on:keydown.escape.window="open = false"
|
||||
x-on:livewire:navigated.window="open = false"
|
||||
x-effect="document.body.classList.toggle('overflow-hidden', open)">
|
||||
{{-- Scrim: fades in/out --}}
|
||||
<div class="fixed inset-0 bg-black/50" x-show="open" x-cloak x-on:click="open = false"
|
||||
x-transition:enter="transition-opacity ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition-opacity ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"></div>
|
||||
{{-- Panel: slides in from the right (iOS drawer curve), exits faster --}}
|
||||
<div class="fixed inset-y-0 right-0 flex" :class="!open && 'pointer-events-none'">
|
||||
<div x-show="open" x-cloak
|
||||
x-transition:enter="transform transition ease-[cubic-bezier(0.32,0.72,0,1)] duration-300"
|
||||
x-transition:enter-start="translate-x-full" x-transition:enter-end="translate-x-0"
|
||||
x-transition:leave="transform transition ease-in duration-200"
|
||||
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 border-l border-neutral-200 bg-white shadow-2xl dark:border-white/[0.12] dark:bg-panel">
|
||||
<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]">
|
||||
<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">
|
||||
Coolify
|
||||
</a>
|
||||
<x-version class="!text-[10.5px] font-medium text-neutral-400 dark:text-fg-faint !opacity-100 hover:!opacity-100 hover:text-black dark:hover:text-fg" />
|
||||
</div>
|
||||
<button type="button" x-on:click="open = false" aria-label="Close menu"
|
||||
class="-mr-1.5 flex size-8 shrink-0 items-center justify-center rounded-md text-neutral-500 transition-colors hover:bg-neutral-100 hover:text-black active:scale-95 dark:text-fg-dim dark:hover:bg-white/[0.06] dark:hover:text-fg">
|
||||
<svg class="size-5" fill="none" viewBox="0 0 24 24" stroke-width="1.75"
|
||||
stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div data-mobile-sidebar-brand
|
||||
class="flex h-12 shrink-0 items-center gap-1.5 border-b border-neutral-200 px-4 dark:border-white/[0.06]">
|
||||
<a href="/" {{ wireNavigate() }} title="Coolify"
|
||||
class="text-[15px] font-semibold tracking-tight text-black transition-opacity hover:opacity-80 dark:text-white">
|
||||
Coolify
|
||||
</a>
|
||||
<x-version class="!text-[10.5px] font-medium text-neutral-400 dark:text-fg-faint !opacity-100 hover:!opacity-100 hover:text-black dark:hover:text-fg" />
|
||||
</div>
|
||||
<div class="flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto pb-2 scrollbar">
|
||||
<x-navbar />
|
||||
</div>
|
||||
|
|
@ -128,7 +141,8 @@ class="hidden shrink-0 items-center"></div>
|
|||
<livewire:upgrade key="mobile-upgrade" />
|
||||
@endif
|
||||
<x-top-user-menu />
|
||||
<button type="button" class="-m-1 p-2 text-neutral-500 dark:text-fg-dim" x-on:click="open = !open">
|
||||
<button type="button" x-on:click="open = !open"
|
||||
class="-mr-1 flex size-9 items-center justify-center rounded-md text-neutral-500 transition-transform duration-100 ease-out hover:bg-neutral-100 hover:text-black active:scale-90 dark:text-fg-dim dark:hover:bg-white/[0.06] dark:hover:text-fg">
|
||||
<span class="sr-only">Open sidebar</span>
|
||||
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
|
|
@ -140,7 +154,7 @@ class="hidden shrink-0 items-center"></div>
|
|||
|
||||
{{-- ============ MAIN ============ --}}
|
||||
<main
|
||||
class="min-h-screen bg-white dark:bg-panel px-5 py-6 sm:px-8 lg:px-10 lg:pt-[calc(3rem+1.75rem)] lg:pb-10"
|
||||
class="min-h-screen bg-neutral-50 dark:bg-app px-5 py-6 sm:px-8 lg:px-10 lg:pt-[calc(3rem+1.75rem)] lg:pb-10"
|
||||
:class="[collapsed ? 'lg:ml-16' : 'lg:ml-56', sidebarReady ? 'transition-[margin] duration-200' : '']">
|
||||
<div class="w-full" :class="pageWidth === 'centered' ? 'mx-auto max-w-[1400px]' : 'max-w-none'">
|
||||
{{ $slot }}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
styles (e.g. [wire\:loading] { display: none }) must be rendered manually too. --}}
|
||||
@livewireStyles
|
||||
@livewireScripts
|
||||
<main class="h-full bg-gray-50 dark:bg-base">
|
||||
<main class="h-full bg-neutral-50 dark:bg-base">
|
||||
{{ $slot }}
|
||||
</main>
|
||||
@parent
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
Continue
|
||||
</x-forms.button>
|
||||
<div
|
||||
class="inline-flex flex-wrap items-center justify-center gap-0.5 rounded-lg border border-neutral-200 bg-neutral-50 p-0.5 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="inline-flex flex-wrap items-center justify-center gap-0.5 rounded-lg border border-neutral-200 bg-neutral-50 p-0.5 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<button type="button" wire:click="skipBoarding"
|
||||
class="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[12px] font-medium text-neutral-500 transition-colors hover:bg-white hover:text-coollabs dark:text-fg-dim dark:hover:bg-white/[0.06] dark:hover:text-warning">
|
||||
<x-reicon name="arrow-right" class="size-3.5 shrink-0" />
|
||||
|
|
@ -101,7 +101,7 @@ class="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[12px] font-
|
|||
<p class="mb-3 text-sm text-neutral-500 dark:text-neutral-400">Use this machine or connect a server you already manage.</p>
|
||||
<div class="grid w-full grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<button
|
||||
class="group relative cursor-pointer min-h-36 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group relative cursor-pointer min-h-36 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
wire:target="setServerType('localhost')" wire:click="setServerType('localhost')">
|
||||
<span role="button" tabindex="0" aria-label="About this machine"
|
||||
data-tooltip="The machine running Coolify. Not recommended for production workloads due to resource contention."
|
||||
|
|
@ -125,7 +125,7 @@ class="absolute top-3 right-3 flex size-6 items-center justify-center rounded-fu
|
|||
|
||||
|
||||
<button
|
||||
class="group relative cursor-pointer min-h-36 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group relative cursor-pointer min-h-36 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
wire:target="setServerType('remote')" wire:click="setServerType('remote')">
|
||||
<span role="button" tabindex="0" aria-label="About remote servers"
|
||||
data-tooltip="Any SSH-accessible server, including cloud VPS, bare metal, and self-hosted infrastructure."
|
||||
|
|
@ -157,7 +157,7 @@ class="absolute top-3 right-3 flex size-6 items-center justify-center rounded-fu
|
|||
<x-modal-input title="Connect a Hetzner Server" isFullWidth>
|
||||
<x-slot:content>
|
||||
<div
|
||||
class="group relative cursor-pointer flex h-full min-h-36 flex-col rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative cursor-pointer flex h-full min-h-36 flex-col rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex h-full flex-col gap-4 text-left">
|
||||
<img src="{{ asset('svgs/hetzner.svg') }}" alt="Hetzner"
|
||||
class="size-10 shrink-0">
|
||||
|
|
@ -175,7 +175,7 @@ class="size-10 shrink-0">
|
|||
<x-modal-input title="Connect a Vultr Server" isFullWidth>
|
||||
<x-slot:content>
|
||||
<div
|
||||
class="group relative cursor-pointer flex h-full min-h-36 flex-col rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative cursor-pointer flex h-full min-h-36 flex-col rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex h-full flex-col gap-4 text-left">
|
||||
<img src="https://www.vultr.com/media/logo_ondark.svg" alt="Vultr"
|
||||
class="h-10 w-28 shrink-0 object-contain object-left">
|
||||
|
|
@ -193,7 +193,7 @@ class="h-10 w-28 shrink-0 object-contain object-left">
|
|||
<x-modal-input title="Connect a DigitalOcean Server" isFullWidth>
|
||||
<x-slot:content>
|
||||
<div
|
||||
class="group relative cursor-pointer flex h-full min-h-36 flex-col rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative cursor-pointer flex h-full min-h-36 flex-col rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex h-full flex-col gap-4 text-left">
|
||||
<x-digital-ocean-icon class="size-10 shrink-0" />
|
||||
<div class="min-h-0 flex-1">
|
||||
|
|
@ -279,7 +279,7 @@ class="bg-red-200 dark:bg-red-900 px-1 rounded-sm">~/.ssh/authorized_keys</code>
|
|||
@endphp
|
||||
<div class="w-full space-y-4">
|
||||
<div
|
||||
class="rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<form wire:submit="selectExistingPrivateKey"
|
||||
class="flex flex-col gap-3 sm:flex-row sm:items-end">
|
||||
<div class="min-w-0 flex-1">
|
||||
|
|
@ -304,7 +304,7 @@ class="bg-[var(--coollabs-base)] px-2.5 text-[10px] font-semibold uppercase trac
|
|||
@endif
|
||||
<div class="grid w-full grid-cols-1 gap-3 lg:grid-cols-2">
|
||||
<button type="button"
|
||||
class="group flex h-full min-h-28 items-start gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex h-full min-h-28 items-start gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
wire:target="setPrivateKey('own')" wire:click="setPrivateKey('own')">
|
||||
<span
|
||||
class="flex size-9 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.035] dark:text-fg-dim">
|
||||
|
|
@ -318,7 +318,7 @@ class="flex size-9 shrink-0 items-center justify-center rounded-lg border border
|
|||
</span>
|
||||
</button>
|
||||
<button type="button"
|
||||
class="group flex h-full min-h-28 items-start gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex h-full min-h-28 items-start gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
wire:target="setPrivateKey('create')" wire:click="setPrivateKey('create')">
|
||||
<span
|
||||
class="flex size-9 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.035] dark:text-fg-dim">
|
||||
|
|
@ -597,7 +597,7 @@ class="text-[10px] font-semibold uppercase tracking-[0.08em] text-neutral-400 da
|
|||
Deploy your first resource
|
||||
</x-forms.button>
|
||||
<div
|
||||
class="inline-flex flex-wrap items-center justify-center gap-0.5 rounded-lg border border-neutral-200 bg-neutral-50 p-0.5 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="inline-flex flex-wrap items-center justify-center gap-0.5 rounded-lg border border-neutral-200 bg-neutral-50 p-0.5 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<button type="button" wire:click="skipBoarding"
|
||||
class="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[12px] font-medium text-neutral-500 transition-colors hover:bg-white hover:text-coollabs dark:text-fg-dim dark:hover:bg-white/[0.06] dark:hover:text-warning">
|
||||
<x-reicon name="arrow-right" class="size-3.5 shrink-0" />
|
||||
|
|
@ -622,7 +622,7 @@ class="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[12px] font-
|
|||
@if ($currentState !== 'welcome' && $currentState !== 'create-resource')
|
||||
<div class="mx-auto mt-6 flex w-full max-w-3xl flex-col items-center gap-3">
|
||||
<div
|
||||
class="inline-flex flex-wrap items-center justify-center gap-0.5 rounded-lg border border-neutral-200 bg-neutral-50 p-0.5 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="inline-flex flex-wrap items-center justify-center gap-0.5 rounded-lg border border-neutral-200 bg-neutral-50 p-0.5 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<button type="button" wire:click="skipBoarding"
|
||||
class="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[12px] font-medium text-neutral-500 transition-colors hover:bg-white hover:text-coollabs dark:text-fg-dim dark:hover:bg-white/[0.06] dark:hover:text-warning">
|
||||
<x-reicon name="arrow-right" class="size-3.5 shrink-0" />
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class="inline-flex shrink-0 items-center gap-1 text-[12px] font-medium text-neut
|
|||
@endphp
|
||||
|
||||
<article
|
||||
class="group relative flex min-h-28 min-w-0 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 min-w-0 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<a href="{{ $project->navigateTo() }}" {{ wireNavigate() }}
|
||||
class="absolute inset-0 rounded-xl"
|
||||
aria-label="Open {{ $project->name }}"></a>
|
||||
|
|
@ -190,7 +190,7 @@ class="button button-highlighted">
|
|||
|
||||
<a href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}"
|
||||
{{ wireNavigate() }} aria-label="Open {{ $server->name }}"
|
||||
class="group relative flex min-h-28 min-w-0 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 min-w-0 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
@if ($server->isMetricsEnabled())
|
||||
<livewire:dashboard.server-metrics-chart :server="$server"
|
||||
:key="'dashboard-server-metrics-'.$server->uuid" />
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
<div class="flex min-w-0 flex-col gap-4">
|
||||
@if ($hasActiveDeployments)
|
||||
<div
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="border-b border-neutral-200 px-4 py-2.5 dark:border-white/[0.08]">
|
||||
<h3 class="text-[12px]! leading-4! font-semibold! text-black dark:text-fg">
|
||||
Active
|
||||
|
|
@ -52,7 +52,7 @@ class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm d
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="dashboard-deployment-table-grid hidden items-center gap-4 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 md:grid dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="dashboard-deployment-table-grid hidden items-center gap-4 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 md:grid dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<span>Application</span>
|
||||
<span>Environment</span>
|
||||
<span>Server</span>
|
||||
|
|
@ -110,7 +110,7 @@ class="dashboard-deployment-table-grid group block border-b border-neutral-200 p
|
|||
|
||||
@if ($hasRecentDeployments)
|
||||
<div
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="border-b border-neutral-200 px-4 py-2.5 dark:border-white/[0.08]">
|
||||
<h3 class="text-[12px]! leading-4! font-semibold! text-black dark:text-fg">
|
||||
Recent
|
||||
|
|
@ -121,7 +121,7 @@ class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm d
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="dashboard-deployment-table-grid hidden items-center gap-4 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 md:grid dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="dashboard-deployment-table-grid hidden items-center gap-4 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 md:grid dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<span>Application</span>
|
||||
<span>Environment</span>
|
||||
<span>Server</span>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class="button button-highlighted">
|
|||
|
||||
<div x-cloak x-show="viewMode === 'grid'" class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($destinations as $destination)
|
||||
<a x-show="matches(@js([$destination->name, $destination->server->name, $destination->getMorphClass() === 'App\\Models\\SwarmDocker' ? 'Docker Swarm' : 'Standalone Docker']))" class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a x-show="matches(@js([$destination->name, $destination->server->name, $destination->getMorphClass() === 'App\\Models\\SwarmDocker' ? 'Docker Swarm' : 'Standalone Docker']))" class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}
|
||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
|
||||
<div class="flex items-start gap-3">
|
||||
|
|
@ -90,8 +90,8 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
<div x-show="viewMode === 'table'" class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.7fr)_10rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
<div x-show="viewMode === 'table'" class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.7fr)_10rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Destination</div><div>Server</div><div>Type</div>
|
||||
</div>
|
||||
@foreach ($destinations as $destination)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class="h-8! w-full rounded-lg! border-neutral-200! bg-white! py-0! pr-3! pl-8! t
|
|||
|
||||
<div class="overflow-x-auto">
|
||||
<div
|
||||
class="grid min-w-[680px] grid-cols-[minmax(10rem,.8fr)_minmax(10rem,.8fr)_minmax(12rem,1fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[680px] grid-cols-[minmax(10rem,.8fr)_minmax(10rem,.8fr)_minmax(12rem,1fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Project</div>
|
||||
<div>Environment</div>
|
||||
<div>Resource</div>
|
||||
|
|
|
|||
|
|
@ -751,7 +751,7 @@ class="relative flex min-h-full items-start justify-center p-4 sm:items-center">
|
|||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="{{ $createModalShell }}"
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-modal)">
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-dropdown)">
|
||||
<header class="flex-nowrap!">
|
||||
<h3 class="min-w-0 flex-1 truncate">New project</h3>
|
||||
<button type="button" @click="modalOpen=false" class="{{ $createModalClose }}">
|
||||
|
|
@ -794,7 +794,7 @@ class="relative flex min-h-full items-start justify-center p-4 sm:items-center">
|
|||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="{{ $createModalShell }}"
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-modal)">
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-dropdown)">
|
||||
<header class="flex-nowrap!">
|
||||
<h3 class="min-w-0 flex-1 truncate">New team</h3>
|
||||
<button type="button" @click="modalOpen=false" class="{{ $createModalClose }}">
|
||||
|
|
@ -837,7 +837,7 @@ class="relative flex min-h-full items-start justify-center p-4 sm:items-center">
|
|||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="{{ $createModalShell }}"
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-modal)">
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-dropdown)">
|
||||
<header class="flex-nowrap!">
|
||||
<h3 class="min-w-0 flex-1 truncate">New S3 storage</h3>
|
||||
<button type="button" @click="modalOpen=false" class="{{ $createModalClose }}">
|
||||
|
|
@ -880,7 +880,7 @@ class="relative flex min-h-full items-start justify-center p-4 sm:items-center">
|
|||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="{{ $createModalShell }}"
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-modal)">
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-dropdown)">
|
||||
<header class="flex-nowrap!">
|
||||
<h3 class="min-w-0 flex-1 truncate">New private key</h3>
|
||||
<button type="button" @click="modalOpen=false" class="{{ $createModalClose }}">
|
||||
|
|
@ -923,7 +923,7 @@ class="relative flex min-h-full items-start justify-center p-4 sm:items-center">
|
|||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 -translate-y-2 sm:scale-95"
|
||||
class="{{ $createModalShell }}"
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-modal)">
|
||||
style="box-shadow: 0 0 0 1px var(--coollabs-hairline), var(--shadow-dropdown)">
|
||||
<header class="flex-nowrap!">
|
||||
<h3 class="min-w-0 flex-1 truncate">New GitHub app</h3>
|
||||
<button type="button" @click="modalOpen=false" class="{{ $createModalClose }}">
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
@click="setTheme('{{ $option['value'] }}')"
|
||||
@keydown.enter.prevent="setTheme('{{ $option['value'] }}')"
|
||||
@endif
|
||||
class="group relative overflow-hidden rounded-[10px] border border-neutral-200 bg-white text-left transition-[border-color,box-shadow] hover:border-neutral-300 hover:shadow-sm dark:border-white/[0.07] dark:bg-white/[0.025] dark:hover:border-white/[0.12]"
|
||||
class="group relative overflow-hidden rounded-[10px] border border-neutral-200 bg-white text-left transition-[border-color,box-shadow] hover:border-neutral-300 hover:shadow-sm dark:border-white/[0.07] dark:bg-white/[0.05] dark:hover:border-white/[0.12]"
|
||||
:class="theme === '{{ $option['value'] }}'
|
||||
? 'ring-1 ring-coollabs/30 border-coollabs/40 dark:ring-warning/30 dark:border-warning/40'
|
||||
: ''">
|
||||
|
|
@ -126,7 +126,7 @@ class="absolute inset-0 z-10 h-full w-full cursor-pointer opacity-0" />
|
|||
['value' => 'centered', 'label' => 'Centered', 'description' => 'Keep content centered at a comfortable maximum width.'],
|
||||
] as $option)
|
||||
<button type="button" @click="setWidth('{{ $option['value'] }}')"
|
||||
class="group overflow-hidden rounded-[10px] border border-neutral-200 bg-white text-left transition-[border-color,box-shadow] hover:border-neutral-300 hover:shadow-sm dark:border-white/[0.07] dark:bg-white/[0.025] dark:hover:border-white/[0.12]"
|
||||
class="group overflow-hidden rounded-[10px] border border-neutral-200 bg-white text-left transition-[border-color,box-shadow] hover:border-neutral-300 hover:shadow-sm dark:border-white/[0.07] dark:bg-white/[0.05] dark:hover:border-white/[0.12]"
|
||||
:class="pageWidth === '{{ $option['value'] }}'
|
||||
? 'ring-1 ring-coollabs/30 border-coollabs/40 dark:ring-warning/30 dark:border-warning/40'
|
||||
: ''">
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ class="flex items-end gap-2">
|
|||
@if (session('status') === 'two-factor-authentication-confirmed'
|
||||
|| session('status') === 'recovery-codes-generated')
|
||||
<div
|
||||
class="grid gap-2 rounded-lg border border-neutral-200 bg-neutral-50 p-4 font-mono text-xs text-neutral-700 sm:grid-cols-2 dark:border-white/[0.07] dark:bg-white/[0.025] dark:text-fg-dim">
|
||||
class="grid gap-2 rounded-lg border border-neutral-200 bg-neutral-50 p-4 font-mono text-xs text-neutral-700 sm:grid-cols-2 dark:border-white/[0.07] dark:bg-white/[0.05] dark:text-fg-dim">
|
||||
@foreach (request()->user()->recoveryCodes() as $code)
|
||||
<div>{{ $code }}</div>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
</div>
|
||||
|
||||
<p
|
||||
class="rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-2.5 text-[12px] text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-dim">
|
||||
class="rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-2.5 text-[12px] text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-dim">
|
||||
A production environment will be created automatically.
|
||||
</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
<livewire:project.shared.configuration-checker :resource="$application" />
|
||||
<livewire:project.application.heading :application="$application" :wire:key="'application-heading-'.$currentRoute" />
|
||||
|
||||
<section class="application-settings-workspace mt-4 w-full max-w-none lg:mt-0">
|
||||
<div class="grid min-w-0 gap-8 xl:grid-cols-[210px_minmax(0,1fr)] xl:gap-8">
|
||||
<section class="application-settings-workspace w-full max-w-none">
|
||||
<div class="grid min-w-0 gap-4 xl:grid-cols-[236px_minmax(0,1fr)] xl:gap-8">
|
||||
<x-application.configuration-sidebar :application="$application" :current-route="$currentRoute" />
|
||||
|
||||
<div class="min-w-0">
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
$domainCount = countDomains($fqdn);
|
||||
}
|
||||
@endphp
|
||||
<div class="flex items-center gap-3 rounded-lg border border-neutral-200 bg-neutral-50/60 px-4 py-3 dark:border-white/[0.07] dark:bg-white/[0.025]">
|
||||
<div class="flex items-center gap-3 rounded-lg border border-neutral-200 bg-neutral-50/60 px-4 py-3 dark:border-white/[0.07] dark:bg-white/[0.05]">
|
||||
<div class="flex min-w-0 flex-1 items-center gap-3">
|
||||
<div class="flex size-9 shrink-0 items-center justify-center rounded-md bg-neutral-200/70 text-neutral-600 dark:bg-white/[0.07] dark:text-fg-dim">
|
||||
<x-reicon name="globe" class="size-4" />
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@
|
|||
@endphp
|
||||
<div>
|
||||
<div class="mb-3 w-full xl:hidden">
|
||||
<div class="flex min-w-0 flex-col items-start gap-2">
|
||||
<h1 class="min-w-0 max-w-full truncate text-[24px]! leading-7! font-semibold! tracking-tight! text-black dark:text-fg">
|
||||
{{-- Identity row: name truncates, status + links stay pinned right. --}}
|
||||
<div class="flex w-full min-w-0 items-center gap-3">
|
||||
<h1 class="min-w-0 flex-1 truncate text-[22px]! leading-7! font-semibold! tracking-tight! text-black dark:text-fg">
|
||||
{{ $application->name }}
|
||||
</h1>
|
||||
<div class="relative flex w-full min-w-0 items-center gap-2">
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<x-status-summary :status="$application->status" />
|
||||
<x-applications.links :application="$application" compact />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
@if (blank($privateKeyId))
|
||||
<div
|
||||
class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-3 py-2.5 ring-1 ring-neutral-200 dark:bg-white/[0.025] dark:ring-white/[0.07]">
|
||||
class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-3 py-2.5 ring-1 ring-neutral-200 dark:bg-white/[0.05] dark:ring-white/[0.07]">
|
||||
<span class="text-[12px] text-neutral-500 dark:text-fg-dim">Connected source</span>
|
||||
<span class="text-[12px] font-medium text-neutral-900 dark:text-fg">
|
||||
{{ data_get($application, 'source.name', 'No source connected') }}
|
||||
|
|
@ -48,7 +48,7 @@ class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-
|
|||
<x-application.settings-section title="Deploy key"
|
||||
description="The SSH key Coolify uses to clone this private repository.">
|
||||
<div
|
||||
class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-3 py-2.5 ring-1 ring-neutral-200 dark:bg-white/[0.025] dark:ring-white/[0.07]">
|
||||
class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-3 py-2.5 ring-1 ring-neutral-200 dark:bg-white/[0.05] dark:ring-white/[0.07]">
|
||||
<span class="text-[12px] text-neutral-500 dark:text-fg-dim">Attached private key</span>
|
||||
<span class="text-[12px] font-medium text-neutral-900 dark:text-fg">{{ $privateKeyName }}</span>
|
||||
</div>
|
||||
|
|
@ -56,7 +56,7 @@ class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-
|
|||
<div class="grid gap-2 sm:grid-cols-2">
|
||||
@forelse ($privateKeys as $key)
|
||||
<button type="button" wire:click="setPrivateKey('{{ $key->id }}')"
|
||||
class="flex min-h-11 items-center rounded-lg border border-neutral-200 bg-white px-3 text-left text-[12px] font-medium transition-colors hover:bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:bg-white/[0.05]">
|
||||
class="flex min-h-11 items-center rounded-lg border border-neutral-200 bg-white px-3 text-left text-[12px] font-medium transition-colors hover:bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:bg-white/[0.05]">
|
||||
{{ $key->name }}
|
||||
</button>
|
||||
@empty
|
||||
|
|
@ -129,7 +129,7 @@ class="size-4 shrink-0 text-coollabs dark:text-warning" />
|
|||
shortConfirmationLabel="Confirmation text" :confirmWithPassword="false">
|
||||
<x-slot:trigger>
|
||||
<button type="button"
|
||||
class="group flex w-full min-h-16 items-center gap-3 rounded-xl border border-neutral-200 bg-white p-3 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:bg-neutral-50 hover:shadow-md focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14] dark:hover:bg-white/[0.05]">
|
||||
class="group flex w-full min-h-16 items-center gap-3 rounded-xl border border-neutral-200 bg-white p-3 text-left shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:bg-neutral-50 hover:shadow-md focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14] dark:hover:bg-white/[0.05]">
|
||||
<div
|
||||
class="flex size-9 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 transition-colors group-hover:border-neutral-300 group-hover:text-neutral-700 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim dark:group-hover:border-white/[0.12] dark:group-hover:text-fg">
|
||||
<x-git-icon class="size-4" :git="$sourceMorph" />
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@
|
|||
class="flex min-h-20 items-center gap-3 rounded-[10px] border p-3 text-left transition-colors"
|
||||
:class="restoreType === 'file'
|
||||
? 'border-coollabs/35 bg-coollabs/[0.06] text-coollabs dark:border-warning/30 dark:bg-warning/[0.08] dark:text-warning'
|
||||
: 'border-neutral-200 bg-white hover:border-neutral-300 dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]'">
|
||||
: 'border-neutral-200 bg-white hover:border-neutral-300 dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]'">
|
||||
<span
|
||||
class="flex size-9 shrink-0 items-center justify-center rounded-lg bg-neutral-100 dark:bg-white/[0.06]">
|
||||
<x-reicon name="file" class="size-4" />
|
||||
|
|
@ -122,7 +122,7 @@ class="flex size-9 shrink-0 items-center justify-center rounded-lg bg-neutral-10
|
|||
class="flex min-h-20 items-center gap-3 rounded-[10px] border p-3 text-left transition-colors"
|
||||
:class="restoreType === 's3'
|
||||
? 'border-coollabs/35 bg-coollabs/[0.06] text-coollabs dark:border-warning/30 dark:bg-warning/[0.08] dark:text-warning'
|
||||
: 'border-neutral-200 bg-white hover:border-neutral-300 dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]'">
|
||||
: 'border-neutral-200 bg-white hover:border-neutral-300 dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]'">
|
||||
<span
|
||||
class="flex size-9 shrink-0 items-center justify-center rounded-lg bg-neutral-100 dark:bg-white/[0.06]">
|
||||
<x-reicon name="storages" class="size-4" />
|
||||
|
|
@ -139,7 +139,7 @@ class="flex size-9 shrink-0 items-center justify-center rounded-lg bg-neutral-10
|
|||
{{-- File Restore Section --}}
|
||||
@can('update', $this->resource)
|
||||
<div x-cloak x-show="restoreType === 'file'"
|
||||
class="mt-4 rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="mt-4 rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<form class="flex flex-col gap-3 sm:flex-row sm:items-end">
|
||||
<div class="min-w-0 flex-1">
|
||||
<x-forms.input label="File path on the server"
|
||||
|
|
@ -158,7 +158,7 @@ class="mt-4 rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:bord
|
|||
</div>
|
||||
|
||||
<form action="{{ route('upload.backup', ['databaseUuid' => $resourceUuid]) }}"
|
||||
class="dropzone rounded-lg! border! border-dashed! border-neutral-300! bg-white! dark:border-white/[0.12]! dark:bg-white/[0.025]!"
|
||||
class="dropzone rounded-lg! border! border-dashed! border-neutral-300! bg-white! dark:border-white/[0.12]! dark:bg-white/[0.05]!"
|
||||
id="my-dropzone" wire:ignore>
|
||||
@csrf
|
||||
</form>
|
||||
|
|
@ -206,7 +206,7 @@ class="mt-4 flex flex-col gap-3 rounded-lg border border-neutral-200 bg-white p-
|
|||
->all();
|
||||
@endphp
|
||||
<div x-cloak x-show="restoreType === 's3'"
|
||||
class="mt-4 rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="mt-4 rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<x-forms.listbox id="s3StorageId" label="S3 storage" :options="$s3StorageOptions"
|
||||
placeholder="Select storage" live />
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class="input h-8! w-full pl-8! text-[13px]!" placeholder="Search backups" />
|
|||
description="Create a schedule to start protecting this database."
|
||||
icon-name="storages" />
|
||||
@else
|
||||
<div x-cloak x-show="search === '' || hasMatches()" class="data-table overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div x-cloak x-show="search === '' || hasMatches()" class="data-table overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="data-table-header scheduled-backups-table-grid">
|
||||
<span>Schedule</span>
|
||||
<span>Latest run</span>
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class="flex size-7.5 items-center justify-center rounded-md transition-colors"
|
|||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<template x-for="project in paginatedProjects" :key="project.uuid">
|
||||
<article
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<a :href="project.href" {{ wireNavigate() }} class="absolute inset-0 rounded-xl"
|
||||
:aria-label="`Open ${project.name}`"></a>
|
||||
<div class="flex items-start gap-3">
|
||||
|
|
@ -151,15 +151,15 @@ class="flex size-7.5 items-center justify-center rounded-md text-neutral-400 tra
|
|||
</article>
|
||||
</template>
|
||||
</div>
|
||||
<x-client-pagination x-show="filteredProjects.length > 0" class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]"
|
||||
<x-client-pagination x-show="filteredProjects.length > 0" class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]"
|
||||
summary="`${rangeStart}-${rangeEnd} of ${filteredProjects.length}`" page-size-model="pageSize"
|
||||
storage-key="coolify.page-size.projects" :options="[12, 24, 48, 96]" />
|
||||
</div>
|
||||
|
||||
<div x-show="viewMode === 'table'"
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div
|
||||
class="projects-table-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="projects-table-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Project</div>
|
||||
<div>Environments</div>
|
||||
<div>Resources</div>
|
||||
|
|
@ -212,7 +212,7 @@ class="flex size-7 items-center justify-center rounded-md text-neutral-400 trans
|
|||
</div>
|
||||
|
||||
<div x-show="filteredProjects.length === 0"
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-reicon name="search" class="mb-3 size-6 text-neutral-300 dark:text-fg-faint" />
|
||||
<p class="text-[13px] font-medium">No matching projects</p>
|
||||
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class="application-settings-section-body grid grid-cols-1 justify-start gap-3 te
|
|||
<article role="button" tabindex="0" :aria-label="'Deploy ' + application.name"
|
||||
@click="setType(application.id)" @keydown.enter.self.prevent="setType(application.id)"
|
||||
@keydown.space.self.prevent="setType(application.id)"
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex min-w-0 items-start gap-3">
|
||||
<div
|
||||
class="flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-neutral-200 bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.04]">
|
||||
|
|
@ -157,7 +157,7 @@ class="mt-auto flex items-center gap-1.5 border-t border-neutral-200 pt-3 dark:b
|
|||
<article role="button" tabindex="0" :aria-label="'Deploy ' + application.name"
|
||||
@click="setType(application.id)" @keydown.enter.self.prevent="setType(application.id)"
|
||||
@keydown.space.self.prevent="setType(application.id)"
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex min-w-0 items-start gap-3">
|
||||
<div
|
||||
class="flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-neutral-200 bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.04]">
|
||||
|
|
@ -206,7 +206,7 @@ class="application-settings-section-body grid grid-cols-1 justify-start gap-3 te
|
|||
<article role="button" tabindex="0" :aria-label="'Deploy ' + database.name"
|
||||
@click="setType(database.id)" @keydown.enter.self.prevent="setType(database.id)"
|
||||
@keydown.space.self.prevent="setType(database.id)"
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<div
|
||||
class="flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-neutral-200 bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.04]">
|
||||
|
|
@ -283,7 +283,7 @@ class="text-[11px] text-neutral-500 dark:text-fg-faint">
|
|||
@click="setType('one-click-service-' + service.id)"
|
||||
@keydown.enter.self.prevent="setType('one-click-service-' + service.id)"
|
||||
@keydown.space.self.prevent="setType('one-click-service-' + service.id)"
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-48 cursor-pointer flex-col rounded-xl border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex min-w-0 items-start gap-3">
|
||||
<div
|
||||
class="flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-neutral-200 bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.04]">
|
||||
|
|
|
|||
|
|
@ -166,9 +166,9 @@ class="flex size-7.5 items-center justify-center rounded-md transition-colors"
|
|||
</div>
|
||||
|
||||
<div x-show="viewMode === 'table'"
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div
|
||||
class="environment-resource-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="environment-resource-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Resource</div>
|
||||
<div class="resource-type">Type</div>
|
||||
<div>Status</div>
|
||||
|
|
@ -271,7 +271,7 @@ class="flex min-h-52 flex-col items-center justify-center px-6 text-center">
|
|||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<template x-for="item in paginatedResources" :key="item.uuid">
|
||||
<article
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<a :href="item.hrefLink"
|
||||
@click="if (item.version === 'v5') { $event.preventDefault(); window.location.assign(item.hrefLink) }"
|
||||
{{ wireNavigate() }} class="absolute inset-0 rounded-xl"
|
||||
|
|
@ -320,7 +320,7 @@ class="relative z-10 max-w-full self-start truncate text-[11px] text-neutral-500
|
|||
</div>
|
||||
|
||||
<div x-show="filteredResources.length === 0"
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-reicon name="search" class="mb-3 size-6 text-neutral-300 dark:text-fg-faint" />
|
||||
<p class="text-[13px] font-medium">No matching resources</p>
|
||||
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">
|
||||
|
|
@ -328,7 +328,7 @@ class="flex min-h-52 flex-col items-center justify-center rounded-xl border bord
|
|||
</p>
|
||||
</div>
|
||||
<x-client-pagination x-show="filteredResources.length > 0"
|
||||
class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]"
|
||||
class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]"
|
||||
summary="filteredResources.length === 0 ? '0 resources' : `${rangeStart}-${rangeEnd} of ${filteredResources.length}`"
|
||||
page-size-model="pageSize" storage-key="coolify.page-size.environment-resources" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -144,10 +144,10 @@ class="flex size-7.5 items-center justify-center rounded-md transition-colors"
|
|||
|
||||
<div :class="viewMode === 'grid'
|
||||
? 'grid grid-cols-1 gap-3 sm:grid-cols-2'
|
||||
: 'overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]'">
|
||||
: 'overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]'">
|
||||
@if ($applications->isNotEmpty() || $databases->isNotEmpty())
|
||||
<div x-cloak x-show="viewMode === 'table'"
|
||||
class="grid min-w-[48rem] grid-cols-[minmax(14rem,1fr)_minmax(12rem,1fr)_12rem_5rem] gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[48rem] grid-cols-[minmax(14rem,1fr)_minmax(12rem,1fr)_12rem_5rem] gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Resource</div>
|
||||
<div>Image</div>
|
||||
<div class="justify-self-start">Status</div>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class="flex min-h-0 flex-col gap-3">
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="flex flex-col items-stretch gap-2 rounded-lg border border-neutral-200 bg-neutral-50 p-1 sm:flex-row sm:flex-wrap sm:items-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="flex flex-col items-stretch gap-2 rounded-lg border border-neutral-200 bg-neutral-50 p-1 sm:flex-row sm:flex-wrap sm:items-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-forms.checkbox label="Escape special characters in labels"
|
||||
helper="By default, $ (and other characters) is escaped. A $ in a label is saved as $$. Turn this off to use environment variables inside labels."
|
||||
id="isContainerLabelEscapeEnabled" instantSave />
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ class="terminal-session-target-trigger flex h-8 max-w-[34rem] min-w-48 items-cen
|
|||
</svg>
|
||||
</button>
|
||||
<div x-cloak x-show="containerOpen" x-transition.origin.top.left
|
||||
class="terminal-target-picker terminal-target-list absolute top-11 left-0 z-50 max-h-72 w-80 overflow-y-auto rounded-lg border p-1 shadow-[0_18px_50px_rgba(0,0,0,0.35)]">
|
||||
class="terminal-target-picker terminal-target-list absolute top-11 left-0 z-50 max-h-72 w-80 overflow-y-auto rounded-lg border p-1 shadow-[var(--shadow-dropdown)]">
|
||||
<template x-for="option in containerOptions" :key="option.value">
|
||||
<button type="button"
|
||||
class="flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-[11px] text-white/65 transition-colors hover:bg-white/[0.07] hover:text-white"
|
||||
|
|
@ -180,7 +180,7 @@ class="size-3 shrink-0 text-[#fcd452]" viewBox="0 0 12 12"
|
|||
@if ($type !== 'server' && $containers->count() > 1)
|
||||
<div x-cloak x-show="!targetChosen" data-terminal-target-picker="launcher"
|
||||
class="absolute inset-0 z-20 flex items-start justify-start p-6 sm:p-10">
|
||||
<div class="terminal-target-picker w-full max-w-md rounded-lg border p-2 shadow-[0_18px_50px_rgba(0,0,0,0.28)]">
|
||||
<div class="terminal-target-picker w-full max-w-md rounded-lg border p-2 shadow-[var(--shadow-dropdown)]">
|
||||
<div class="px-2 pt-1 pb-2">
|
||||
<div class="text-sm font-semibold text-white/80">Start a terminal session</div>
|
||||
<div class="mt-0.5 text-[11px] text-white/45">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
@if ($executionCount > 0)
|
||||
<div class="data-table w-full overflow-x-auto">
|
||||
<div
|
||||
class="data-table-header volume-backup-executions-grid border-b border-neutral-200 bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="data-table-header volume-backup-executions-grid border-b border-neutral-200 bg-neutral-50 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<span>Status</span>
|
||||
<span>Archive</span>
|
||||
<span>Time</span>
|
||||
|
|
@ -129,7 +129,7 @@ class="icon-button shrink-0 text-red-500 hover:text-red-600 dark:text-red-400 da
|
|||
|
||||
@if ($execution->message)
|
||||
<pre
|
||||
class="volume-backup-execution-message col-span-6 mt-2 max-h-32 overflow-auto rounded-lg border border-neutral-200 bg-neutral-50 p-2 text-[11px] whitespace-pre-wrap text-neutral-600 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-dim">{{ $execution->message }}</pre>
|
||||
class="volume-backup-execution-message col-span-6 mt-2 max-h-32 overflow-auto rounded-lg border border-neutral-200 bg-neutral-50 p-2 text-[11px] whitespace-pre-wrap text-neutral-600 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-dim">{{ $execution->message }}</pre>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
</x-slot:actions>
|
||||
|
||||
<div class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-3 py-2.5 ring-1 ring-neutral-200 dark:bg-white/[0.025] dark:ring-white/[0.07]">
|
||||
<div class="mb-4 flex items-center justify-between gap-3 rounded-lg bg-neutral-50 px-3 py-2.5 ring-1 ring-neutral-200 dark:bg-white/[0.05] dark:ring-white/[0.07]">
|
||||
<span class="text-[12px] text-neutral-500 dark:text-fg-dim">
|
||||
{{ $backup?->targetType() ?? ($storage instanceof \App\Models\LocalFileVolume ? 'Directory' : 'Volume') }}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class="flex size-7.5 items-center justify-center rounded-md transition-colors"
|
|||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<template x-for="environment in paginatedEnvironments" :key="environment.uuid">
|
||||
<article
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<a :href="environment.href" {{ wireNavigate() }} class="absolute inset-0 rounded-xl"
|
||||
:aria-label="`Open ${environment.name}`"></a>
|
||||
|
||||
|
|
@ -165,15 +165,15 @@ class="flex size-7.5 items-center justify-center rounded-md text-neutral-400 tra
|
|||
</article>
|
||||
</template>
|
||||
</div>
|
||||
<x-client-pagination x-show="filteredEnvironments.length > 0" class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]"
|
||||
<x-client-pagination x-show="filteredEnvironments.length > 0" class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]"
|
||||
summary="`${rangeStart}-${rangeEnd} of ${filteredEnvironments.length}`" page-size-model="pageSize"
|
||||
storage-key="coolify.page-size.project-environments" :options="[12, 24, 48, 96]" />
|
||||
</div>
|
||||
|
||||
<div x-show="viewMode === 'table'"
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div
|
||||
class="environments-table-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="environments-table-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Environment</div>
|
||||
<div class="environment-resource-count">Resources</div>
|
||||
<div class="environment-description">Description</div>
|
||||
|
|
@ -222,7 +222,7 @@ class="flex size-7 items-center justify-center rounded-md text-neutral-400 trans
|
|||
</div>
|
||||
|
||||
<div x-show="filteredEnvironments.length === 0"
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-reicon name="search" class="mb-3 size-6 text-neutral-300 dark:text-fg-faint" />
|
||||
<p class="text-[13px] font-medium">No matching environments</p>
|
||||
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class="button button-highlighted">
|
|||
icon-name="file-content" size="sm" />
|
||||
@else
|
||||
<div>
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_12rem_1.75rem] items-center gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[13px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_12rem_1.75rem] items-center gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[13px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div class="pl-11">Script</div>
|
||||
<div>Last updated</div>
|
||||
<div class="w-7"></div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
@endif
|
||||
|
||||
<div
|
||||
class="rounded-lg border border-neutral-200 bg-neutral-50 p-3 text-[11px] leading-5 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-dim">
|
||||
class="rounded-lg border border-neutral-200 bg-neutral-50 p-3 text-[11px] leading-5 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-dim">
|
||||
Create the token in the
|
||||
<a :href="providerConsoleUrl"
|
||||
target="_blank" class="font-medium text-coollabs hover:underline dark:text-warning">
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class="button button-highlighted">
|
|||
description="Add a provider token to provision new cloud servers." icon-name="keys" size="sm" />
|
||||
@else
|
||||
<div>
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_8rem_1.75rem] items-center gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[13px] font-medium text-neutral-500 sm:grid-cols-[minmax(0,1fr)_8rem_minmax(0,1fr)_1.75rem] dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_8rem_1.75rem] items-center gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[13px] font-medium text-neutral-500 sm:grid-cols-[minmax(0,1fr)_8rem_minmax(0,1fr)_1.75rem] dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div class="pl-11">Token</div>
|
||||
<div class="text-center">Provider</div>
|
||||
<div class="hidden sm:block">Description</div>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class="listbox-option justify-start! gap-2.5!" role="menuitem">
|
|||
icon-name="keys" />
|
||||
@else
|
||||
<div>
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_7rem_1.75rem] items-center gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[13px] font-medium text-neutral-500 sm:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)_7rem_1.75rem] dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_7rem_1.75rem] items-center gap-3 border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[13px] font-medium text-neutral-500 sm:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)_7rem_1.75rem] dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div class="pl-11">Private key</div>
|
||||
<div class="hidden sm:block">Description</div>
|
||||
<div class="text-center">Status</div>
|
||||
|
|
@ -115,7 +115,7 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
title="You do not have permission to view this private key">
|
||||
<div class="flex items-start gap-3">
|
||||
<div
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-white text-neutral-400 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-white text-neutral-400 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<x-reicon name="keys" class="size-4" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<div class="application-settings-section-body is-flush">
|
||||
<div class="grid grid-cols-1 gap-3 p-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<a href="{{ route('server.create.type', ['type' => 'manual']) }}"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}>
|
||||
<div class="flex items-start">
|
||||
<span
|
||||
|
|
@ -52,7 +52,7 @@ class="flex size-8 items-center justify-center rounded-lg border border-neutral-
|
|||
<div class="application-settings-section-body is-flush">
|
||||
<div class="grid grid-cols-1 gap-3 p-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<a href="{{ route('server.create.type', ['type' => 'hetzner']) }}"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}>
|
||||
<div class="flex items-start">
|
||||
<img src="{{ asset('svgs/hetzner.svg') }}" alt="Hetzner" class="size-8">
|
||||
|
|
@ -66,7 +66,7 @@ class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-whit
|
|||
</a>
|
||||
|
||||
<a href="{{ route('server.create.type', ['type' => 'vultr']) }}"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}>
|
||||
<div class="flex items-start">
|
||||
<img src="https://www.vultr.com/media/logo_ondark.svg" alt="Vultr"
|
||||
|
|
@ -81,7 +81,7 @@ class="h-8 w-20 object-contain object-left">
|
|||
</a>
|
||||
|
||||
<a href="{{ route('server.create.type', ['type' => 'digital-ocean']) }}"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}>
|
||||
<div class="flex items-start">
|
||||
<x-digital-ocean-icon class="size-8" />
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
|||
<a x-cloak
|
||||
x-show="filteredServers.some(server => server.uuid === @js($server->uuid))"
|
||||
href="{{ $serverRow['href'] }}" {{ wireNavigate() }}
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
@if ($server->isMetricsEnabled())
|
||||
<livewire:dashboard.server-metrics-chart :server="$server"
|
||||
:key="'server-index-metrics-'.$server->uuid" />
|
||||
|
|
@ -170,9 +170,9 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
</div>
|
||||
|
||||
<div x-show="viewMode === 'table'"
|
||||
class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div
|
||||
class="grid min-w-[480px] grid-cols-[minmax(0,1fr)_9.5rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[480px] grid-cols-[minmax(0,1fr)_9.5rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Server</div>
|
||||
<div>Status</div>
|
||||
</div>
|
||||
|
|
@ -205,7 +205,7 @@ class="ml-auto flex size-6 shrink-0 items-center justify-center rounded-md"
|
|||
</div>
|
||||
|
||||
<div x-show="filteredServers.length === 0"
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-reicon name="search" class="mb-3 size-6 text-neutral-300 dark:text-fg-faint" />
|
||||
<p class="text-[13px] font-medium">No matching servers</p>
|
||||
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">Try a different search.</p>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
<div class="flex h-full min-h-0 flex-col gap-4 overflow-y-auto scrollbar">
|
||||
@if ($ask)
|
||||
<div
|
||||
class="rounded-[10px] border border-neutral-200 bg-neutral-50 px-4 py-3 text-[13px] leading-5 text-neutral-600 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-dim">
|
||||
class="rounded-[10px] border border-neutral-200 bg-neutral-50 px-4 py-3 text-[13px] leading-5 text-neutral-600 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-dim">
|
||||
This will revalidate the server, install or update Docker Engine, Docker Compose, and related
|
||||
configuration. Docker Engine will restart, so running containers may be briefly unreachable.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($project->environments as $environment)
|
||||
<a x-show="matches(@js([$environment->name, $environment->description, $project->name]))"
|
||||
class="group flex min-h-24 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-24 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.environment.show', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid]) }}" {{ wireNavigate() }}>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim"><x-reicon name="layers" class="size-4" /></div>
|
||||
|
|
@ -46,7 +46,7 @@ class="group flex min-h-24 flex-col rounded-xl border border-neutral-200 bg-whit
|
|||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="viewMode === 'list'" class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div x-show="viewMode === 'list'" class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
@foreach ($projects as $project)
|
||||
@foreach ($project->environments as $environment)
|
||||
<a x-show="matches(@js([$environment->name, $environment->description, $project->name]))"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<div class="w-full">
|
||||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.team.index') }}" {{ wireNavigate() }}>
|
||||
<div
|
||||
class="flex size-8 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
|
|
@ -21,7 +21,7 @@ class="flex size-8 items-center justify-center rounded-lg border border-neutral-
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.project.index') }}" {{ wireNavigate() }}>
|
||||
<div
|
||||
class="flex size-8 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
|
|
@ -35,7 +35,7 @@ class="flex size-8 items-center justify-center rounded-lg border border-neutral-
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.environment.index') }}" {{ wireNavigate() }}>
|
||||
<div
|
||||
class="flex size-8 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
|
|
@ -49,7 +49,7 @@ class="flex size-8 items-center justify-center rounded-lg border border-neutral-
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a class="group flex min-h-32 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.server.index') }}" {{ wireNavigate() }}>
|
||||
<div
|
||||
class="flex size-8 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<div x-cloak x-show="viewMode === 'grid'" class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($projects as $project)
|
||||
<a x-show="matches(@js([$project->name, $project->description]))"
|
||||
class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.project.show', ['project_uuid' => $project->uuid]) }}" {{ wireNavigate() }}>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
|
|
@ -43,7 +43,7 @@ class="h-full w-full rounded-lg object-cover">
|
|||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="viewMode === 'list'" class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div x-show="viewMode === 'list'" class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
@foreach ($projects as $project)
|
||||
<a x-show="matches(@js([$project->name, $project->description]))"
|
||||
href="{{ route('shared-variables.project.show', ['project_uuid' => $project->uuid]) }}" {{ wireNavigate() }}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<div x-cloak x-show="viewMode === 'grid'" class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($servers as $server)
|
||||
<a x-show="matches(@js([$server->name, $server->description, $server->ip]))"
|
||||
class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
href="{{ route('shared-variables.server.show', ['server_uuid' => $server->uuid]) }}" {{ wireNavigate() }}>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim"><x-reicon name="servers" class="size-4" /></div>
|
||||
|
|
@ -29,7 +29,7 @@ class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-whit
|
|||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="viewMode === 'list'" class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div x-show="viewMode === 'list'" class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
@foreach ($servers as $server)
|
||||
<a x-show="matches(@js([$server->name, $server->description, $server->ip]))"
|
||||
href="{{ route('shared-variables.server.show', ['server_uuid' => $server->uuid]) }}" {{ wireNavigate() }}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div x-show="filteredItems.length === 0" class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div x-show="filteredItems.length === 0" class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-reicon name="search" class="mb-3 size-6 text-neutral-300 dark:text-fg-faint" />
|
||||
<p class="text-[13px] font-medium">No matching {{ $label }}</p>
|
||||
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">Try a different search.</p>
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ class="rounded-lg border border-red-300 bg-red-50 p-4 ring-1 ring-inset ring-red
|
|||
@endif
|
||||
|
||||
<div
|
||||
class="rounded-lg border border-neutral-200 bg-neutral-50 p-3 text-[12px] leading-5 text-neutral-600 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-dim">
|
||||
class="rounded-lg border border-neutral-200 bg-neutral-50 p-3 text-[12px] leading-5 text-neutral-600 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-dim">
|
||||
<p class="font-medium text-black dark:text-fg">Mandatory permissions</p>
|
||||
<p class="mt-1">Contents: read · Metadata: read · Email: read</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class="h-8! w-full rounded-lg! border-neutral-200! bg-white! py-0! pr-3! pl-8! t
|
|||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<div
|
||||
class="grid min-w-[680px] grid-cols-[minmax(10rem,.8fr)_minmax(10rem,.8fr)_minmax(12rem,1fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[680px] grid-cols-[minmax(10rem,.8fr)_minmax(10rem,.8fr)_minmax(12rem,1fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Project</div>
|
||||
<div>Environment</div>
|
||||
<div>Resource</div>
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class="h-8! w-full rounded-lg! border-neutral-200! bg-white! py-0! pr-3! pl-8! t
|
|||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<div
|
||||
class="grid min-w-[680px] grid-cols-[minmax(10rem,.8fr)_minmax(10rem,.8fr)_minmax(12rem,1fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[680px] grid-cols-[minmax(10rem,.8fr)_minmax(10rem,.8fr)_minmax(12rem,1fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Project</div>
|
||||
<div>Environment</div>
|
||||
<div>Resource</div>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class="button button-highlighted">
|
|||
<div x-cloak x-show="viewMode === 'grid'" class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($s3 as $storage)
|
||||
<a x-show="matches(@js([$storage->name, $storage->description ?: 'S3-compatible storage', $storage->is_usable ? 'Connected' : 'Not usable']))" {{ wireNavigate() }} href="/storages/{{ $storage->uuid }}"
|
||||
class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex items-start gap-3">
|
||||
<div
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
|
|
@ -74,8 +74,8 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
<div x-show="viewMode === 'table'" class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.8fr)_9rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint"><div>Storage</div><div>Description</div><div>Status</div></div>
|
||||
<div x-show="viewMode === 'table'" class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.8fr)_9rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint"><div>Storage</div><div>Description</div><div>Status</div></div>
|
||||
@foreach ($s3 as $storage)
|
||||
<a x-show="matches(@js([$storage->name, $storage->description ?: 'S3-compatible storage', $storage->is_usable ? 'Connected' : 'Not usable']))" {{ wireNavigate() }} href="/storages/{{ $storage->uuid }}" class="grid min-h-14 min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.8fr)_9rem] items-center border-b border-neutral-200 px-4 py-2.5 text-[12px] transition-colors last:border-b-0 hover:bg-neutral-50 hover:no-underline dark:border-white/[0.07] dark:hover:bg-white/[0.025]">
|
||||
<div class="truncate font-semibold text-black dark:text-fg">{{ $storage->name }}</div>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class="h-8! w-full rounded-lg! border-neutral-200! bg-white! py-0! pr-3! pl-8! t
|
|||
|
||||
<div class="overflow-x-auto">
|
||||
<div
|
||||
class="grid min-w-[780px] grid-cols-[minmax(12rem,1fr)_9rem_7rem_minmax(15rem,1.2fr)] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[780px] grid-cols-[minmax(12rem,1fr)_9rem_7rem_minmax(15rem,1.2fr)] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Backup target</div>
|
||||
<div>Frequency</div>
|
||||
<div>Status</div>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class="app-tab h-6! px-2.5!"
|
|||
|
||||
<div class="grid gap-6 lg:grid-cols-[minmax(0,.8fr)_minmax(0,1.2fr)]">
|
||||
<div
|
||||
class="rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="rounded-[10px] border border-neutral-200 bg-neutral-50 p-4 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<p class="text-[11px] font-medium text-neutral-500 dark:text-fg-faint">Base price</p>
|
||||
<div class="mt-2 flex items-end gap-1.5">
|
||||
<span x-show="selected === 'monthly'" x-cloak
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
@else
|
||||
<div class="data-table w-full">
|
||||
<div
|
||||
class="grid grid-cols-[minmax(0,1fr)_minmax(8rem,.55fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid grid-cols-[minmax(0,1fr)_minmax(8rem,.55fr)_8rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<span>Resource</span>
|
||||
<span>Server</span>
|
||||
<span>Status</span>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class="flex size-7.5 items-center justify-center rounded-md transition-colors"
|
|||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<template x-for="tag in paginatedTags" :key="tag.id">
|
||||
<article
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group relative flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<a :href="tag.href" {{ wireNavigate() }} class="absolute inset-0 rounded-xl"
|
||||
:aria-label="`Open ${tag.name}`"></a>
|
||||
|
||||
|
|
@ -121,15 +121,15 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
</article>
|
||||
</template>
|
||||
</div>
|
||||
<x-client-pagination x-show="filteredTags.length > 0" class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]"
|
||||
<x-client-pagination x-show="filteredTags.length > 0" class="mt-3 rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]"
|
||||
summary="`${rangeStart}-${rangeEnd} of ${filteredTags.length}`" page-size-model="pageSize"
|
||||
storage-key="coolify.page-size.tags" :options="[12, 24, 48, 96]" />
|
||||
</div>
|
||||
|
||||
<div x-show="viewMode === 'table'"
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div
|
||||
class="tags-table-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="tags-table-grid border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Tag</div>
|
||||
<div>Resources</div>
|
||||
<div>Applications</div>
|
||||
|
|
@ -161,7 +161,7 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
</div>
|
||||
|
||||
<div x-show="filteredTags.length === 0"
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="flex min-h-52 flex-col items-center justify-center rounded-xl border border-neutral-200 bg-white px-6 text-center dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<x-reicon name="search" class="mb-3 size-6 text-neutral-300 dark:text-fg-faint" />
|
||||
<p class="text-[13px] font-medium">No matching tags</p>
|
||||
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">
|
||||
|
|
@ -250,7 +250,7 @@ function tagsIndex() {
|
|||
<div class="flex flex-col gap-6">
|
||||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-3">
|
||||
<div
|
||||
class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<p class="text-[11px] font-medium text-neutral-500 dark:text-fg-faint">Resources</p>
|
||||
<p class="mt-1 text-[20px] font-semibold tracking-tight text-black dark:text-fg">
|
||||
{{ $resourceCount }}
|
||||
|
|
@ -260,7 +260,7 @@ class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08
|
|||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<p class="text-[11px] font-medium text-neutral-500 dark:text-fg-faint">Applications</p>
|
||||
<p class="mt-1 text-[20px] font-semibold tracking-tight text-black dark:text-fg">
|
||||
{{ $applications?->count() ?? 0 }}
|
||||
|
|
@ -270,7 +270,7 @@ class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08
|
|||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<p class="text-[11px] font-medium text-neutral-500 dark:text-fg-faint">Active deployments</p>
|
||||
<p class="mt-1 text-[20px] font-semibold tracking-tight text-black dark:text-fg">
|
||||
{{ collect($deploymentsPerTagPerServer ?? [])->flatten(1)->count() }}
|
||||
|
|
@ -308,7 +308,7 @@ class="rounded-xl border border-neutral-200 bg-white p-3 dark:border-white/[0.08
|
|||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($applications ?? [] as $application)
|
||||
<a {{ wireNavigate() }} href="{{ $application->link() }}"
|
||||
class="group flex min-h-24 flex-col rounded-lg border border-neutral-200 bg-neutral-50/70 p-3 transition-colors hover:border-neutral-300 hover:no-underline dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-24 flex-col rounded-lg border border-neutral-200 bg-neutral-50/70 p-3 transition-colors hover:border-neutral-300 hover:no-underline dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex items-start gap-2.5">
|
||||
<div
|
||||
class="flex size-7 shrink-0 items-center justify-center rounded-md border border-neutral-200 bg-white text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.035] dark:text-fg-dim">
|
||||
|
|
@ -332,7 +332,7 @@ class="truncate text-[12px]! leading-4! font-semibold! text-black dark:text-fg">
|
|||
|
||||
@foreach ($services ?? [] as $service)
|
||||
<a {{ wireNavigate() }} href="{{ $service->link() }}"
|
||||
class="group flex min-h-24 flex-col rounded-lg border border-neutral-200 bg-neutral-50/70 p-3 transition-colors hover:border-neutral-300 hover:no-underline dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]">
|
||||
class="group flex min-h-24 flex-col rounded-lg border border-neutral-200 bg-neutral-50/70 p-3 transition-colors hover:border-neutral-300 hover:no-underline dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]">
|
||||
<div class="flex items-start gap-2.5">
|
||||
<div
|
||||
class="flex size-7 shrink-0 items-center justify-center rounded-md border border-neutral-200 bg-white text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.035] dark:text-fg-dim">
|
||||
|
|
@ -374,7 +374,7 @@ class="truncate text-[12px]! leading-4! font-semibold! text-black dark:text-fg">
|
|||
</div>
|
||||
@else
|
||||
<div
|
||||
class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.55fr)_7rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint">
|
||||
class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.55fr)_7rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
|
||||
<div>Resource</div>
|
||||
<div>Server</div>
|
||||
<div>Status</div>
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ class="terminal-session-target-trigger flex h-8 min-w-0 max-w-sm cursor-pointer
|
|||
</button>
|
||||
|
||||
<div x-cloak x-show="targetOpen" x-transition.origin.top.left
|
||||
class="terminal-target-picker absolute top-11 left-0 z-50 w-80 overflow-hidden rounded-lg border shadow-[0_18px_50px_rgba(0,0,0,0.35)]">
|
||||
class="terminal-target-picker absolute top-11 left-0 z-50 w-80 overflow-hidden rounded-lg border shadow-[var(--shadow-dropdown)]">
|
||||
<div class="border-b border-white/[0.08] p-1.5">
|
||||
<div class="relative">
|
||||
<x-reicon name="search"
|
||||
|
|
@ -287,7 +287,7 @@ class="px-2 py-5 text-center text-[11px] text-white/35">
|
|||
@else
|
||||
<div x-cloak x-show="!targetChosen" data-terminal-target-picker="launcher"
|
||||
class="absolute inset-0 z-20 flex items-start justify-start p-6 sm:p-10">
|
||||
<div class="terminal-target-picker w-full max-w-md overflow-hidden rounded-lg border shadow-[0_18px_50px_rgba(0,0,0,0.28)]">
|
||||
<div class="terminal-target-picker w-full max-w-md overflow-hidden rounded-lg border shadow-[var(--shadow-dropdown)]">
|
||||
<div class="border-b border-white/[0.08] p-2">
|
||||
<div class="px-1 pb-2">
|
||||
<div class="text-sm font-semibold text-white/80">Start a terminal session</div>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class="listbox-option justify-start! gap-2.5!" role="menuitem">
|
|||
<div x-cloak x-show="viewMode === 'grid'" class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
@foreach ($sources as $source)
|
||||
@if ($source->getMorphClass() === 'App\Models\GithubApp')
|
||||
<a x-show="matches(@js([$source->name, 'GitHub', $source->organization, $source->isConnected() ? 'Connected' : 'Setup incomplete']))" class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a x-show="matches(@js([$source->name, 'GitHub', $source->organization, $source->isConnected() ? 'Connected' : 'Setup incomplete']))" class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}
|
||||
href="{{ route('source.github.show', ['github_app_uuid' => data_get($source, 'uuid')]) }}">
|
||||
<div class="flex items-start gap-3">
|
||||
|
|
@ -102,7 +102,7 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
</div>
|
||||
</a>
|
||||
@elseif ($source->getMorphClass() === 'App\Models\GitlabApp')
|
||||
<a x-show="matches(@js([$source->name, 'GitLab', $source->group_name, $source->isConnected() ? 'Connected' : 'Setup incomplete']))" class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.025] dark:hover:border-white/[0.14]"
|
||||
<a x-show="matches(@js([$source->name, 'GitLab', $source->group_name, $source->isConnected() ? 'Connected' : 'Setup incomplete']))" class="group flex min-h-28 flex-col rounded-xl border border-neutral-200 bg-white p-3 shadow-sm transition-all hover:-translate-y-px hover:border-neutral-300 hover:no-underline hover:shadow-md dark:border-white/[0.08] dark:bg-white/[0.05] dark:hover:border-white/[0.14]"
|
||||
{{ wireNavigate() }}
|
||||
href="{{ route('source.gitlab.show', ['gitlab_app_uuid' => data_get($source, 'uuid')]) }}">
|
||||
<div class="flex items-start gap-3">
|
||||
|
|
@ -131,8 +131,8 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg border border
|
|||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
<div x-show="viewMode === 'table'" class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.025]">
|
||||
<div class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.7fr)_9rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.025] dark:text-fg-faint"><div>Source</div><div>Provider</div><div>Status</div></div>
|
||||
<div x-show="viewMode === 'table'" class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
|
||||
<div class="grid min-w-[620px] grid-cols-[minmax(0,1fr)_minmax(10rem,.7fr)_9rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint"><div>Source</div><div>Provider</div><div>Status</div></div>
|
||||
@foreach ($sources as $source)
|
||||
@php
|
||||
$isGithub = $source->getMorphClass() === 'App\\Models\\GithubApp';
|
||||
|
|
|
|||
Loading…
Reference in a new issue