Александр Зимин
21d95613fc
feat(ui): searchable MultiSelect (cmdk) + DateRangePicker (react-day-picker)
2026-05-12 13:55:35 +00:00
Александр Зимин
3984d99004
fix(ux): friendly error UI вместо raw AxiosError
2026-05-12 12:41:48 +00:00
Zimin A.N.
ca53322b14
fix(form): break drawer counter/dirty infinite-loop + add GlobeLoader + AppErrorBoundary
...
Maximum update depth exceeded showed на /dictionaries/$name когда RecordDrawer
открывался в create mode. Root cause:
1. SchemaDrivenForm useEffect deps включал onCounterChange/onDirtyChange.
2. Parent route передавал inline arrow (() => setDrawerCount({...})) —
новая identity каждый render.
3. setDrawerCount({visible, total}) создавал новый object literal даже
при тех же значениях → React re-render → effect fires → loop.
Fix:
- SchemaDrivenForm: ref-pattern для callback. useEffect subscribed только
на value deps (visibleFieldCount/totalFieldCount/dirtyCount), latest
callback хранится в ref.
- dataValues — useMemo с frozen EMPTY_DATA default чтобы не invalidate'ить
isFieldVisible memo каждый render.
Plus:
- GlobeLoader component — orbital globe spinner per Downloads/Globe loader
prototype. Pure SVG + CSS animations, без d3/topojson.
- LoadingBlock переключен с Loader2 на GlobeLoader (все usage обновляется
автоматически: RecordHistoryDrawer, dictionaries.$name editor loading,
search results, webhooks list, etc).
- AppErrorBoundary — friendly fallback вместо TanStack DefaultErrorComponent.
GlobeLoader (paused/dimmed) + 'Что-то пошло не так' + [Обновить][На главную].
Dev-only collapsible с raw stack trace.
2026-05-11 22:31:57 +03:00
Zimin A.N.
0acba4c073
feat(handoff): WorkflowBanner + table a11y + responsive + toast styling
...
Closing handoff gaps выявленных при полном audit'е README.md vs current
implementation. См. screen-by-screen mapping ниже.
== Screen 2 — Editor: WorkflowBanner (NEW) ==
Required by handoff (line 238-242) но не существовал. Inline status row выше
tab bar — live/review/info variants. Backend не имеет explicit dict-level
workflow state (draft → review → live transition), используем proxy:
- approvalRequired=false → 'Live' (green-bg + green left edge)
- approvalRequired=true + 0 → 'Approval enabled' (accent-bg + accent edge)
- approvalRequired=true + N → 'На ревью N' (warn-bg + warn edge), link к /reviews
Backend extension future: добавить explicit workflowState к DictionaryDetail
+ buttons для transitions (request-review / approve / publish). Сейчас banner
дает минимум — visual workflow signal без UI mutation buttons.
== Table accessibility per handoff line 476 ==
TableHeaderCell:
- scope='col' (a11y screen reader requirement)
- aria-sort='ascending|descending|none' когда sortable prop true
- New sortable + sortDirection props (API ready, не используется пока)
== 560px responsive per handoff line 466 ==
TableHeaderCell + TableCell получили optional hideBelow='sm|md|lg' prop:
hideBelow='sm' → hidden <640px (table-cell ≥sm)
hideBelow='md' → hidden <768px
hideBelow='lg' → hidden <1024px
Callsites могут пометить secondary columns (created_by, updated_at, etc.)
hideBelow='md' для clean mobile experience. Текущие routes ещё не используют
prop — API ready для incremental adoption.
== Toast styling per handoff line 302-305 ==
Sonner toast — раньше surface bg + ink text. Handoff:
- Navy bg + on-accent text (warm cream-orange feeling)
- 4s auto-dismiss
- Variant accent через left border 4px:
success → green / error → pink / info → accent / warning → warn
- cap-style title (но используем text-body для нативности, не overkill)
- 13px font-sans
richColors disabled — наши tokens вместо sonner defaults.
Files:
- NEW src/components/editor/WorkflowBanner.tsx
- src/routes/dictionaries.$name.tsx (wire banner above tab bar)
- src/ui/components/table.tsx (a11y + hideBelow API)
- src/ui/components/toaster.tsx (navy variant + variant borders)
- src/ui/index.ts (TableCellProps export)
Tests: 116 pass. TS strict clean.
2026-05-11 15:58:12 +03:00
Zimin A.N.
5007e0f4eb
feat(ui): drop @nstart/ui dependency (Stage 3.9)
...
Все font cascade bugs из последних MR были вызваны @nstart/ui pollution
(Tektur inheritance от Card parent'ов, Onest font в Button, font-primary
class overrides). Решили обрезать раньше plan'а.
What changed:
New primitives (8 файлов в src/ui/components/):
- panel.tsx — container с border/surface
- field.tsx — FieldLabel/Hint/Error typography helpers
- text-input.tsx — Input + label/hint/error composite
- table.tsx — Table/TableHeader/Body/Row/HeaderCell/Cell/Empty
- date-picker.tsx — native <input type=date> wrapper с label/hint/error
- multi-select.tsx — Radix Popover + inline checkboxes
- single-select.tsx — native <select> с label/hint/error chrome
- language-switch.tsx — segmented control в Tektur uppercase
Compatibility shims (existing components extended):
- checkbox.tsx — + label/description/error/onChange (nstart-compat
synthetic event), wrap в <label> когда есть chrome
- modal.tsx — + panelClassName / bodyClassName props
- form-actions.tsx — + align prop (start/end/between)
- tabs-simple.tsx — TabItem.count alias for .trailing (nstart-compat)
- table TableHead — alias TableHeaderCell с align prop
Barrel rewrite (src/ui/index.ts):
- Удалён 'export * from @nstart/ui'
- Explicit exports для всех 45+ нужных символов
- SelectOption / MultiSelectOption / LanguageOption теперь {id, label}
с optional 'value' alias — nstart-compat без массового codemod call-sites
styles.css cleanup:
- Removed @import @nstart/ui/styles/{fonts,theme}.css
- Removed @source nstart/dist directive (Tailwind v4 scan)
- Removed --text-sm: 13px override (был костыль для @nstart/ui dist)
- Legacy color tokens (--color-carbon/ultramarain/orbit/regolith/asteroid)
sсодержали fallback mappings — оставлены, но callsites больше не используют
Codemod: 9 файлов конвертированы legacy colors → handoff tokens
carbon → ink, ultramarain → accent, orbit → warn, regolith → line, asteroid → mute
main.tsx:
- NStartUiProvider → TooltipProvider (Radix)
- DatePickerProvider убран (наш DatePicker native, no provider needed)
routes/dictionaries.$name.tsx:
- Removed useRef-based <input>.indeterminate hack
- Radix Checkbox принимает checked='indeterminate' declaratively
package.json: -@nstart/ui (was 0.1.3)
Bundle impact:
before: vendor-nstart-ui chunk = 1228 KB
after: no nstart chunk, всё в vendor-misc (+~70 KB Radix wrappers)
net savings: ~1.15 MB minified, ~440 KB gzip
Tests: 116 pass (1 fixed: tab role from 'button' → 'tab', Radix semantically correct).
TS strict: clean.
Browser-verified (preview): 7 utilities computed correctly, nstart bundle absent.
2026-05-11 15:17:37 +03:00
Zimin A.N.
f0dbc20f62
fix(fonts): explicit font-family on title utilities + cascade conflicts
...
Реальные измерения через DevTools на staging выявили 3 бага после MR !47 :
Bug 1: text-title-md/lg/xl inherited Tektur от @nstart/ui Card parent.
Handoff: 'Inter for all headings'. Computed: Tektur.
Fix: добавил font-family: var(--font-sans) explicit на text-title-*
и text-body/text-cell. После Stage 3.9 (nstart gone) можно убрать —
body inherit будет достаточно.
Bug 2: text-cap + font-mono cohabit (catalog scope chips, time-travel
presets) → Tailwind v4 cascade order: font-mono идёт после text-cap
в bundled CSS → JetBrains Mono перебивает Tektur. text-cap baked
font-display, font-mono token redundant.
Fix: codemod strip font-mono где есть text-cap (4 sites). Computed
font-family теперь правильно Tektur.
Bug 3: @nstart/ui PageHeader рендерил h1 'DICTIONARIES' в Tektur
36px/700 uppercase (font-primary text-4xl). Handoff page title:
17px/600 Inter normal case. Наш src/ui/components/page-header.tsx
написан но не экспортирован через barrel — все routes резолвили
PageHeader к nstart версии.
Fix: добавил 'export { PageHeader }' override в src/ui/index.ts.
Все 7 PageHeader usages (catalog/search/reviews/webhooks/outbox/
my-drafts/graph) теперь получат handoff-conformant heading.
Bug 4 (small): catalog counter '37/37' использовал text-cap но это
numeric value — handoff role text-mono (11px JetBrains Mono).
Fix: text-cap → text-mono + tabular-nums для grid alignment.
Verified via injected test elements + CDP computed styles:
text-title-xl: 22/600 Inter
text-title-lg: 17/600 Inter
text-title-md: 15/600 Inter
text-body: 13/400 Inter
text-cell: 12.5/500 Inter
text-mono: 11/500 JetBrains Mono
text-cap: 10.5/600 Tektur
Все 7 utilities точно matches handoff scale.
Files: 4 modified. TS strict + 116 tests pass.
2026-05-11 14:58:32 +03:00
Александр Зимин
649b7c4244
feat(admin-ui): shadcn TextArea (Stage 3.8a)
2026-05-11 09:13:10 +00:00
Александр Зимин
e2f1c3527b
feat(admin-ui): sonner Toast + TimeTravel polish (Stage 3.6+3.7)
2026-05-11 09:11:21 +00:00
Александр Зимин
b7d2fbd7ce
feat(admin-ui): codemod @nstart/ui → @/ui (Stage 2.2)
2026-05-10 22:17:06 +00:00
Александр Зимин
5d12c89c4f
feat(admin-ui): shadcn primitives + @/ui barrel (Stage 2.1)
2026-05-10 21:47:24 +00:00