diff --git a/index.html b/index.html index 6ec2cdb..52bad1d 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,18 @@ - + + + + + + Subsonics + + +
diff --git a/package.json b/package.json index 24076cf..14067c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chopin-frontend", - "version": "2.0.0", + "version": "2.1.0", "private": true, "scripts": { "dev": "vite --host --port 8080", diff --git a/src/App.vue b/src/App.vue index 4ce31f3..d481d66 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,10 +1,14 @@ \ No newline at end of file + diff --git a/src/assets/Global.scss b/src/assets/Global.scss index b7cef2e..51c545b 100644 --- a/src/assets/Global.scss +++ b/src/assets/Global.scss @@ -1,10 +1,13 @@ @font-face { font-family: 'Gunship'; src: url("/gunship.ttf"); + font-display: swap; } -[data-theme='dark'] { - +/* Thème sombre : appliqué aussi tant que data-theme n'est pas encore posé (évite un flash blanc) */ +[data-theme='dark'], +:root:not([data-theme]) { + color-scheme: dark; --primary: #111210; --primary-inverse: #FFFFFF; @@ -19,11 +22,14 @@ --text-error: #ff2b2b; --text-success: #00ff00; --text-warning: #FFA500; - - + --text-info: #4db4ff; + + --scrollbar-thumb: color-mix(in srgb, var(--text) 30%, transparent); + --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 55%, transparent); } [data-theme='light'] { + color-scheme: light; --primary: #FFFFFF; --primary-inverse: #111210; @@ -34,25 +40,84 @@ --text: #111210; --text-inverse: #FFFFFF; --text-secondary: #404040; - --text-tertiary: #C5c3c3; - --text-error: #CD034F; - --text-success: #00a900; - --text-warning: #FFA500; + /* Contraste suffisant sur fond clair (l'ancien #C5c3c3 était quasi invisible) */ + --text-tertiary: #6b6b6b; + --text-error: #CD034F; + --text-success: #007a1f; + --text-warning: #a35f00; + --text-info: #0063b1; + + --scrollbar-thumb: color-mix(in srgb, var(--text) 30%, transparent); + --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 55%, transparent); } :root { --main: #CD034F; --main-hover: color-mix(in srgb, var(--main) 90%, black); --main-active: color-mix(in srgb, var(--main) 70%, black); + --main-soft: color-mix(in srgb, var(--main) 16%, transparent); + --main-contrast: #fff; --admin-color: #209AFE; --owner-color: #FFAA32; --mod-color: #0BFF89; + + /* Variables utilisées par des composants mais jamais définies jusqu'ici */ + --text-primary: var(--text); + --text-color: var(--text); + --text-hover: var(--text-secondary); + --border: color-mix(in srgb, var(--quaternary) 45%, transparent); + --background: transparent; + + /* Surfaces */ + --surface-1: var(--secondary); + --surface-2: var(--tertiary); + --surface-3: var(--quaternary); + + /* Rayons */ + --radius-sm: 6px; + --radius: 10px; + --radius-lg: 14px; + --radius-pill: 999px; + + /* Espacements */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 24px; + --space-6: 32px; + + /* Élévation */ + --shadow-sm: 0 1px 3px rgba(0, 0, 0, .25); + --shadow: 0 0 10px rgba(0, 0, 0, .35); + --shadow-lg: 0 10px 30px rgba(0, 0, 0, .45); + + /* Focus clavier : anneau doublé pour rester visible sur fond rose comme sur fond sombre */ + --focus-ring: 0 0 0 2px var(--primary), 0 0 0 4px var(--main); + /* Variante intérieure, pour un élément coupé par un conteneur overflow: hidden */ + --focus-ring-inset: inset 0 0 0 2px var(--main); + + /* Survol / pression d'une ligne de liste (teinte neutre qui suit le thème) */ + --surface-hover: color-mix(in srgb, var(--text) 8%, transparent); + --surface-active: color-mix(in srgb, var(--text) 13%, transparent); + + /* Voile des modales et texte posé sur une image (miniatures) */ + --overlay: rgba(0, 0, 0, .55); + --on-media: #fff; + + /* Mouvement */ + --ease: cubic-bezier(.2, .7, .2, 1); + --dur-fast: .15s; + --dur: .25s; + + --font: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; + --font-mono: ui-monospace, 'Cascadia Mono', 'SFMono-Regular', Menlo, Consolas, monospace; } html, body { margin: 0 !important; - font-family: 'Inter', sans-serif; + font-family: var(--font); min-height: 100vh; min-width: 100vw; margin: 0; @@ -60,10 +125,11 @@ html, body { height: 100%; overflow-x: hidden; background-color: var(--primary); - transition: all 0.2s ease-in-out; + /* Seules les couleurs s'animent au changement de thème (avant : transition: all) */ + transition: background-color var(--dur) ease-in-out, color var(--dur) ease-in-out; color: var(--text); - - + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } #app { @@ -71,64 +137,198 @@ html, body { display: flex; } +/* Les boutons natifs n'héritent pas de la police par défaut */ +button, input, select, textarea { + font-family: inherit; +} + .no-decoration { text-decoration: none !important; -} +} .underline { text-decoration: underline !important; -} +} -h1 { +h1 { font-family: 'Gunship'; font-size: 30px; color: var(--text-color); -} +} a { color: var(--text-secondary) } +a:hover { + color: var(--text); +} + +/* Focus clavier visible partout (la souris ne déclenche pas :focus-visible) */ +:focus-visible { + outline: 2px solid var(--main); + outline-offset: 2px; +} + +::selection { + background-color: color-mix(in srgb, var(--main) 38%, transparent); +} + /*Scrollbar */ ::-webkit-scrollbar { width: 5px; + height: 5px; margin-right: 20px; margin-left: 20px; - } +} + ::-webkit-scrollbar-track { border-radius: 12px; - } +} + ::-webkit-scrollbar-thumb { - background: #ffffff56; + background: var(--scrollbar-thumb); border-radius: 5px; transition: 0.2s; - } +} ::-webkit-scrollbar-thumb:hover { - background: #ffffffa8; - } - + background: var(--scrollbar-thumb-hover); +} + +/* Firefox ne connaît pas ::-webkit-scrollbar */ +@supports not selector(::-webkit-scrollbar) { + * { + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb) transparent; + } +} + .full { width: 100%; } +/* Champs de formulaire */ +input:is([type="text"], [type="search"], [type="url"], [type="password"], [type="number"], [type="email"]), +select, +textarea { + background-color: var(--tertiary); + color: var(--text); + border: none; + border-radius: var(--radius-sm); + padding: 8px 10px; + font-family: var(--font); + font-size: inherit; + /* Contour transparent : invisible normalement, mais rendu en mode contraste élevé */ + outline: 2px solid transparent; + outline-offset: 0; + transition: box-shadow var(--dur-fast) ease, background-color var(--dur-fast) ease; +} + +input:is([type="text"], [type="search"], [type="url"], [type="password"], [type="number"], [type="email"]):focus, +select:focus, +textarea:focus { + box-shadow: var(--focus-ring); +} + +input:is([type="text"], [type="search"], [type="url"], [type="password"], [type="number"], [type="email"]):disabled, +select:disabled, +textarea:disabled { + opacity: .6; + cursor: not-allowed; +} + +input::placeholder, +textarea::placeholder { + color: var(--text-secondary); + opacity: .7; +} + +select { + cursor: pointer; +} + textarea { resize: vertical; - background-color: var(--tertiary); - border: none; - border-radius: 5px; - padding: 5px; - color: var(--text); - font-family: 'Inter', sans-serif; - outline: none; min-height: 4vh; max-height: 15vh; } -textarea:focus { - box-shadow: 0 0 5px var(--main); +/* Champ posé sur une carte --tertiary : on redescend d'un niveau pour garder le contraste */ +.input-inset { + background-color: var(--secondary) !important; } +input[type="checkbox"], +input[type="radio"], +input[type="range"], +progress { + accent-color: var(--main); +} + +input[type="checkbox"], +input[type="radio"] { + cursor: pointer; +} + +/* Utilitaires */ + +/* Bouton sans apparence (ligne de liste, carte cliquable…) : garde le focus visible du navigateur */ +.u-plain-button { + margin: 0; + padding: 0; + border: none; + background: none; + color: inherit; + font: inherit; + text-align: inherit; + cursor: pointer; + -webkit-tap-highlight-color: transparent; +} + +.u-plain-button:disabled { + cursor: not-allowed; +} + +/* Titre de vue (résultats, fichiers…) : même échelle partout */ +.u-view-title { + display: flex; + align-items: center; + gap: 10px; + margin: 0; + font-size: 1.25rem; + font-weight: 700; + line-height: 1.25; + color: var(--text); +} + +.u-view-title > svg { + color: var(--main); +} + +.sr-only { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} + +.u-mono { + font-family: var(--font-mono); + font-variant-numeric: tabular-nums; +} + +.u-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-width: 0; +} @keyframes appear { from { @@ -150,30 +350,6 @@ textarea:focus { } } - -input[type="checkbox"] { - background-color: #FFFFFF !important; -} - -input[type="checkbox"]:checked { - background-color: var(--main-hover) !important; -} - -input[type="checkbox"]:hover { - background-color: var(--main-active) !important; -} - -input[type="text"] { - background-color: var(--tertiary); - border: none; - border-radius: 5px; - padding: 7px; - color: var(--text); - font-family: 'Inter', sans-serif; - outline: none; -} - - @keyframes scroll { 0% { transform: translateX(0); @@ -181,4 +357,29 @@ input[type="text"] { 100% { transform: translateX(var(--scroll-distance)); } -} \ No newline at end of file +} + +@keyframes u-fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes u-spin { + to { transform: rotate(360deg); } +} + +/* Mouvement réduit : on coupe les animations et transitions (notes du splash, marquee, glissements…) */ +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto !important; + } + + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/src/components/Admin/AdminBanner.vue b/src/components/Admin/AdminBanner.vue new file mode 100644 index 0000000..d7cdaaf --- /dev/null +++ b/src/components/Admin/AdminBanner.vue @@ -0,0 +1,52 @@ + + diff --git a/src/components/Admin/AdminCard.vue b/src/components/Admin/AdminCard.vue index f78976e..efced37 100644 --- a/src/components/Admin/AdminCard.vue +++ b/src/components/Admin/AdminCard.vue @@ -1,73 +1,187 @@ - diff --git a/src/components/Admin/AdminConfig.vue b/src/components/Admin/AdminConfig.vue index a1da7fd..f211ca9 100644 --- a/src/components/Admin/AdminConfig.vue +++ b/src/components/Admin/AdminConfig.vue @@ -1,154 +1,111 @@