Repository navigation
Release v2.1.0
v2.1.0
Changelog
Page-contract follow-ups from migrating HttpLog, Workflow, CookieConsent and RoutingKit (REQ-UI-003 phase 1). Additive; see UPGRADING.
Fixed
PageContractTestCaseresets collection prototypes between renders:vars.prototypeFormViews
(CollectionTypewithprototype: 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).PageContractTestCaseno longer flags themodal_shellstructure:modal,fade,modal-dialog,
modal-content,modal-header,modal-title,btn-close,modal-body,modal-footerare a documented structural
exception (FrameworkClasses::MODAL_SHELL, like the pagination list), allowed for everycss_framework; the partial
keeps its 1.x output, so bundles drop them fromallowedClasses(). Page-contract bundles should prefer the new
framework-freedialogpartial.- Header actions backed by a
FormViewkeep their CSRF token when a hostpage_headerpartial override renders
actionsitself (REQ-UI-003): the scaffolds pre-render the 1.xtoolbar, which marked the form's fields rendered,
so the override'sform_endprinted no_token. TheFormViewbranch of the action partial now prints the hidden
leaf fields of the form on every render (other children still render once throughform_end); this also covers one
CSRFFormViewshared 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: trueor explicithelp: false), collection pages need
2.1, headerFormViewactions, form themes, area navigation,dialogvsmodal_shell, new slot mappings. - Wide-form and muted-dialog slots:
input_wide/input_full(complete input class lists with the semantic
modifiersnowo-ui-input--wide— max width 36rem — andnowo-ui-input--full; Tailwind defaultsmax-w-xl/ no
max width),dialog_body_muted(nowo-ui-dialog__body--muted) and thenowo-ui-confirm__body--mutedmodifier:
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), slotsdialog,dialog_header,
dialog_title,dialog_body,dialog_footer, andjs/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 tomodal_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_hrefintoArray()) prints a<noscript>link (classnowo-ui-action__fallback)
to e.g. apage/confirmpage 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::$formThemesandSettingsSection::$formThemes(lists of template names) are
applied withform_themeinside the scaffold before the form renders (settings: before the
nowo_ui_settings_sectionblock), so bundles keep their form theme without overridingnowo_ui_content. - Area navigation (
PageHeader::$tabs,View\AreaNav/View\AreaNavItem,PageHeader::withTabs()): a tab bar
between the sections of a bundle area, rendered by thepage_headerpartial through thetabspartial (region
area-nav, rownowo-ui-page-header__nav).Navigation\AreaNavProviderInterface(autoconfigured tag
nowo_ui_kit.area_nav_provider),Navigation\AreaNavRegistry(servicenowo_ui_kit.area_nav_registry) and the
Twig functionnowo_ui_area_nav(area, context)let other bundles (DashboardMenu) consume an area's navigation. _tabsrootattr: attributes of the<nav>(e.g.{'data-turbo': 'false'}kept from a bundle's 1.x tab
bar), merged over thetabsslot attributes (call site wins), also without the ThemeExtension; 1.x output unchanged.- Theme slots
codeandcode_block(REQ-UI-003): inline<code>(identifiers, keys) and a<pre>block for
payloads / JSON / logs. Semantic classesnowo-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--wrapwraps lines);
framework defaults Bootstrapborder p-3(block), Tailwindfont-mono text-sm(+p-3 borderon 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'spage_headeroverride renders the headeractionsitself (after the
scaffold's pre-renderedtoolbar), and a seventh test per fixture,testPageActionFormsKeepTheirHiddenFields
(helperassertActionFormsKeepHiddenFields(),RenderedPage::$actionForms/hiddenFieldValues()), fails when a
rendered form of aFormView-backedActionof 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.