| 1 |
import classNames from 'classnames'; |
| 2 |
|
| 3 |
// Covers the viewport: blurring one region leaves four hard edges mid-page. |
| 4 |
const OVERLAY = [ |
| 5 |
'fixed inset-0 z-20 overflow-y-auto p-6', |
| 6 |
// Drawn outside the page canvas, so the type it sets never reaches here. |
| 7 |
'text-ui-body font-ui-body', |
| 8 |
'[backdrop-filter:blur(var(--ext-ui-wait-blur,6px))]', |
| 9 |
].join(' '); |
| 10 |
|
| 11 |
// min-h-full, or a box taller than the viewport centres its overflow out of reach. |
| 12 |
const CENTERING = 'flex min-h-full items-center justify-center'; |
| 13 |
|
| 14 |
const BOX = 'flex flex-col [gap:var(--ext-tpl-modal-gap,12px)]'; |
| 15 |
|
| 16 |
// Stretched either way, or a shrink-wrapped heading has no room to move. |
| 17 |
const CENTER = 'items-stretch [text-align:var(--ext-tpl-modal-align,center)]'; |
| 18 |
|
| 19 |
const LEFT = 'items-stretch [text-align:var(--ext-tpl-modal-align,left)]'; |
| 20 |
|
| 21 |
// The one template allowed off the shared card, so an interruption can differ. |
| 22 |
const CARD_BOX = [ |
| 23 |
'border-solid shadow-ui', |
| 24 |
'[border-radius:var(--ext-tpl-modal-radius,var(--radius-ui-card))]', |
| 25 |
// Floating over a blurred page, the overlay needs an edge the cards can skip. |
| 26 |
'[border-width:var(--ext-tpl-modal-border,max(1px,var(--ext-ui-border-width,1px)))]', |
| 27 |
'[border-color:var(--ext-tpl-modal-line,var(--color-ui-line))]', |
| 28 |
// An overlay that lets the page through is not covering anything, so the |
| 29 |
// shared surface is taken before its opacity is mixed in. |
| 30 |
'[background:var(--ext-tpl-modal-surface,var(--ext-ui-surface,#f0f0f0))]', |
| 31 |
// Every part inside paints by these tokens, the icons included. |
| 32 |
'[--color-ui-ink:var(--ext-tpl-modal-text,var(--ui-base-ink))]', |
| 33 |
'[--color-ui-action:var(--ext-tpl-modal-action,var(--ui-base-action))]', |
| 34 |
'[--color-ui-action-text:var(--ext-tpl-modal-action-text,var(--ui-base-action-text))]', |
| 35 |
'[--color-ui-secondary-fill:var(--ext-tpl-modal-secondary-fill,var(--ui-base-secondary-fill))]', |
| 36 |
'[--color-ui-secondary-line:var(--ext-tpl-modal-secondary-line,var(--ui-base-secondary-line))]', |
| 37 |
'[--color-ui-secondary-text:var(--ext-tpl-modal-secondary-text,var(--ui-base-secondary-text))]', |
| 38 |
'[padding:var(--ext-tpl-modal-pad,var(--ext-ui-surface-padding,1.5rem))]', |
| 39 |
'[max-width:var(--ext-tpl-modal-width,448px)]', |
| 40 |
].join(' '); |
| 41 |
|
| 42 |
const ACTIONS = 'flex items-center [gap:var(--ext-tpl-modal-actions-gap,12px)]'; |
| 43 |
|
| 44 |
export const Page = ({ parts, has }) => ( |
| 45 |
<div className={OVERLAY}> |
| 46 |
<div className={CENTERING}> |
| 47 |
<div |
| 48 |
className={classNames( |
| 49 |
BOX, |
| 50 |
has.left ? LEFT : CENTER, |
| 51 |
has.card && CARD_BOX, |
| 52 |
)} |
| 53 |
> |
| 54 |
{has.heading && parts.heading} |
| 55 |
{parts.body} |
| 56 |
{has.actions && ( |
| 57 |
<div |
| 58 |
className={classNames( |
| 59 |
ACTIONS, |
| 60 |
has.left ? 'justify-end' : 'justify-center', |
| 61 |
)} |
| 62 |
> |
| 63 |
{parts.actions} |
| 64 |
</div> |
| 65 |
)} |
| 66 |
</div> |
| 67 |
</div> |
| 68 |
</div> |
| 69 |
); |
| 70 |
|