Skip to content

Release v2.1.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 00:59
· 113 commits to main since this release

v2.1.0

Changelog

Page-contract follow-ups from migrating HttpLog, Workflow, CookieConsent and RoutingKit (REQ-UI-003 phase 1). Additive; see UPGRADING.

Fixed

  • PageContractTestCase resets collection prototypes between renders: vars.prototype FormViews
    (CollectionType with prototype: true) are marked not rendered too, so the second render of a fixture keeps its
    data-prototype (it rendered empty or threw "already rendered" with some form themes).
  • PageContractTestCase no longer flags the modal_shell structure: modal, fade, modal-dialog,
    modal-content, modal-header, modal-title, btn-close, modal-body, modal-footer are a documented structural
    exception (FrameworkClasses::MODAL_SHELL, like the pagination list), allowed for every css_framework; the partial
    keeps its 1.x output, so bundles drop them from allowedClasses(). Page-contract bundles should prefer the new
    framework-free dialog partial.
  • Header actions backed by a FormView keep their CSRF token when a host page_header partial override renders
    actions itself (REQ-UI-003): the scaffolds pre-render the 1.x toolbar, which marked the form's fields rendered,
    so the override's form_end printed no _token. The FormView branch of the action partial now prints the hidden
    leaf fields of the form on every render (other children still render once through form_end); this also covers one
    CSRF FormView shared by every row.

Added

  • docs/MIGRATING_BUNDLES.md: FormKit placeholder / help convention vs the contract test's raw-key check
    (translate every field, convention_requires_translation: true or explicit help: false), collection pages need
    2.1, header FormView actions, form themes, area navigation, dialog vs modal_shell, new slot mappings.
  • Wide-form and muted-dialog slots: input_wide / input_full (complete input class lists with the semantic
    modifiers nowo-ui-input--wide — max width 36rem — and nowo-ui-input--full; Tailwind defaults max-w-xl / no
    max width), dialog_body_muted (nowo-ui-dialog__body--muted) and the nowo-ui-confirm__body--muted modifier:
    muted text and wide inputs that do not depend on Bootstrap CSS.
  • Generic native dialog: partial dialog (partials/_dialog.html.twig; header / title / close button, body,
    footer; size, body_muted, dismissible, backdrop_close, attr), slots dialog, dialog_header,
    dialog_title, dialog_body, dialog_footer, and js/nowo-ui-dialog.js (CSP-safe opener
    data-nowo-ui-dialog-open="<id>", data-nowo-ui-dialog-close, backdrop close, focus return;
    window.nowoUiOpenDialog / nowoUiCloseDialog; loaded by the UiKit document layout). The framework-free
    alternative to modal_shell (kept for BC) for page-contract bundles. Demo: restock dialog on the dashboard.
  • No-JS fallback for confirm actions: Action::$fallbackHref (last constructor argument, kept by
    withConfirmScope(), fallback_href in toArray()) prints a <noscript> link (class nowo-ui-action__fallback)
    to e.g. a page/confirm page next to the dialog toggle, in toolbars and row actions.
  • theme.bundles.<Bundle>.pages.<type> (classes, attributes, framework_defaults): per-bundle variation by
    page type. Precedence: bundle page slot > bundle slot > bundle page > bundle > page-type slot > page type > host
    slot > host; attributes merge host → page type → bundle → bundle page type. Validated by the configuration and by
    Theme.
  • Per-page form themes: FormPage::$formThemes and SettingsSection::$formThemes (lists of template names) are
    applied with form_theme inside the scaffold before the form renders (settings: before the
    nowo_ui_settings_section block), so bundles keep their form theme without overriding nowo_ui_content.
  • Area navigation (PageHeader::$tabs, View\AreaNav / View\AreaNavItem, PageHeader::withTabs()): a tab bar
    between the sections of a bundle area, rendered by the page_header partial through the tabs partial (region
    area-nav, row nowo-ui-page-header__nav). Navigation\AreaNavProviderInterface (autoconfigured tag
    nowo_ui_kit.area_nav_provider), Navigation\AreaNavRegistry (service nowo_ui_kit.area_nav_registry) and the
    Twig function nowo_ui_area_nav(area, context) let other bundles (DashboardMenu) consume an area's navigation.
  • _tabs root attr: attributes of the <nav> (e.g. {'data-turbo': 'false'} kept from a bundle's 1.x tab
    bar), merged over the tabs slot attributes (call site wins), also without the ThemeExtension; 1.x output unchanged.
  • Theme slots code and code_block (REQ-UI-003): inline <code> (identifiers, keys) and a <pre> block for
    payloads / JSON / logs. Semantic classes nowo-ui-code / nowo-ui-code-block (monospace, muted surface; the block
    has a border, scrolls both ways above --nowo-ui-code-block-max-height, nowo-ui-code-block--wrap wraps lines);
    framework defaults Bootstrap border p-3 (block), Tailwind font-mono text-sm (+ p-3 border on the block). New
    optional tokens --nowo-ui-font-mono, --nowo-ui-code-bg, --nowo-ui-code-text, --nowo-ui-code-border,
    --nowo-ui-code-radius, --nowo-ui-code-block-max-height (docs/THEME_SLOTS.md, docs/THEMING.md). Demo: webhook
    payload on the page contract show page.
  • PageContractTestCase: the stub host's page_header override renders the header actions itself (after the
    scaffold's pre-rendered toolbar), and a seventh test per fixture, testPageActionFormsKeepTheirHiddenFields
    (helper assertActionFormsKeepHiddenFields(), RenderedPage::$actionForms / hiddenFieldValues()), fails when a
    rendered form of a FormView-backed Action of the fixture lacks (or duplicates) a hidden field of that form.
  • Demo: the page contract show page has a FormView-backed header action (Reopen); the Playwright e2e checks its
    CSRF token through the host override and the default partial.