This commit is contained in:
onysd 2026-07-24 22:46:05 +03:00
parent b443ff0c73
commit 3325e793f9
10 changed files with 76 additions and 121 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -23,8 +23,8 @@
})();
</script>
<script type="module" crossorigin src="/assets/index-ilFwQ32E.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B998Ff2K.css">
<script type="module" crossorigin src="/assets/index-Bdm4PGkp.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DWxQF996.css">
</head>
<body>
<div id="root"></div>

View file

@ -16,7 +16,7 @@ import {
} from "lucide-react";
import { useEffect, useState, type ReactNode } from "react";
import { api } from "../api";
import { LanguageSwitch, useI18n } from "../i18n";
import { useI18n } from "../i18n";
import { type Navigate, type RouteState, routeSubtitle, routeTitle } from "../routing";
import { ThemeSwitch } from "../theme";
import { AppLink } from "./AppLink";
@ -133,7 +133,6 @@ export function Shell({
</div>
<div className="topbar-actions">
<ThemeSwitch />
<LanguageSwitch />
<span className="actor-pill">{t("layout.actor", { actor })}</span>
<button className="btn ghost icon-text" type="button" onClick={logout} title={t("layout.logout")}>
<LogOut size={16} /> {t("layout.logout")}

View file

@ -1564,25 +1564,6 @@ export function useI18n(): I18nContextValue {
return value;
}
export function LanguageSwitch() {
const { lang, setLang, t } = useI18n();
return (
<div className="language-switch" role="group" aria-label="Language">
{(["en", "zh", "ru"] as const).map((item) => (
<button
key={item}
className={lang === item ? "active" : ""}
type="button"
aria-pressed={lang === item}
onClick={() => setLang(item)}
>
{t(`language.${item}`)}
</button>
))}
</div>
);
}
export function translate(lang: Language, key: string, params?: TranslationParams): string {
const value = translations[lang][key] ?? translations.en[key] ?? key;
if (!params) {

View file

@ -2,7 +2,7 @@ import type { FormEvent } from "react";
import { useState } from "react";
import { api, errorMessage } from "../api";
import { Alert } from "../components/ui";
import { LanguageSwitch, useI18n } from "../i18n";
import { useI18n } from "../i18n";
import { ThemeSwitch } from "../theme";
export function LoginPage({ onLogin }: { onLogin: (actor: string) => void }) {
@ -38,7 +38,6 @@ export function LoginPage({ onLogin }: { onLogin: (actor: string) => void }) {
</div>
<div className="login-head-actions">
<ThemeSwitch />
<LanguageSwitch />
<span className="login-chip">{t("app.localAccess")}</span>
</div>
</div>

View file

@ -8,42 +8,43 @@
color-scheme: light;
/* Surfaces */
--bg: #eef1f5;
--bg-accent: #e7ecf1;
--bg: #f7f9fc;
--bg-accent: #eef1f5;
--panel: #ffffff;
--panel-subtle: #f5f8fb;
--panel-strong: #eef2f6;
--surface-soft: #f2f7f6;
--panel-subtle: #f7f9fc;
--panel-strong: #f1f5f9;
--surface-soft: #f2f7fd;
--overlay: rgba(24, 34, 47, 0.42);
--topbar-bg: rgba(255, 255, 255, 0.86);
--topbar-bg: rgba(255, 255, 255, 0.94);
/* Lines */
--line: #e5eaf0;
--line-strong: #d3dce4;
--line: #e2e8f0;
--line-strong: #cbd5e1;
/* Text */
--heading: #253040;
--text: #333f4d;
--text-soft: #45525f;
--muted: #6d7885;
--muted-2: #9aa4b1;
--heading: #101828;
--text: #0f1720;
--text-soft: #344054;
--muted: #64748b;
--muted-2: #94a3b8;
/* Brand */
--brand: #1f7d6f;
--brand-strong: #196155;
--brand-2: #3a6cae;
--brand-tint: #e8f4f0;
--brand-tint-border: #c8e2db;
--brand-tint-text: #235d53;
--brand: #2563eb;
--brand-strong: #1d4ed8;
--brand-2: #38bdf8;
--grad: linear-gradient(135deg, #38bdf8 0%, #2563eb 55%, #1e40af 100%);
--brand-tint: #eaf2fd;
--brand-tint-border: #c7dcf9;
--brand-tint-text: #1e3a8a;
/* Semantic */
--good: #1f8a57;
--good: #167447;
--good-tint: #eaf6ef;
--good-border: #c1e1cf;
--warn: #a86a12;
--warn: #a15c07;
--warn-tint: #fcf4e4;
--warn-border: #e7d09e;
--danger: #c0392b;
--danger: #b42318;
--danger-tint: #fcefec;
--danger-border: #eecac3;
--danger-text: #8f2f27;
@ -67,20 +68,20 @@
--code-border: #2b3a49;
/* Sidebar */
--sidebar: #1c2530;
--sidebar-soft: #26313d;
--sidebar-line: #313c4a;
--sidebar-row: #232d38;
--sidebar-text: #dbe3ec;
--sidebar-muted: #8b98a8;
--sidebar-faint: #7c8a9a;
--sidebar: #08080e;
--sidebar-soft: #12121a;
--sidebar-line: #222228;
--sidebar-row: #17171f;
--sidebar-text: #c6d0dc;
--sidebar-muted: #8fa0b4;
--sidebar-faint: #8492a6;
--sidebar-heading: #ffffff;
/* Effects */
--focus: rgba(31, 125, 111, 0.16);
--shadow: 0 12px 34px rgba(24, 39, 56, 0.1);
--focus: rgba(37, 99, 235, 0.16);
--shadow: 0 28px 70px -36px rgba(5, 5, 8, 0.35);
--shadow-sm: 0 2px 10px rgba(24, 39, 56, 0.05);
--shadow-brand: 0 8px 22px rgba(31, 125, 111, 0.22);
--shadow-brand: 0 8px 22px rgba(37, 99, 235, 0.22);
/* Radii */
--radius-xs: 8px;
@ -110,12 +111,12 @@
--muted: #98a4b1;
--muted-2: #6d7885;
--brand: #37a596;
--brand-strong: #45b6a6;
--brand-2: #6fa8e6;
--brand-tint: #14322d;
--brand-tint-border: #245349;
--brand-tint-text: #7fd3c4;
--brand: #5b9dff;
--brand-strong: #7db4ff;
--brand-2: #7cd1fb;
--brand-tint: #142a4a;
--brand-tint-border: #24466e;
--brand-tint-text: #9dc3f5;
--good: #47c281;
--good-tint: #12301f;
@ -152,10 +153,10 @@
--sidebar-faint: #6f7b88;
--sidebar-heading: #f0f4f8;
--focus: rgba(55, 165, 150, 0.24);
--focus: rgba(91, 157, 255, 0.24);
--shadow: 0 16px 40px rgba(0, 0, 0, 0.46);
--shadow-sm: 0 2px 12px rgba(0, 0, 0, 0.38);
--shadow-brand: 0 8px 22px rgba(55, 165, 150, 0.26);
--shadow-brand: 0 8px 22px rgba(91, 157, 255, 0.26);
}
* {
@ -221,20 +222,11 @@ a {
justify-content: center;
}
.brand-elevated .brand-mark {
box-shadow: var(--shadow-brand);
}
.brand-mark {
display: grid;
width: 34px;
height: 34px;
place-items: center;
color: #ffffff;
background: var(--brand);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: var(--radius-sm);
font-weight: 800;
}
.brand-mark img {
@ -299,7 +291,7 @@ a {
.nav-section.active .nav-section-toggle {
color: var(--sidebar-heading);
background: var(--sidebar-soft);
border-color: var(--sidebar-line);
border-color: #34404d;
}
.nav-section-chevron {
@ -343,7 +335,7 @@ a {
.nav-item.active {
color: var(--sidebar-heading);
background: var(--sidebar-soft);
border-color: var(--sidebar-line);
border-color: #34404d;
}
.nav-item.active .nav-dot {
@ -365,7 +357,7 @@ a {
padding: 0 8px;
color: var(--sidebar-text);
background: var(--sidebar-row);
border: 1px solid var(--sidebar-line);
border: 1px solid #27313c;
border-radius: var(--radius-sm);
}
@ -412,39 +404,6 @@ a {
gap: 8px;
}
.language-switch {
display: inline-flex;
min-height: 30px;
align-items: center;
padding: 2px;
background: var(--panel-subtle);
border: 1px solid var(--line);
border-radius: 999px;
}
.language-switch button {
min-width: 42px;
min-height: 24px;
padding: 0 9px;
color: var(--muted);
background: transparent;
border: 0;
border-radius: 999px;
cursor: pointer;
font-weight: 800;
transition: color 140ms ease, background-color 140ms ease;
}
.language-switch button.active {
color: #ffffff;
background: var(--brand);
}
.language-switch button:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}
.theme-toggle {
display: inline-grid;
width: 34px;