From 6627fd918d382f338bc4ee2667df70dfae604191 Mon Sep 17 00:00:00 2001 From: "Zimin A.N." Date: Mon, 11 May 2026 19:50:41 +0300 Subject: [PATCH 1/2] fix(topbar): revert ThemeSwitch to 3-icon original + shorten create button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User explicitly: "ThemeSwitch не трогай". Реверт my 2-button Earth|Dark переделку обратно на 3-icon Sun/Moon/Monitor segmented control (по original 3bfa7ca). Также: - schema.action.create RU: "Создать справочник" → "Создать" - schema.action.create EN: "Create dictionary" → "Create" (per prototype catalog button — короче чтобы не растягивать toolbar) --- .../src/components/layout/ThemeSwitch.tsx | 40 +++++++++---------- ordinis-admin-ui/src/i18n.ts | 4 +- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/ordinis-admin-ui/src/components/layout/ThemeSwitch.tsx b/ordinis-admin-ui/src/components/layout/ThemeSwitch.tsx index da8465d..65158cf 100644 --- a/ordinis-admin-ui/src/components/layout/ThemeSwitch.tsx +++ b/ordinis-admin-ui/src/components/layout/ThemeSwitch.tsx @@ -1,42 +1,37 @@ import { useTranslation } from 'react-i18next' +import { Monitor, Moon, Sun } from 'lucide-react' import { useTheme, type ThemePreference } from '@/stores/ThemeProvider' import { cn } from '@/lib/utils' /** - * Theme switch per redesign prototype — 2-button segmented control с text - * labels "Earth | Dark". Filled accent-bg на active. + * Tri-state theme switch: Light / Dark / System. * - *

Прошлый tri-state (Light/Dark/System icons) был noise — "system" preference - * редко используется явно, мало кто понимает Monitor icon. Простой 2-button - * `Earth / Dark` toggle — точно повторяет prototype и улучшает discoverability. + *

Segmented control с тремя иконками. Активный — `--color-accent` + * background + `--color-on-accent` foreground. Click меняет `preference` + * в {@link ThemeProvider}, который пишет в localStorage и переключает + * `data-theme` на html. * - *

Internally "Earth" maps на `light` preference (Earthy palette default). - * "System" preference больше не выставляется через UI; localStorage value - * остаётся валидным (ThemeProvider может read), но новые users получают - * explicit light/dark choice. + *

System icon показывает «follow OS» — auto-update при OS theme change. */ export function ThemeSwitch() { const { t } = useTranslation() const { preference, setPreference } = useTheme() - // Treat 'system' как 'light' для UI — переключение всё равно flatten'ит - // preference на explicit choice. - const activeId: Exclude = - preference === 'dark' ? 'dark' : 'light' - - const items: { id: Exclude; label: string }[] = [ - { id: 'light', label: t('theme.earth', { defaultValue: 'Earth' }) }, - { id: 'dark', label: t('theme.dark', { defaultValue: 'Dark' }) }, + const items: { id: ThemePreference; label: string; icon: typeof Sun }[] = [ + { id: 'light', label: t('theme.light'), icon: Sun }, + { id: 'dark', label: t('theme.dark'), icon: Moon }, + { id: 'system', label: t('theme.system'), icon: Monitor }, ] return (

{items.map((item) => { - const active = activeId === item.id + const Icon = item.icon + const active = preference === item.id return ( ) })} diff --git a/ordinis-admin-ui/src/i18n.ts b/ordinis-admin-ui/src/i18n.ts index f0d83f9..38ba474 100644 --- a/ordinis-admin-ui/src/i18n.ts +++ b/ordinis-admin-ui/src/i18n.ts @@ -338,7 +338,7 @@ i18n 'scope.PUBLIC': 'PUBLIC — публичный', 'scope.INTERNAL': 'INTERNAL — внутренний', 'scope.RESTRICTED': 'RESTRICTED — ограниченный', - 'schema.action.create': 'Создать справочник', + 'schema.action.create': 'Создать', 'schema.action.edit': 'Изменить справочник', 'schema.action.editSchema': 'Схема', 'schema.tabs.metadata': 'Метаданные', @@ -844,7 +844,7 @@ i18n 'scope.PUBLIC': 'PUBLIC', 'scope.INTERNAL': 'INTERNAL', 'scope.RESTRICTED': 'RESTRICTED', - 'schema.action.create': 'Create dictionary', + 'schema.action.create': 'Create', 'schema.action.edit': 'Edit dictionary', 'schema.action.editSchema': 'Schema', 'schema.tabs.metadata': 'Metadata', From 38f7dcee3ec7ba645ecbbaa8e278fb060f2b7c6c Mon Sep 17 00:00:00 2001 From: "Zimin A.N." Date: Mon, 11 May 2026 19:55:52 +0300 Subject: [PATCH 2/2] fix(topbar): restore full right cluster per user preference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User explicitly: "Руководство · dev · 19a3731b · ☀️🌙🖥 · RU EN · zimin.an · ↩ это оставь". Revert MR !81 cluster-minimization — diagnostic info нужна для prod debugging. Restored: - Docs link (/docs/) — opens admin docs portal - VersionBadge (channel + commit short SHA) — shows local/dev/v1.x.x · hash - LanguageSwitch (dual RU | EN radio) — keeps both visible vs single-toggle - (ThemeSwitch + AuthBadge остаются как были) --- .../src/components/layout/TopBar.tsx | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/ordinis-admin-ui/src/components/layout/TopBar.tsx b/ordinis-admin-ui/src/components/layout/TopBar.tsx index 7a2f3ef..4bfabb2 100644 --- a/ordinis-admin-ui/src/components/layout/TopBar.tsx +++ b/ordinis-admin-ui/src/components/layout/TopBar.tsx @@ -1,12 +1,19 @@ import { useTranslation } from 'react-i18next' import { Link, useLocation, useNavigate } from '@tanstack/react-router' import { useDictionaryDetail } from '@/api/queries' +import { LanguageSwitch } from '@/ui' import { AuthBadge } from '@/auth/AuthBadge' import { ThemeSwitch } from '@/components/layout/ThemeSwitch' +import { VersionBadge } from '@/components/version/VersionBadge' import { SearchInput } from '@/ui/components/search-input' import { Menu } from 'lucide-react' import { useEffect, useRef, useState } from 'react' +const LANG_OPTIONS = [ + { id: 'ru-RU', label: 'RU' }, + { id: 'en-US', label: 'EN' }, +] + /** * TopBar — sticky header (h=56) per handoff design. * @@ -17,7 +24,7 @@ import { useEffect, useRef, useState } from 'react' * - Right: VersionBadge · ThemeSwitch · LanguageSwitch · Docs · AuthBadge */ export function TopBar({ onMenuClick }: { onMenuClick?: () => void }) { - const { t } = useTranslation() + const { t, i18n } = useTranslation() const navigate = useNavigate() const [searchValue, setSearchValue] = useState('') const inputRef = useRef(null) @@ -115,42 +122,34 @@ export function TopBar({ onMenuClick }: { onMenuClick?: () => void }) { /> - {/* Right cluster — minimal per redesign prototype: - * - Lang toggle (single label, click flips) - * - Theme switch (Earth / Dark) - * - AuthBadge (sign-in / user avatar) - * Docs link и VersionBadge перенесены в sidebar footer — diagnostic info, - * не critical UX. */} + {/* Right cluster — user prefers full set: Docs link + VersionBadge + + * ThemeSwitch + LanguageSwitch + AuthBadge (logged-in avatar/sign-in). + * User explicitly: "Руководство · dev · {commit} · theme · RU EN · + * zimin.an · logout это оставь". */}
- + + {t('nav.docs')} + + + + + i18n.changeLanguage(id)} + />
) } -/** - * LanguageToggle — single-button toggle per redesign prototype (показывает - * текущий язык как label, click переключает на следующий). Замена tri/dual - * radio LanguageSwitch который занимал ~80px горизонтально. - */ -function LanguageToggle() { - const { i18n } = useTranslation() - const cur = i18n.language?.toLowerCase().startsWith('en') ? 'en' : 'ru' - const next = cur === 'ru' ? 'en-US' : 'ru-RU' - return ( - - ) -} - type Crumb = { label: string; to?: string; subtitle?: string } /**