From 9e2d985485f60f8333ed5d81de7cd6bcd5009bad Mon Sep 17 00:00:00 2001 From: "Zimin A.N." Date: Mon, 11 May 2026 15:45:27 +0300 Subject: [PATCH] =?UTF-8?q?fix(ui):=20tailwind-merge=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B8=D0=BF=D0=B0=D0=BB=20text-body=20=E2=80=94=20buttons=20?= =?UTF-8?q?=D1=83=D1=88=D0=BB=D0=B8=20=D0=B2=2016px=20inherited?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL bug — на staging buttons рендерились в 16px вместо handoff workhorse 13px. UpdateBanner secondary buttons показывали invisible текст (text-ink overrode by inherited text-on-accent от parent banner). Root cause: buttonVariants base = 'rounded-md text-body font-medium ...' primary variant = 'bg-navy text-on-accent ...' tailwind-merge default config pattern-matches `text-*` как ОДНУ группу (color). Видя `text-body text-on-accent` он считал это конфликтом двух colors → keep last → text-on-accent остаётся, text-body стрипается. Result: button теряет font-size → inherit body 16px. Fix: extendTailwindMerge регистрирует наши custom semantic typography utilities (text-body/cell/mono/cap/title-*) в группе font-size (отдельной от colors). twMerge теперь знает `text-body text-on-accent` это size + color, обе сохраняются. Also: text-mono/text-cap в font-family группе (они baked Mono/Tektur) — fix конфликт с font-mono/font-display tokens если кто-то их случайно combined. Verified в preview: 'Sign in' button class теперь содержит text-body, computed fontSize: 13px (вместо 16px). Plus CI: release job image node:22-alpine → repo.nstart.cloud/library/ node:22-alpine (Docker Hub rate-limited, mirror используется во всех других jobs). --- .gitlab-ci.yml | 2 +- ordinis-admin-ui/src/lib/utils.ts | 34 +++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fecbc9b..07bff4d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -393,7 +393,7 @@ trigger-deploy-prod: # `[skip release]` и semantic-release пропустит этот commit (см. parserOpts). release: stage: release - image: node:22-alpine + image: repo.nstart.cloud/library/node:22-alpine needs: - job: trigger-deploy-staging artifacts: false diff --git a/ordinis-admin-ui/src/lib/utils.ts b/ordinis-admin-ui/src/lib/utils.ts index c0ef9f0..832faff 100644 --- a/ordinis-admin-ui/src/lib/utils.ts +++ b/ordinis-admin-ui/src/lib/utils.ts @@ -1,12 +1,42 @@ import { type ClassValue, clsx } from 'clsx' -import { twMerge } from 'tailwind-merge' +import { extendTailwindMerge } from 'tailwind-merge' /** * Tailwind class merger — combines clsx (conditional classes) + tailwind-merge * (resolves conflicts: e.g. `px-2 px-4` → `px-4`). * * Standard shadcn/ui utility, used by every primitive variant. + * + *

tailwind-merge по умолчанию не знает наши custom typography utilities + * (text-body, text-cell, text-mono, text-title-xl/lg/md, text-cap) — он + * pattern-matches `text-*` как color class, поэтому считал `text-body text-ink` + * конфликтом (двух color rules) и убирал первый. Результат: buttons теряли + * font-size, наследовали 16px от body. + * + *

extendTailwindMerge регистрирует наши utilities в группе `font-size` + * (separate от colors), и в группе `font-family` для text-mono/text-cap + * (которые baked в Mono/Tektur respectively). Теперь `text-body text-ink` + * корректно сохраняется как size + color combination. */ +const customTwMerge = extendTailwindMerge({ + extend: { + classGroups: { + 'font-size': [ + 'text-body', + 'text-cell', + 'text-mono', + 'text-cap', + 'text-title-xl', + 'text-title-lg', + 'text-title-md', + ], + // text-mono / text-cap baked font-family. Регистрируем отдельной группой + // чтобы конфликтовали с `font-mono` / `font-display` корректно. + 'font-family': ['text-mono', 'text-cap'], + }, + }, +}) + export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return customTwMerge(clsx(inputs)) }