refactor(alert): stack title above actions row to fix narrow-width layout (#4239)

Confirm Deletion (and the three other Alert callsites — clear
annotations, delete files, book-detail delete) used to try to keep
the icon/title/message and the Cancel/Confirm buttons in a single
row. At narrow widths the row would flex-wrap and produce a cramped
two-column shape with stacked buttons next to wrapped text — the
case shown in the original PR thread's third screenshot.

Rework the layout to always stack:

* outer container is now `flex flex-col gap-3` instead of toggling
  between flex-row at sm+ and flex-col below.
* top block: icon + title/message, items-start (icon nudged with
  `mt-0.5` so it baselines with the title).
* bottom block: `flex items-center justify-end gap-2` — Cancel +
  Confirm always right-aligned on their own row.
* Drop the daisyUI `alert` class. Its `display: grid` +
  `justify-items: center` was collapsing the actions row to content
  width and pulling it toward centre, which defeated `justify-end`
  the first time around. The styles I actually wanted (`bg-base-300
  rounded-lg p-4 shadow-2xl`) were already explicit.
* Replace the chain of viewport-relative max-widths with the more
  conventional `max-w-md sm:max-w-lg md:max-w-xl` cap so the
  capsule doesn't grow without bound on big monitors.
* Drop the `text-center` flip — text stays left-aligned at every
  width, which matches the rest of the app.

Color theme unchanged: blue `stroke-info` icon, `bg-base-300`
surface, `btn-neutral` Cancel, `btn-warning` Confirm, `btn-sm`
sizing. `useKeyDownActions` keyboard binding and `role='alert'`
preserved. No callsite changes — the four consumers keep the same
props.

Verified visually at 1400 / 900 / 520 / 500 px viewports via
`pnpm dev-web`; `pnpm test` (4389 passed) and `pnpm lint` (tsgo
+ biome) clean.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-05-20 13:16:36 +08:00
committed by GitHub
parent d943a1c146
commit ff4c03919b
+16 -10
View File
@@ -18,19 +18,25 @@ const Alert: React.FC<{
<div
ref={divRef}
role='alert'
// Always stack the title/message block above the actions row. The
// previous side-by-side layout flex-wrapped at narrow widths and
// produced the cramped two-column-with-stacked-buttons shape from
// Image #3. Avoid the daisyUI `alert` class here — it applies a
// `display: grid` with `justify-items: center` that collapses the
// actions row to content width and pulls it toward the centre,
// defeating `justify-end`. We want a plain flex-column surface.
className={clsx(
'alert flex items-center justify-between',
'bg-base-300 rounded-lg border-none p-4 shadow-2xl',
'w-full max-w-[90vw] sm:max-w-[70vw] md:max-w-[50vw] lg:max-w-[40vw] xl:max-w-[40vw]',
'min-w-[70vw] flex-col sm:min-w-[40vw] sm:flex-row',
'flex flex-col gap-3',
'bg-base-300 rounded-lg p-4 shadow-2xl',
'w-full max-w-md sm:max-w-lg md:max-w-xl',
)}
>
<div className='labels flex items-center space-x-2 self-start sm:space-x-4 sm:self-center'>
<div className='labels flex items-start gap-3'>
<svg
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 24'
className='stroke-info h-6 w-6 shrink-0'
className='stroke-info mt-0.5 h-6 w-6 shrink-0'
>
<path
strokeLinecap='round'
@@ -39,12 +45,12 @@ const Alert: React.FC<{
d='M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
></path>
</svg>
<div className='flex flex-col gap-y-2'>
<h3 className='text-start text-sm font-medium sm:text-center'>{title}</h3>
<div className='text-start text-sm sm:text-center'>{message}</div>
<div className='flex min-w-0 flex-col gap-1'>
<h3 className='text-start text-sm font-medium'>{title}</h3>
<div className='text-start text-sm'>{message}</div>
</div>
</div>
<div className='buttons flex flex-wrap items-center justify-end gap-2 self-end sm:max-w-[20vw] sm:self-center'>
<div className='buttons flex items-center justify-end gap-2'>
<button className='btn btn-sm btn-neutral' onClick={onCancel}>
{_('Cancel')}
</button>