From f0a03eefee9b7bfeb9a453ea181520216692acd7 Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Sun, 5 Apr 2026 14:35:01 +0200 Subject: [PATCH] Update app layout and styles --- src/App.css | 489 ++++++++++++++++++++++++++++++++++---------------- src/index.css | 6 +- 2 files changed, 340 insertions(+), 155 deletions(-) diff --git a/src/App.css b/src/App.css index f90339d..beeab7c 100644 --- a/src/App.css +++ b/src/App.css @@ -1,184 +1,371 @@ -.counter { - font-size: 16px; - padding: 5px 10px; - border-radius: 5px; - color: var(--accent); - background: var(--accent-bg); - border: 2px solid transparent; - transition: border-color 0.3s; - margin-bottom: 24px; +/* ── Layout ─────────────────────────────────────────────────── */ - &:hover { - border-color: var(--accent-border); - } - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -.hero { - position: relative; - - .base, - .framework, - .vite { - inset-inline: 0; - margin: 0 auto; - } - - .base { - width: 170px; - position: relative; - z-index: 0; - } - - .framework, - .vite { - position: absolute; - } - - .framework { - z-index: 1; - top: 34px; - height: 28px; - transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) - scale(1.4); - } - - .vite { - z-index: 0; - top: 107px; - height: 26px; - width: auto; - transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) - scale(0.8); - } -} - -#center { +.app { display: flex; flex-direction: column; - gap: 25px; - place-content: center; - place-items: center; - flex-grow: 1; + min-height: 100svh; +} - @media (max-width: 1024px) { - padding: 32px 20px 24px; - gap: 18px; +/* ── Topbar ─────────────────────────────────────────────────── */ + +.topbar { + position: sticky; + top: 0; + z-index: 10; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.75rem 1.5rem; + background: var(--bg); + border-bottom: 1px solid var(--border); + backdrop-filter: blur(8px); +} + +.topbar-left { + display: flex; + align-items: baseline; + gap: 0.75rem; +} + +.topbar-left h1 { + font-size: 1.1rem; + font-weight: 600; + letter-spacing: -0.02em; + margin: 0; + color: var(--text-h); +} + +.count { + font-size: 0.8rem; + color: var(--text); + opacity: 0.7; +} + +.topbar-right { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.topbar-right input[type="search"] { + padding: 0.4rem 0.75rem; + border: 1px solid var(--border); + border-radius: 6px; + background: var(--code-bg); + color: var(--text-h); + font: inherit; + font-size: 0.875rem; + width: 220px; + outline: none; + transition: border-color 0.15s; + + &:focus { + border-color: var(--accent); } } -#next-steps { - display: flex; - border-top: 1px solid var(--border); - text-align: left; +/* ── Buttons ─────────────────────────────────────────────────── */ - & > div { - flex: 1 1 0; - padding: 32px; - @media (max-width: 1024px) { - padding: 24px 20px; +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.4rem; + padding: 0.4rem 0.75rem; + border: 1px solid var(--border); + border-radius: 6px; + background: var(--code-bg); + color: var(--text-h); + font: inherit; + font-size: 0.875rem; + cursor: pointer; + transition: background 0.15s, border-color 0.15s, opacity 0.15s; + + & svg { + width: 16px; + height: 16px; + } + + &:hover:not(:disabled) { + background: var(--accent-bg); + border-color: var(--accent-border); + } + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } + + &.active { + background: var(--accent-bg); + border-color: var(--accent-border); + color: var(--accent); + } + + &.primary { + background: var(--accent); + border-color: var(--accent); + color: #fff; + font-weight: 500; + + &:hover:not(:disabled) { + opacity: 0.85; + background: var(--accent); + border-color: var(--accent); } } - - .icon { - margin-bottom: 16px; - width: 22px; - height: 22px; - } - - @media (max-width: 1024px) { - flex-direction: column; - text-align: center; - } } -#docs { - border-right: 1px solid var(--border); +/* ── Settings panel ──────────────────────────────────────────── */ - @media (max-width: 1024px) { - border-right: none; - border-bottom: 1px solid var(--border); - } -} - -#next-steps ul { - list-style: none; - padding: 0; +.settings-panel { display: flex; - gap: 8px; - margin: 32px 0 0; + align-items: flex-end; + gap: 1rem; + padding: 1rem 1.5rem; + background: var(--code-bg); + border-bottom: 1px solid var(--border); + flex-wrap: wrap; +} - .logo { - height: 18px; +.settings-fields { + display: flex; + gap: 1rem; + flex: 1; + flex-wrap: wrap; +} + +.field { + display: flex; + flex-direction: column; + gap: 0.3rem; + flex: 1; + min-width: 200px; + + & span { + font-size: 0.75rem; + font-weight: 500; + color: var(--text); + text-transform: uppercase; + letter-spacing: 0.05em; } - a { - color: var(--text-h); - font-size: 16px; + & input { + padding: 0.4rem 0.75rem; + border: 1px solid var(--border); border-radius: 6px; - background: var(--social-bg); - display: flex; - padding: 6px 12px; - align-items: center; - gap: 8px; - text-decoration: none; - transition: box-shadow 0.3s; + background: var(--bg); + color: var(--text-h); + font: inherit; + font-size: 0.875rem; + outline: none; + transition: border-color 0.15s; - &:hover { - box-shadow: var(--shadow); - } - .button-icon { - height: 18px; - width: 18px; - } - } - - @media (max-width: 1024px) { - margin-top: 20px; - flex-wrap: wrap; - justify-content: center; - - li { - flex: 1 1 calc(50% - 8px); - } - - a { - width: 100%; - justify-content: center; - box-sizing: border-box; + &:focus { + border-color: var(--accent); } } } -#spacer { - height: 88px; - border-top: 1px solid var(--border); - @media (max-width: 1024px) { - height: 48px; +/* ── Main content ────────────────────────────────────────────── */ + +main { + flex: 1; + padding: 1.5rem; +} + +/* ── States ──────────────────────────────────────────────────── */ + +.empty-state { + text-align: center; + padding: 4rem 1rem; + color: var(--text); + opacity: 0.6; + font-size: 0.95rem; +} + +.loading { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 4rem 1rem; + color: var(--text); + opacity: 0.6; +} + +.spinner { + width: 18px; + height: 18px; + border: 2px solid var(--border); + border-top-color: var(--accent); + border-radius: 50%; + animation: spin 0.7s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +.error-banner { + padding: 0.75rem 1rem; + border-radius: 8px; + background: oklch(0.95 0.05 27); + border: 1px solid oklch(0.85 0.1 27); + color: oklch(0.4 0.15 27); + font-size: 0.875rem; + margin-bottom: 1rem; + + @media (prefers-color-scheme: dark) { + background: oklch(0.25 0.05 27); + border-color: oklch(0.4 0.1 27); + color: oklch(0.75 0.12 27); } } -.ticks { - position: relative; - width: 100%; +/* ── Entry list ──────────────────────────────────────────────── */ - &::before, - &::after { - content: ''; - position: absolute; - top: -4.5px; - border: 5px solid transparent; +.list { + display: flex; + flex-direction: column; + gap: 0; + border: 1px solid var(--border); + border-radius: 10px; + overflow: hidden; +} + +.entry { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--border); + transition: background 0.1s; + + &:last-child { + border-bottom: none; } + &:hover { + background: var(--accent-bg); + } + + &.dim { + opacity: 0.55; + } +} + +.entry-info { + display: flex; + align-items: center; + gap: 0.6rem; + min-width: 0; + flex-shrink: 0; +} + +.entry-name { + font-size: 0.9rem; + font-weight: 500; + color: var(--text-h); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 240px; +} + +.entry-badges { + display: flex; + align-items: center; + gap: 0.4rem; +} + +.badge { + font-size: 0.7rem; + font-weight: 500; + padding: 0.15rem 0.5rem; + border-radius: 999px; + letter-spacing: 0.03em; + white-space: nowrap; + + &.type-application { + background: oklch(0.92 0.06 260); + color: oklch(0.4 0.15 260); + + @media (prefers-color-scheme: dark) { + background: oklch(0.28 0.06 260); + color: oklch(0.75 0.12 260); + } + } + + &.type-service { + background: oklch(0.92 0.06 145); + color: oklch(0.4 0.15 145); + + @media (prefers-color-scheme: dark) { + background: oklch(0.28 0.06 145); + color: oklch(0.75 0.12 145); + } + } +} + +.status { + display: flex; + align-items: center; + gap: 0.35rem; + font-size: 0.72rem; + color: var(--text); + white-space: nowrap; + &::before { - left: 0; - border-left-color: var(--border); + content: ''; + width: 6px; + height: 6px; + border-radius: 50%; + flex-shrink: 0; } - &::after { - right: 0; - border-right-color: var(--border); + + &.dot-running::before { background: oklch(0.65 0.2 145); } + &.dot-stopped::before { background: oklch(0.65 0.0 0); } + &.dot-starting::before { background: oklch(0.75 0.18 85); animation: pulse 1.2s ease-in-out infinite; } + &.dot-error::before { background: oklch(0.65 0.2 27); } + &.dot-unknown::before { background: oklch(0.7 0.0 0); } +} + +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.4; } +} + +/* ── Domain links ────────────────────────────────────────────── */ + +.entry-domains { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + justify-content: flex-end; +} + +.domain-link { + font-size: 0.85rem; + color: var(--accent); + text-decoration: none; + padding: 0.2rem 0.6rem; + border-radius: 6px; + border: 1px solid var(--accent-border); + background: var(--accent-bg); + white-space: nowrap; + transition: opacity 0.15s; + + &:hover { + opacity: 0.75; } } + +.no-domain { + font-size: 0.8rem; + color: var(--text); + opacity: 0.45; + font-style: italic; +} diff --git a/src/index.css b/src/index.css index 2c84af0..82dc951 100644 --- a/src/index.css +++ b/src/index.css @@ -55,11 +55,9 @@ body { } #root { - width: 1126px; - max-width: 100%; + width: 100%; + max-width: 1200px; margin: 0 auto; - text-align: center; - border-inline: 1px solid var(--border); min-height: 100svh; display: flex; flex-direction: column;