fix(fonts): align all text sizes to handoff spec via Tailwind theme overrides

Глобальные правки через @theme в styles.css вместо 200+ точечных правок:

- text-sm: 14px -> 13px (handoff workhorse — body, buttons, tabs)
- text-2xs: undefined -> 11px (handoff IDs, mono meta — было невидимо)
- @utility text-cap: 10.5px Tektur uppercase 0.10em (handoff caps)

Codemod (30 sites): text-2xs + uppercase + tracking-[0.10em] -> text-cap.
Sidebar section labels consolidated с explicit text-[10.5px] на text-cap.

Покрывает 64 text-sm + 148 text-2xs автоматически. Table cells (12.5px)
и page/modal titles (17px/22px) остаются explicit text-[Npx] arbitrary
values по месту — нет slots в Tailwind scale.
This commit is contained in:
Zimin A.N.
2026-05-11 14:12:57 +03:00
parent 780de70fc5
commit 71432e9ae7
19 changed files with 56 additions and 31 deletions
@@ -327,7 +327,7 @@ const FieldBody = ({
<div>
<FieldLabel required={required}>
{label}{' '}
<span className="text-2xs uppercase tracking-[0.10em] text-mute ml-1">i18n</span>
<span className="text-cap text-mute ml-1">i18n</span>
</FieldLabel>
<div className="space-y-2 pl-3 border-l-2 border-line mt-1">
{supportedLocales.map((loc) => (
@@ -126,7 +126,7 @@ export function Sidebar() {
{visibleSections.map((section, idx) => (
<div key={idx} className="flex flex-col gap-0.5">
{section.label && (
<div className="px-3 py-1 font-display uppercase tracking-[0.10em] text-mute text-[10.5px] leading-none">
<div className="text-cap px-3 py-1 text-mute">
{section.label}
</div>
)}
@@ -224,7 +224,7 @@ export const CascadeConfirmDialog = ({
<div>
<label
htmlFor="cascade-reason"
className="text-2xs text-ink-2 uppercase tracking-[0.10em]"
className="text-cap text-ink-2"
>
{t('cascade.reason.label')}
</label>
@@ -242,7 +242,7 @@ export const CascadeConfirmDialog = ({
<div>
<label
htmlFor="cascade-confirm"
className="text-2xs text-ink-2 uppercase tracking-[0.10em]"
className="text-cap text-ink-2"
>
{t('cascade.confirmGate.label', { word: 'CONFIRM' })}
</label>
@@ -181,7 +181,7 @@ export function DictionaryHubView({ detail }: { detail: DictionaryDetail }) {
{detail.description}
</p>
)}
<div className="mt-4 pt-3 border-t border-line flex items-center justify-between text-2xs uppercase tracking-[0.10em] text-mute">
<div className="text-cap mt-4 pt-3 border-t border-line flex items-center justify-between text-mute">
<span>{detail.bundle}</span>
<span>{detail.supportedLocales.join(', ')}</span>
{typeof detail.recordCount === 'number' && (
@@ -341,7 +341,7 @@ export const DictionaryEditorDialog = ({ open, mode, onClose, onSuccess }: Props
<div className="md:col-span-2">
<label
htmlFor="approval-min-role"
className="text-2xs uppercase tracking-[0.10em] text-ink-2"
className="text-cap text-ink-2"
>
{t('schema.approvalMinRole.label')}
</label>
@@ -51,7 +51,7 @@ export const PropertyEditor = ({
return (
<div className="border border-line rounded-lg p-3 space-y-3 bg-white">
<div className="flex items-start justify-between gap-2">
<span className="text-2xs uppercase tracking-[0.10em] text-mute">
<span className="text-cap text-mute">
{t('schema.property')} #{index + 1}
</span>
<div className="flex items-center gap-1">
@@ -53,7 +53,7 @@ export function TimeTravelPicker({
<div className="flex flex-col gap-3 px-4 py-3 rounded-md border border-warn bg-warn-bg text-sm">
<div className="flex items-center gap-2">
<ClockCounterClockwiseIcon weight="bold" size={16} className="text-warn" />
<span className="text-2xs font-display uppercase tracking-[0.10em] text-ink-2">
<span className="text-cap font-display text-ink-2">
{t('timeTravel.label')}
</span>
<button
@@ -340,7 +340,7 @@ function QuickPresets({ onPick }: { onPick: (deltaMs: number) => void }) {
]
return (
<div className="flex flex-wrap items-center gap-1.5">
<span className="text-2xs uppercase tracking-[0.10em] text-mute font-display mr-1">
<span className="text-cap text-mute font-display mr-1">
{t('timeTravel.quickPresets')}
</span>
{presets.map((p) => (
@@ -348,7 +348,7 @@ function QuickPresets({ onPick }: { onPick: (deltaMs: number) => void }) {
key={p.key}
type="button"
onClick={() => onPick(p.deltaMs)}
className="px-2.5 py-1 rounded-full border border-line hover:border-accent hover:bg-accent/4 text-2xs font-mono uppercase tracking-[0.10em] text-ink transition-colors"
className="text-cap px-2.5 py-1 rounded-full border border-line hover:border-accent hover:bg-accent/4 font-mono text-ink transition-colors"
>
{p.label}
</button>