fix(topbar): revert ThemeSwitch to 3-icon original + shorten create button
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)
This commit is contained in:
@@ -1,42 +1,37 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { Monitor, Moon, Sun } from 'lucide-react'
|
||||||
import { useTheme, type ThemePreference } from '@/stores/ThemeProvider'
|
import { useTheme, type ThemePreference } from '@/stores/ThemeProvider'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Theme switch per redesign prototype — 2-button segmented control с text
|
* Tri-state theme switch: Light / Dark / System.
|
||||||
* labels "Earth | Dark". Filled accent-bg на active.
|
|
||||||
*
|
*
|
||||||
* <p>Прошлый tri-state (Light/Dark/System icons) был noise — "system" preference
|
* <p>Segmented control с тремя иконками. Активный — `--color-accent`
|
||||||
* редко используется явно, мало кто понимает Monitor icon. Простой 2-button
|
* background + `--color-on-accent` foreground. Click меняет `preference`
|
||||||
* `Earth / Dark` toggle — точно повторяет prototype и улучшает discoverability.
|
* в {@link ThemeProvider}, который пишет в localStorage и переключает
|
||||||
|
* `data-theme` на html.
|
||||||
*
|
*
|
||||||
* <p>Internally "Earth" maps на `light` preference (Earthy palette default).
|
* <p>System icon показывает «follow OS» — auto-update при OS theme change.
|
||||||
* "System" preference больше не выставляется через UI; localStorage value
|
|
||||||
* остаётся валидным (ThemeProvider может read), но новые users получают
|
|
||||||
* explicit light/dark choice.
|
|
||||||
*/
|
*/
|
||||||
export function ThemeSwitch() {
|
export function ThemeSwitch() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { preference, setPreference } = useTheme()
|
const { preference, setPreference } = useTheme()
|
||||||
|
|
||||||
// Treat 'system' как 'light' для UI — переключение всё равно flatten'ит
|
const items: { id: ThemePreference; label: string; icon: typeof Sun }[] = [
|
||||||
// preference на explicit choice.
|
{ id: 'light', label: t('theme.light'), icon: Sun },
|
||||||
const activeId: Exclude<ThemePreference, 'system'> =
|
{ id: 'dark', label: t('theme.dark'), icon: Moon },
|
||||||
preference === 'dark' ? 'dark' : 'light'
|
{ id: 'system', label: t('theme.system'), icon: Monitor },
|
||||||
|
|
||||||
const items: { id: Exclude<ThemePreference, 'system'>; label: string }[] = [
|
|
||||||
{ id: 'light', label: t('theme.earth', { defaultValue: 'Earth' }) },
|
|
||||||
{ id: 'dark', label: t('theme.dark', { defaultValue: 'Dark' }) },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
role="radiogroup"
|
role="radiogroup"
|
||||||
aria-label={t('theme.label')}
|
aria-label={t('theme.label')}
|
||||||
className="inline-flex items-center rounded-md border border-line bg-surface overflow-hidden"
|
className="inline-flex items-center rounded-md border border-line bg-surface p-0.5"
|
||||||
>
|
>
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const active = activeId === item.id
|
const Icon = item.icon
|
||||||
|
const active = preference === item.id
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={item.id}
|
key={item.id}
|
||||||
@@ -44,15 +39,16 @@ export function ThemeSwitch() {
|
|||||||
role="radio"
|
role="radio"
|
||||||
aria-checked={active}
|
aria-checked={active}
|
||||||
aria-label={item.label}
|
aria-label={item.label}
|
||||||
|
title={item.label}
|
||||||
onClick={() => setPreference(item.id)}
|
onClick={() => setPreference(item.id)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'h-8 px-3 text-cap font-semibold tracking-[0.14em] transition-colors',
|
'inline-flex h-6 w-6 items-center justify-center rounded transition-colors',
|
||||||
active
|
active
|
||||||
? 'bg-accent text-on-accent'
|
? 'bg-accent text-on-accent'
|
||||||
: 'text-ink-2 hover:text-ink hover:bg-surface-2',
|
: 'text-mute hover:text-ink hover:bg-surface-2',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{item.label}
|
<Icon size={13} strokeWidth={2.25} />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ i18n
|
|||||||
'scope.PUBLIC': 'PUBLIC — публичный',
|
'scope.PUBLIC': 'PUBLIC — публичный',
|
||||||
'scope.INTERNAL': 'INTERNAL — внутренний',
|
'scope.INTERNAL': 'INTERNAL — внутренний',
|
||||||
'scope.RESTRICTED': 'RESTRICTED — ограниченный',
|
'scope.RESTRICTED': 'RESTRICTED — ограниченный',
|
||||||
'schema.action.create': 'Создать справочник',
|
'schema.action.create': 'Создать',
|
||||||
'schema.action.edit': 'Изменить справочник',
|
'schema.action.edit': 'Изменить справочник',
|
||||||
'schema.action.editSchema': 'Схема',
|
'schema.action.editSchema': 'Схема',
|
||||||
'schema.tabs.metadata': 'Метаданные',
|
'schema.tabs.metadata': 'Метаданные',
|
||||||
@@ -844,7 +844,7 @@ i18n
|
|||||||
'scope.PUBLIC': 'PUBLIC',
|
'scope.PUBLIC': 'PUBLIC',
|
||||||
'scope.INTERNAL': 'INTERNAL',
|
'scope.INTERNAL': 'INTERNAL',
|
||||||
'scope.RESTRICTED': 'RESTRICTED',
|
'scope.RESTRICTED': 'RESTRICTED',
|
||||||
'schema.action.create': 'Create dictionary',
|
'schema.action.create': 'Create',
|
||||||
'schema.action.edit': 'Edit dictionary',
|
'schema.action.edit': 'Edit dictionary',
|
||||||
'schema.action.editSchema': 'Schema',
|
'schema.action.editSchema': 'Schema',
|
||||||
'schema.tabs.metadata': 'Metadata',
|
'schema.tabs.metadata': 'Metadata',
|
||||||
|
|||||||
Reference in New Issue
Block a user