feat(topbar): match redesign prototype — breadcrumb back-arrow + cleaner right cluster

Per /Users/zimin/Downloads/Ordinis (4)/redesign/compact.html.

TopBar breadcrumb:
- Detail routes теперь показывают `← Справочники / Космические аппараты`
  с back-arrow prefix на parent crumb (caption text, mute). Bold title +
  inline mono subtitle "satellites · v1.0.0".
- Catalog route: simple "Dictionaries" title.

TopBar right cluster cleanup:
- Removed `Docs` link — diagnostic, не critical UX, моя кноп не нужна
  для UI flow.
- Removed `VersionBadge` (commit + tag) — был noise рядом с продакшн
  features. Build info всё ещё доступна в browser console / Docs.
- ThemeSwitch: tri-state (Light/Dark/System icons 3×24px) заменён на
  2-button `Earth | Dark` с text labels (per prototype). `system`
  preference остаётся в localStorage для existing users, но новый UI
  не выставляет.
- LanguageSwitch: dual radio `RU | EN` заменён на single toggle button —
  показывает текущий язык как label, click переключает на следующий.
  Saves ~60px горизонтально, matches prototype.

EditorInfoPanel order:
- Action buttons (Экспорт / Time-travel / AOI) переехали из середины
  panel (между metadata и Relations) в bottom (после Relations) —
  per prototype. Info → meta → relations → actions flow.
- Action order: Экспорт первым (frequent), затем Time-travel, AOI последним
  (rare для most dicts).
This commit is contained in:
Zimin A.N.
2026-05-11 19:43:05 +03:00
parent bc737820d6
commit ac1ca8d035
3 changed files with 120 additions and 104 deletions
@@ -72,57 +72,6 @@ export function EditorInfoPanel({ detail, recordCount, actions }: EditorInfoPane
</MetaCell>
</div>
{/* Actions — bottom buttons per redesign prototype: Time-travel + AOI */}
{actions && (
<div className="space-y-2 pt-2 border-t border-line-2">
{actions.onTimeTravel && (
<button
type="button"
onClick={actions.onTimeTravel}
aria-pressed={actions.timeTravelActive}
className={cn(
'w-full h-8 rounded-md border text-cell flex items-center justify-center gap-1.5 transition-colors',
actions.timeTravelActive
? 'border-accent bg-accent-bg text-accent'
: 'border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2',
)}
>
<ClockCounterClockwiseIcon weight="regular" size={14} />
{t('timeTravel.button', { defaultValue: 'Time-travel…' })}
</button>
)}
{actions.onAoi && (
<button
type="button"
onClick={actions.onAoi}
aria-pressed={actions.aoiActive}
className={cn(
'w-full h-8 rounded-md border text-cell flex items-center justify-center gap-1.5 transition-colors',
actions.aoiActive
? 'border-accent bg-accent-bg text-accent'
: 'border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2',
)}
>
<MapTrifoldIcon weight="regular" size={14} />
{t('aoi.button', { defaultValue: 'AOI фильтр…' })}
</button>
)}
{actions.onExport && (
<button
type="button"
onClick={actions.onExport}
disabled={actions.exportPending}
className="w-full h-8 rounded-md border border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2 disabled:opacity-50 disabled:cursor-not-allowed text-cell flex items-center justify-center gap-1.5 transition-colors"
>
<DownloadSimpleIcon weight="regular" size={14} />
{actions.exportPending
? t('export.pending', { defaultValue: 'Экспорт…' })
: t('export.button', { defaultValue: '↓ Экспорт…' })}
</button>
)}
</div>
)}
{/* Relations — merged inline DictionaryDependentsPanel в InfoPanel.
* → ссылается: outgoing FK targets (имя dict, links).
* ← используют: incoming FK rows с field path + active count + policy chip
@@ -202,6 +151,59 @@ export function EditorInfoPanel({ detail, recordCount, actions }: EditorInfoPane
)}
</Section>
)}
{/* Actions — bottom buttons per redesign prototype: Экспорт + Time-travel
* + AOI. После Relations block чтобы не разрывать info → meta → relations
* мыслительный поток info-panel'а. */}
{actions && (
<div className="space-y-2 pt-3 mt-2 border-t border-line-2">
{actions.onExport && (
<button
type="button"
onClick={actions.onExport}
disabled={actions.exportPending}
className="w-full h-8 rounded-md border border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2 disabled:opacity-50 disabled:cursor-not-allowed text-cell flex items-center justify-center gap-1.5 transition-colors"
>
<DownloadSimpleIcon weight="regular" size={14} />
{actions.exportPending
? t('export.pending', { defaultValue: 'Экспорт…' })
: t('export.button', { defaultValue: '↓ Экспорт…' })}
</button>
)}
{actions.onTimeTravel && (
<button
type="button"
onClick={actions.onTimeTravel}
aria-pressed={actions.timeTravelActive}
className={cn(
'w-full h-8 rounded-md border text-cell flex items-center justify-center gap-1.5 transition-colors',
actions.timeTravelActive
? 'border-accent bg-accent-bg text-accent'
: 'border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2',
)}
>
<ClockCounterClockwiseIcon weight="regular" size={14} />
{t('timeTravel.button', { defaultValue: 'Time-travel…' })}
</button>
)}
{actions.onAoi && (
<button
type="button"
onClick={actions.onAoi}
aria-pressed={actions.aoiActive}
className={cn(
'w-full h-8 rounded-md border text-cell flex items-center justify-center gap-1.5 transition-colors',
actions.aoiActive
? 'border-accent bg-accent-bg text-accent'
: 'border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2',
)}
>
<MapTrifoldIcon weight="regular" size={14} />
{t('aoi.button', { defaultValue: 'AOI фильтр…' })}
</button>
)}
</div>
)}
</aside>
)
}