All checks were successful
Deploy Development / deploy (push) Successful in 39s
Test Suite / pytest-backend (push) Successful in 37s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m14s
- Updated modal components to utilize a consistent overlay and panel structure, improving layout and responsiveness. - Enhanced FormActionBar to support short labels for action buttons, improving usability in mobile views. - Introduced new styling for action buttons and modal titles, ensuring better alignment and visual consistency across forms. - Improved accessibility by adding aria-labels and titles to buttons for better screen reader support.
115 lines
3.7 KiB
JavaScript
115 lines
3.7 KiB
JavaScript
import { Check, Save, X } from 'lucide-react'
|
|
|
|
/**
|
|
* Feste Aktionsleiste für Formulare/Modale: Speichern, Speichern & schließen, Abbrechen.
|
|
* Bleibt sichtbar (sticky), während der Formularinhalt scrollt.
|
|
*/
|
|
function ActionLabel({ Icon, long, short, saving, savingShort = '…' }) {
|
|
if (saving) {
|
|
return <span className="form-action-bar__saving">{savingShort}</span>
|
|
}
|
|
return (
|
|
<>
|
|
{Icon ? <Icon size={17} strokeWidth={2.25} className="form-action-bar__icon" aria-hidden /> : null}
|
|
<span className="form-action-bar__text form-action-bar__text--long">{long}</span>
|
|
{short != null && short !== '' ? (
|
|
<span className="form-action-bar__text form-action-bar__text--short">{short}</span>
|
|
) : null}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default function FormActionBar({
|
|
placement = 'bottom',
|
|
variant = 'default',
|
|
saving = false,
|
|
saveLabel,
|
|
saveShortLabel,
|
|
saveAndCloseLabel = 'Speichern & schließen',
|
|
saveAndCloseShortLabel,
|
|
cancelLabel = 'Abbrechen',
|
|
onSave,
|
|
onSaveAndClose,
|
|
onCancel,
|
|
showSave = true,
|
|
showSaveAndClose = true,
|
|
showCancel = true,
|
|
formId,
|
|
isNew = false,
|
|
primaryIsSaveOnly = false,
|
|
}) {
|
|
const labelSave = saveLabel ?? (isNew ? 'Anlegen' : 'Speichern')
|
|
const shortSave = saveShortLabel ?? (isNew ? 'Neu' : 'Sichern')
|
|
const shortClose = saveAndCloseShortLabel ?? 'Fertig'
|
|
const showSaveBtn = showSave && (Boolean(onSave) || Boolean(formId))
|
|
const showCloseBtn = showSaveAndClose && (Boolean(onSaveAndClose) || Boolean(formId))
|
|
const showCancelBtn = showCancel && Boolean(onCancel)
|
|
|
|
if (!showSaveBtn && !showCloseBtn && !showCancelBtn) return null
|
|
|
|
const saveBtnClass = `btn form-action-bar__btn${
|
|
primaryIsSaveOnly ? ' btn-primary' : ' btn-secondary'
|
|
}`
|
|
const closeBtnClass = `btn form-action-bar__btn${
|
|
primaryIsSaveOnly ? ' btn-secondary' : ' btn-primary'
|
|
}`
|
|
|
|
const primaryCount = (showSaveBtn ? 1 : 0) + (showCloseBtn ? 1 : 0)
|
|
|
|
return (
|
|
<div
|
|
className={`form-action-bar form-action-bar--${placement} form-action-bar--${variant}${
|
|
primaryCount === 1 ? ' form-action-bar--single-primary' : ''
|
|
}`}
|
|
role="group"
|
|
aria-label="Formularaktionen"
|
|
>
|
|
<div className="form-action-bar__inner">
|
|
{showCancelBtn ? (
|
|
<button
|
|
type="button"
|
|
className="btn btn-secondary form-action-bar__btn form-action-bar__btn--cancel"
|
|
onClick={onCancel}
|
|
disabled={saving}
|
|
aria-label={cancelLabel}
|
|
title={cancelLabel}
|
|
>
|
|
<ActionLabel Icon={X} long={cancelLabel} short="" saving={saving} />
|
|
</button>
|
|
) : null}
|
|
<div className="form-action-bar__primary-group">
|
|
{showSaveBtn ? (
|
|
<button
|
|
type={formId && !onSave ? 'submit' : 'button'}
|
|
form={formId && !onSave ? formId : undefined}
|
|
className={saveBtnClass}
|
|
disabled={saving}
|
|
onClick={onSave || undefined}
|
|
title={labelSave}
|
|
>
|
|
<ActionLabel Icon={Save} long={labelSave} short={shortSave} saving={saving} />
|
|
</button>
|
|
) : null}
|
|
{showCloseBtn ? (
|
|
<button
|
|
type={formId && !onSaveAndClose ? 'submit' : 'button'}
|
|
form={formId && !onSaveAndClose ? formId : undefined}
|
|
className={closeBtnClass}
|
|
disabled={saving}
|
|
onClick={onSaveAndClose || undefined}
|
|
title={saveAndCloseLabel}
|
|
>
|
|
<ActionLabel
|
|
Icon={Check}
|
|
long={saveAndCloseLabel}
|
|
short={shortClose}
|
|
saving={saving}
|
|
/>
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|