diff --git a/HISTORY.md b/HISTORY.md index 9100fb3..d9dfd2b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2345,3 +2345,82 @@ JSON лишився запасним виходом для джерел, яки валідація невідоме джерело → 400 з поясненням тести server (з базою) і web build — зелені ``` + +## Три правки інтерфейсу + +### «Правила» пішли з бічної панелі + +Тригери переїхали в шаблони, а окремий пункт меню лишився й далі +пропонував заводити правила там, звідки їх щойно прибрали. + +Тепер це вкладка поруч з «Алертами»: `Алерти · Правила`. Розділ +лишився — разові правила на конкретний хост нікуди не діваються, — але +не займає рядок у меню як рівноправна тема. + +Вкладки маршрутні, а не станові: посилання лишається посиланням, із +середньою кнопкою, «відкрити в новій вкладці» й адресою в рядку +браузера. Тому це окремий компонент `SectionTabs`, а не той самий +`Tabs`, що перемикає вміст форми. + +Підзаголовок сторінки правил тепер прямо каже, де правити тригери +шаблонів. + +### Кнопки перестали бути текстом + +У кнопок типово `user-select: auto` — підпис лишається виділюваним +текстом, і в нього можна поставити текстовий курсор. Він блимає +всередині кнопки, ніби туди щось вводять. На дотик гірше: довге +натискання виділяє слово замість натиснути. + +Правило на елемент, а не на компонент — кнопки трапляються й поза +`
diff --git a/web/src/components/ui.tsx b/web/src/components/ui.tsx index 702dee5..4701bf9 100644 --- a/web/src/components/ui.tsx +++ b/web/src/components/ui.tsx @@ -1,5 +1,6 @@ import { useEffect, useRef, useState } from 'react' import type { ReactNode } from 'react' +import { NavLink } from 'react-router-dom' /** * Примітиви інтерфейсу. @@ -29,6 +30,38 @@ export function PageHeader({ ) } +/** + * Смуга розділів під шапкою сторінки. + * + * Не те саме, що Tabs: ті перемикають вміст форми, а ці — маршрут, і + * посилання лишається посиланням (середня кнопка, «відкрити в новій + * вкладці», адреса в рядку браузера). + * + * Потрібна там, де два екрани — це одна тема, і обидва в бічній панелі + * лише подовжували б її: алерти й правила, за якими вони виникають. + */ +export function SectionTabs({ tabs }: { tabs: { to: string; label: string }[] }) { + return ( +
+ {tabs.map((t) => ( + + `-mb-px rounded-t border-b-2 px-3 py-1.5 text-sm transition-colors ${ + isActive + ? 'border-sky-500 font-medium text-slate-100' + : 'border-transparent text-slate-500 hover:text-slate-300' + }` + } + > + {t.label} + + ))} +
+ ) +} + type ButtonKind = 'primary' | 'default' | 'danger' | 'ghost' const buttonKind: Record = { diff --git a/web/src/index.css b/web/src/index.css index b1be2b0..0368055 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -27,6 +27,31 @@ body { color: #334155 !important; } +/* --------------------------------------------------------------------- + Кнопки — це кнопки, а не текст + ------------------------------------------------------------------ */ + +/* Типово підпис кнопки лишається виділюваним текстом (user-select: auto), + і в браузері на ньому можна поставити текстовий курсор — він блимає + всередині кнопки, ніби туди щось вводять. На дотик те саме виглядає + гірше: довге натискання виділяє слово замість натиснути. + + Правило на елемент, а не на компонент: кнопки трапляються й поза +