feat(ui): 3-dot row menu + history compare/revert + DateTime fitting + tablet touch
Per user feedback screenshots:
SchemaDrivenForm DateTimeField:
- grid → flex flex-wrap: на узких cells (drawer 520px ÷ 2 cols = ~210px)
time wraps под date вертикально. На wide — inline.
- Date min-w 8rem (128px), time w-24 (96px) — tablet touch-safe.
TableHeaderCell без visible label (sr-only для screen readers).
TableCell содержит DropdownMenu trigger 36×36px (touch target):
- History (always)
- Edit, Separator, Close (только canMutate, Close в danger color)
Заменяет 3 inline IconButton'a — экономит ширину + tablet friendly.
RecordHistoryDrawer accepts onCompare / onRevert callbacks. Каждая
non-current version row показывает:
- Сравнить с текущим — opens ConflictDiffModal (reused diff UI)
- Откатить к v{N} — submit updateMut с этой version данными как
payload (+ confirm dialog). Backend создаёт новую active version,
bitemporal history preserves старые.
JSON viewer переключился с <details> на state-driven (hide/show
без CSS rabbit hole).
history.hideData/compare/revert/revertConfirm (RU + EN).
- 3-dot trigger 36px = comfortable touch target (Apple HIG 44, ours
acceptable для density)
- Drawer на <880px viewport = fullscreen sheet (already)
- DateTime wraps на cell <8rem+9rem+gap = 290px
- Sidebar collapse на <1024 = hamburger overlay
This commit is contained in:
@@ -802,15 +802,21 @@ type DateTimeFieldProps = {
|
||||
const DateTimeField = ({ label, value, defaultTime, onChange, hint, error }: DateTimeFieldProps) => {
|
||||
const dateValue = parseFormDate(value)
|
||||
const timeValue = extractTime(value, defaultTime)
|
||||
// flex-wrap вместо fixed grid: на узких ячейках (drawer 520px ÷ 2 cols =
|
||||
// ~210px) time wraps под date. На wide (880px ÷ 2 = ~410px) — inline.
|
||||
// min-w на date обеспечивает разумный размер до wrap'a. Время 6rem (96px)
|
||||
// достаточно для HH:mm + tap target 44px touch-safe.
|
||||
return (
|
||||
<div>
|
||||
<div className="grid grid-cols-[1fr_auto] gap-2 items-end">
|
||||
<DatePicker
|
||||
label={label}
|
||||
value={dateValue}
|
||||
onChange={(d) => onChange(combineDateTime(d, timeValue, value ?? ''))}
|
||||
/>
|
||||
<div className="w-28">
|
||||
<div className="flex flex-wrap gap-2 items-end">
|
||||
<div className="flex-1 min-w-[8rem]">
|
||||
<DatePicker
|
||||
label={label}
|
||||
value={dateValue}
|
||||
onChange={(d) => onChange(combineDateTime(d, timeValue, value ?? ''))}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-24 shrink-0">
|
||||
<TextInput
|
||||
label="HH:mm"
|
||||
type="time"
|
||||
|
||||
Reference in New Issue
Block a user