Update dependency @nldd/design-system to ^0.10.0 #471

Open
robbertbos wants to merge 1 commit from renovate/nldd into main
Owner

This PR contains the following updates:

Package Change Age Confidence
@nldd/design-system ^0.8.92 → ^0.10.0 age confidence

Release Notes

NederlandseDigitaleDienst/design-system (@​nldd/design-system)

v0.10.0

Compare Source

Highlights
  • Themes for 17 Rijkshuisstijl colors. Set data-nldd-theme on <html> and buttons, selections, links, the focus ring, the hero and the badge take that color instead of lintblauw, in light and dark mode. The ribbon and the logo stay lintblauw.
  • A favicon and touch icon in the color of your theme. The field behind the ribbon takes the theme color, so the tab and the home screen match the site. They ship as @nldd/design-system/favicon/geel/ and so on.
Added
  • A stylesheet per theme. Import @nldd/design-system/themes/geel.css and set data-nldd-theme="geel" on <html>. @nldd/design-system/themes holds all of them, for a site that switches without a reload. Lintblauw is the default and needs no file. A theme sets the accent scale, the tokens per role and, for cool colors, a gray with a hint of the theme color. The "Thema's" page in Storybook explains what each role does.
  • A favicon and touch icon per theme. @nldd/design-system/favicon/geel/favicon.svg and …/geel/touch-icon.png, and the same for every theme, have the field behind the ribbon in the theme color. The ribbon stays lintblauw and the coat of arms white. Without a theme, @nldd/design-system/favicon.svg and touch-icon.png stay as they are.
  • Surface tokens in the theme color. --semantics-surfaces-accent-tinted-* is a tint of the theme color with the contrast of tinted. --semantics-surfaces-accent-filled-* is the panel of the hero, with --semantics-content-on-accent-filled-* for the text on it.
  • background="accent-tinted" on nldd-box, nldd-card and the page sections. The area takes the tint of the theme color.
  • color="inherit" on nldd-checkbox, nldd-radio-button and nldd-switch, and on their fields. A checked control takes the text color of the area it sits on, and the color of that area for its mark. Use it on the accent panel of the hero, where the theme color would not stand out.
  • A --components-* layer, only for what a theme sets. A theme reaches :root, not the styles of a component, so the few values a theme changes for one component live in variables.css as --components-{component}-*: the accent badge and status bar, the icon of the accent banner, the mention in the text editor and the current tab of the tab bar. It is not the old component layer: a component reads only its own tokens, and the style check fails on any other. Everything else stays a local variable or a semantics token.
Changed
  • --semantics-controls-is-highlighted-* is now --semantics-controls-is-selected-*. It is the color of a checked, selected or current control, so the name says that, as --semantics-buttons-*-is-selected-* already did. The highlighted item of a menu or mention list, where the keyboard or pointer is, reads --semantics-list-items-is-highlighted-* instead, like the highlighted row of a list, and that token has its own values now. If your own CSS reads one of these tokens, rename it.
  • Categories are for telling groups apart; surfaces are for areas. Only the tag and the progress bar and circle read --semantics-categories-* now. The banner draws on --semantics-surfaces-{tinted,accent-tinted,success-tinted,warning-tinted,critical-tinted}-*, new for success, warning and critical; nldd-box background="critical" takes a surface too. The badge, status bar, date picker and image keep their colors in their own styles, and a mention in the text editor reads --components-text-editor-mention-*, which a theme can set. The neutral and accent banner are one step lighter, on the same tint as background="tinted", and the warning and success icons of the banner are a lighter orange and green in light mode.
  • The reference category style is gone. --semantics-categories-{color}-reference-* drew the panel of the hero, which now reads --semantics-surfaces-accent-filled-* and --semantics-content-on-accent-filled-*. No component used it anymore. If your own CSS reads one of these tokens, take the accent-filled surface for the theme color, or the filled style of the color.
  • The surface border tokens are called highlight-border, as everywhere else. --semantics-surfaces-border-width is now --semantics-surfaces-highlight-border-width, and --semantics-surfaces-base-border-color and --semantics-surfaces-tinted-border-color are now -highlight-border-color. The components follow by themselves. If your own CSS reads one of these tokens, rename it.
  • Warning is a lighter orange on the badge and the status bar. They take orange step 300 instead of 400 (700 instead of 600 in dark mode), which reads clearer next to black text. Their border stays at 3:1 against the page.
  • The focus ring is lighter in dark mode. It takes the color of the button when that reaches 4.5:1 against the page, so with the default theme it is lintblauw 650 instead of 600.
  • A checked control has a mark in the color of the page in dark mode. The check of a checkbox, the dot of a radio button and the knob of a switch were white and now read as a cut-out of the page. The new --semantics-controls-is-selected-mark-color sets that color.
  • The accent badge and status bar match the accent button in dark mode. They take lintblauw 650 with white text instead of 400 with black text.
  • The wordmark of nldd-top-navigation-bar stands where the printed logo has it. On md and lg it is 10px from the ribbon instead of 8px, so the first letter is as far from the ribbon as in the logo. On a small screen a wordmark taller than the ribbon keeps 16px from the top instead of 12px.
Fixed
  • Components switch to their narrow layout when you zoom in Safari. With page zoom, Safari measured the width of a container that takes its size from the layout in zoomed pixels, so a list 537px wide counted as wider than 641px and kept its desktop layout, with a column of one word per line. The breakpoints in the component styles are now in rem (40rem instead of 640px), which scale with the zoom, and so are the thresholds of their own in rich text, the split sections, the progress bar, pagination and the document tab bar. The style check now fails on a px length in a query condition. At the default font size of 16px nothing changes; with a larger default font size the narrow layout comes earlier. @nldd/design-system/breakpoints adds queryBreakpoints (the rem values), and breakpointPx() and rootFontSize() for a width you measure in script; breakpoints keeps its px values. A hide-below or hide-above with a px value of your own still has the problem in Safari: write it in rem.
  • On a small screen nldd-hero keeps the full distance at the top again. Half the distance (8px) put the hero too close to the top bar on mobile, so there it is 16px again, as for the other page sections. On md and lg the top stays at half.
Breaking
  • nldd-badge no longer takes a Rijkshuisstijl color. color is the same set as nldd-status-bar, plus inherit: critical (the default), accent, neutral, warning, success and inherit. A badge is a signal, not a category, and a color of its own clashed with the theme. A badge with color="hemelblauw" or another named color now gets the accent, and says so in the console during development. Pick the color for the whole site with a theme, or use custom-color for a color of its own.
  • nldd-hero no longer takes a Rijkshuisstijl color for its panel. main-background is accent (the default) or base. A color per hero came before themes. A theme now picks the color for the whole site. A hero with main-background="donkerblauw" or another named color gets the accent instead, and says so in the console during development. To keep the color, set the theme on <html> (data-nldd-theme="donkerblauw", with @nldd/design-system/themes/donkerblauw.css) and remove the attribute. Without a theme the accent is lintblauw.

v0.9.0

Compare Source

Highlights
  • Links say where they go to a screen reader. A link to another domain adds "andere website" to its name by itself, in every component with an href. Nobody has to set anything, so nobody can forget it.
  • A table of contents in a sheet takes you to the heading. A link in the collapsed sidebar of nldd-sidebar-section closes the sheet and moves focus to the heading it points at, in view.
  • accessible-label works the same everywhere. It names a navigation list, and nldd-list-item has one too.
  • A step stands beside its title. nldd-step-cell puts its dot at the top of a row with vertical-alignment="top", or beside a first line of any height with marker-offset, so a step with a title and a paragraph no longer has its dot halfway down the text.
  • The corner of a hero without an image is smaller. On a hero with a single title the corner took up most of its height, so the panel looked like a drop. Without media it now takes half the radius, and in any hero never more than a third of the height.
Added
  • A hint for a link to another website. An href to another origin than the page adds a visually hidden "andere website" to the link's name, in one sentence with "opent in nieuw tabblad" when both apply: "Lees de startnotitie, andere website, opent in nieuw tabblad". It works in nldd-button, nldd-icon-button, nldd-link, nldd-card, nldd-avatar, nldd-toolbar, nldd-list-item and nldd-list-item-segment. Only http: and https: links count, a subdomain counts as another website too, and there is no way to switch it off: another domain has its own heading, navigation and title. An external-link icon stays your own choice. The hint is translated in English, Frisian and Papiamento.

  • A design guideline: don't explain the interface, improve it. A sentence that says where to click or what a button or filter does shows that the interface does not say it by itself. People read it only once they get stuck, and it goes stale as soon as the interface changes. Change the label, the order or the component instead. Where a hint is still needed, keep it short and put it next to the part it is about, not in an introduction above.

  • accessible-label on nldd-list-item, the name of the row's action. For a row whose text does not say enough on its own. It replaces the content of the whole row for a screen reader, the supporting text and a status included, so set it only on a row without text of its own, or put everything that matters in it.

  • vertical-alignment and marker-offset on nldd-step-cell, for a step in a row higher than one line. The dot stood in the middle of the row, so beside a title with a paragraph under it, it hung halfway down the text. vertical-alignment="top" puts it against the row's top padding and bottom against its bottom padding, as a whole dot would stand, so a minor dot lines up with a major one. To line it up with what stands beside it, such as the first line of a text cell or an nldd-title, marker-offset says how far below the top of the content the middle of the dot stands, measured after the row's padding, as a length or as a percentage of the content's height. Write it in rem, so the dot moves along when someone sets a larger font size. The track runs to the middle of the dot, so rows still connect.

Changed
  • The hint for a new tab follows the name after a comma, in lowercase. "Lees de startnotitie, opent in nieuw tabblad". The hidden text ran on without a pause, and the hint in an aria-label started with a capital after the comma. nldd-list-item-segment now gives the hint as well.

  • A link in the sheet of nldd-sidebar-section closes it and moves focus to the place it points at. Left to the browser, the page scrolled under a sheet that was still open, and closing it gave focus back to the trigger without scrolling to it, so focus ended up out of sight. The section now closes the sheet, scrolls to the heading and gives it focus with a temporary tab stop, as nldd-skip-link does. A link to another page, in a new tab, with a modifier key or into the sidebar itself is left alone, as is a click you already handled with preventDefault(). The content page pattern no longer needs its own click handler.

  • accessible-label names a navigation list. With type="navigation" it did nothing, and the landmark kept the default name "Navigatie". It now names the landmark, as it names the list and the search field in the other types. An aria-label or aria-labelledby on the element still wins. The page patterns use accessible-label on their navigation lists.

  • The corner of an nldd-hero without media is smaller. On a hero with a single title, the radius of 60px took up more than 80% of a panel 73px high. Without an image the panel is the whole hero, so it now takes the radius of a panel: half, 0.75X on small screens and 1X above. In any hero the radius is never more than a third of the shortest side of the area it rounds, which also protects a hero with a small media-height. Without media the corner applies in every layout, overlap included, and the hero chooses top-right, or top-left for a panel on the right.

Breaking
  • The translation key for the new-tab hint is renamed. components.{name}.opens-in-new-tab-label is now components.{name}.link-hint-new-tab-lowercase-label, next to the new link-hint-external-lowercase-label and link-hint-external-new-tab-lowercase-label, so the three hints of a link sit together. The text always follows a name after a comma, so the default is lowercase: "opent in nieuw tabblad". If you override this text with translations or setTranslations(), rename the key and write the text in lowercase. The old key does nothing anymore.

v0.8.100

Compare Source

Highlights
  • nldd-hero can take the rounded corner of the Rijkshuisstijl. corner rounds one corner of the image and half a one on the panel, in a contained hero with the panel in a corner or along a side.
  • Room to play with typography. nldd-title takes sm-, md- and lg-custom-size for a statement larger than size 1, set per breakpoint and never smaller than size 1.
  • Icons are easier to find. The icon gallery has its own page under Docs › Iconen, where it used to be the last story of nldd-icon. Search every icon and alias there, or see what is new or updated.
  • A design guideline for link text. A link names where it goes: no "klik hier", "lees meer" or "meer info", which say nothing to someone scanning the page or to a screen reader listing its links.
  • The examples follow the design guidelines. Button labels in the imperative, no "Annuleer" next to the primary action, the safe way out first in a destructive dialog, link texts that name their destination, and Dutch text with the fixed example cast.
Added
  • item-max-width on nldd-collection, the largest width of an item in a horizontal scroll. A scroll with only one or two items, such as an agenda that starts small, keeps them at a readable width instead of filling the container. It takes a CSS length such as 400px or 25rem, is never narrower than item-min-width and never wider than the container. Once the items overflow, scrolling, the edge fade and the previous and next buttons work as before. Grid, lanes and stack ignore it. A grid leaves empty columns rather than stretching an item, so the problem does not occur there, and a maximum would change how many columns fit.

  • A design guideline for link text: say where the link goes, no "click here". A screen reader can read every link on a page as a list of its own, and people scanning a page read the underlined words. Out of context, "klik hier", "lees meer" and "meer info" say nothing. The guideline asks for the destination or subject as the link, the distinguishing words first, a different text for every destination, and the format and size of a file. WCAG 2.4.4 accepts a generic link when the sentence around it gives the context. This guideline is stricter, because that context only helps whoever reads the sentence. The examples in Storybook follow it now.

  • corner on nldd-hero, the rounded corner of the Rijkshuisstijl shape language. <nldd-hero corner> (or corner="auto") rounds one corner of the image and lets the hero choose one the panel leaves free; corner="top-left" and the other three choose it yourself. The panel gets a corner at half the radius, the one pointing into the image, and stands against the edge of the image, so a main-width of 33.33% or 50% is that share of the image. The radius follows the ribbon width: 1.5X on small screens, 2X above. It applies with layout="contained" and the panel in a corner or along a side; with overlap or a centered panel the hero stays rectangular and says so in development, as it does for a chosen corner that sits under the panel or a corner with width="full". Without corner the hero is rectangular, as before.

  • sm-custom-size, md-custom-size and lg-custom-size on nldd-title, for a statement larger than size 1. Size 1 tops out at 52px, which is small for a title that has to make an impression. These take any CSS length per breakpoint, with the weight, typeface and line height of size 1. They never go below size 1 at the same breakpoint: a smaller value shows as size 1 and says so in development, so they are no way around the scale for an ordinary heading. There is no plain custom-size on purpose: a breakpoint you leave out keeps the size from size, so a title made large for a wide screen does not break a narrow one.

  • no-results on nldd-table, for a table whose rows are all filtered away. An empty table and a filtered one said the same thing, because the table had only empty. When every body row is [hidden], the table now shows [slot="no-results"]: say that nothing matches and how to get rows back, and keep empty for a table that has no rows yet. Without no-results it falls back to empty, the same as nldd-list.

Changed
  • nldd-modal-dialog says so in development when it opens with one action. A dialog with one button offers nothing to choose, which the design guidelines advise against. Tell the user with an nldd-notification or an inline message instead, or give the dialog a real choice. It warns once per dialog.

  • The component docs point to the design guidelines where an attribute invites misuse. disabled and loading on the buttons, nldd-dropdown as a last resort after visible options and a combo box, when an nldd-modal-dialog is right, and horizontal scroll in nldd-collection as more than a carousel. The examples in Storybook follow the guidelines as well: labels in the imperative, no "Annuleer" next to the primary action, the safe way out first in a destructive dialog, and Dutch text with the fixed example cast. They are built from the system's own components too: nldd-container for layout, nldd-text for captions with an nldd-spacer to the example, and cells inside an nldd-list, so the code you copy from Storybook has no inline layout CSS.

  • The icon gallery has its own page, Docs › Iconen. It was the last story of nldd-icon, where nobody looking for an icon name thought to look. The page shows every icon and alias, two across on a phone, with a search field and a filter for the new and updated ones.

  • Inline elements in nldd-text look as they do in nldd-rich-text. <em> is italic, <a> an underlined link, <code> sits on a tinted surface in the monospace font and <mark> is highlighted, beside the bold <strong> it already had. A short text with a code word or a link no longer needs a rich-text block.

  • The form pattern allows a format requirement on an optional field. An optional field is not required, and an empty value passes every requirement, so a phone number you may leave out can still be checked when it is filled in.

  • The title of the wordmark in nldd-top-navigation-bar is semi-bold. It was medium, close enough to the subtitle below it that the two read as one block. One step heavier sets the name apart without competing with the page title.

  • A menu under an nldd-menu-bar-item opens against its indicator. The indicator stops 6px short of the item's bottom edge, and the menu hung off the item, so it opened with a gap below the gray box that marked the open item. It now touches the indicator, which keeps its rounded corners.

Breaking
  • Items in a horizontal-scroll nldd-collection stop at 480px. One or two items that fit grew to the full width of the container, so a card of 320px became more than 1000px wide on a desktop. They now grow up to 480px and stay at the start. An item-min-width wider than 480px raises the limit with it, and item-max-width sets your own; item-max-width="100%" brings back the old behavior.

  • item-width on nldd-collection is now item-min-width. It was a minimum in every layout: in a grid the narrowest a column gets, in a horizontal scroll the width an item never shrinks below. The new name says so, and pairs with item-max-width. There is no alias. An item-width left on a collection does nothing, so its items fall back to the default of 280px; in development the collection says so once, with the renamed attribute. Rename the attribute on every nldd-collection.

Fixed
  • nldd-container width="fit-content" takes the width of its content. The container measures its own width for its breakpoint padding and gap, and that measuring left a fit-content container 0px wide, so whatever was in it piled up on its neighbours. A fit-content container no longer measures itself; its breakpoints follow the container around it.

v0.8.99

Compare Source

Highlights
  • nldd-menu can be a navigation. With variant="navigation" it is a list of links instead of a menu of actions, so a submenu in the site navigation is read as what it is.
  • Tabs that do not fit go to a menu. On a narrow screen nldd-tab-bar puts the tabs that do not fit behind a "Meer tabs" button instead of cutting off every tab, and the current tab always stays in the bar. In an nldd-toolbar the other items make room first.
  • Closing tabs one after another keeps the next close button under the pointer. The tabs in an nldd-document-tab-bar keep their width while you close them, and grow into the space once the pointer leaves the bar.
  • Notifications can be raised from code. NLDDNotification.show() creates, shows and cleans up a notification, which is the way to raise one from a framework.
  • nldd-visually-hidden is new, for text that only a screen reader reads, such as the header of a column of checkboxes.
Added
  • variant="navigation" on nldd-menu, for a submenu in a site navigation. A submenu in nldd-top-navigation-bar was a menu of actions: role="menu" with menu items. For site navigation that is the wrong role, since a screen reader switches to an application mode in a menu where a visitor expects a list of links. With variant="navigation" the menu is a list (role="list") and each item a list item around a real link; it looks the same. Tab reaches every link, the arrow keys, Home and End move between them, Escape closes and returns focus to the trigger, and the menu closes when focus leaves it. The nldd-menu-bar-item that opens it says aria-expanded and no longer aria-haspopup="menu". A submenu and a group inside it follow along. Checkbox and radio items, shortcuts and filter() belong to actions and warn in development here. Give every item an href, and keep the default variant for menus that do things, such as an account menu or a language switch.

  • NLDDNotification.show(), to raise a notification from code. An nldd-notification places itself, which is why it does not matter where you write it. It also means a framework cannot render one: the element is no longer where the framework left it, so a keyed list (v-for with a :key) fails on its next render and a removed row leaves its notification on screen. NLDDNotification.show({ text, supportingText, variant, icon, duration, actions }) creates the element, shows it and removes it once it is dismissed. An action is { text, onClick }, at most two, and a click on one takes the notification away as well. It returns a handle with dismiss() and update(options). An update changes the message, puts the notification in front and starts its clock over, so a status that changes often stays one notification, and the clock still pauses on hover and focus. The declarative element stays as it is; raise notifications with show() from a framework.

  • nldd-visually-hidden, text for a screen reader only. It stays in the accessibility tree and the reading order and takes no room on the page. Use it for a name that is visually redundant, such as the header of a column of checkboxes. The recipe is the one the components already use inside, so a site no longer needs a .visually-hidden class of its own. It is not for repairing structure that is missing, nor for a status: a status that matters to a screen reader matters to anyone, so show it.

Changed
  • Tabs in nldd-tab-bar that do not fit go to a menu instead of being cut off. On a narrow screen every tab was cut off with an ellipsis, and the rest of its text could not be read anywhere, often the very part that told the tabs apart. Tabs that do not fit now go behind a "Meer tabs" button at the end of the bar, in a menu. The current tab always stays in the bar. While tabs are in the menu, the bar fills its container and the tabs in it share the width in proportion to their own; choosing a tab in the bar leaves the rest where it is, and one chosen from the menu swaps places with the last tab in the bar, so the bar does not jump when you switch. In an nldd-toolbar the other items go to the toolbar's menu first; when it is the tab bar's turn, it narrows down to the current tab beside its own button, and only then goes into the toolbar's menu as a whole. Tabs are hidden, never moved in the DOM, so a framework that renders them finds them where it put them. Only a tab that does not fit on its own is still cut off. The label of the button can be translated with components.tab-bar.overflow-action.

  • nldd-code-viewer scrolls across its whole box. The padding sat on the box and the scrolling on the code inside it, so a long line stopped short of the edge, the scrollbar was inset, and the room for the copy button kept the whole right side free. The scroll area is now the box itself, with the padding inside it: a line scrolls out to the edge, the scrollbar runs from corner to corner, and at the end of a long line the last character stops beside the copy button instead of behind it.

  • Closing tabs in nldd-document-tab-bar one after another keeps the next close button under the pointer. Closing a tab with the pointer used to spread the others over the space at once, so the close button of the next tab moved away from the pointer. The tabs now keep their width until the pointer leaves the bar, and the next close button slides in under the pointer. Then they grow into the space, without motion for anyone who asks for reduced motion. Closing the last tab of the row, with none left in the overflow, lets them grow into the space at once; closing from the keyboard spreads them at once.

Breaking
  • label on nldd-toolbar is now accessible-label. It was the one place where an accessible name was called label; every other component says accessible-label, and on nldd-toolbar-item label is the visible text below the item, which made the two easy to mix up. There is no alias: a label left on a toolbar does nothing, so the toolbar loses its name. Rename the attribute on every nldd-toolbar. The label on nldd-toolbar-item stays as it is.
Fixed
  • Text in an nldd-popover under a button can be selected. nldd-button, nldd-icon-button, nldd-menu-bar-item and nldd-menu-bar switch text selection off for themselves and everything in them, and a popover in their popup slot is in them. The popover now switches it back on, so its text can be selected and copied.
  • A card that is a link or button no longer stays pressed when a touch turns into a scroll. The pressed shade of nldd-card came from :active, which can flash or linger while a touch scrolls the page. The card now sets it on a press and clears it on release, or when the browser hands the touch to scrolling, as nldd-list-item already did.
  • The ribbon of nldd-top-navigation-bar starts at the top of the bar again with logo-href. With a link on the logo the ribbon sat in a span as an inline image, on the text baseline with room below it for descenders, and centering that taller box lifted the ribbon 2 to 4 pixels above the bar. Anything placed above the bar, such as an nldd-status-bar, was overlapped by it.
  • The current item in the menu sheet of nldd-top-navigation-bar has aria-current. Behind the Menu button on a narrow screen the current item was only painted. The list in that sheet is a navigation list now, named after the global menu bar, so the link of the current item carries aria-current with the current-type of its menu bar item.

v0.8.98

Compare Source

Highlights
  • Navigation lists can nest. A sub-page in an nldd-list type="navigation" goes in its parent row's slot="children" and is then a list inside a list item, where it used to be an indented row in one flat list.
  • A round of accessibility fixes. A skip link that could silently do nothing, a tooltip you could not close with Escape while pointing at it, a copy failure that vanished after two seconds, and a scrolling sidebar that Firefox focused without a role or a name.
  • A rule in nldd-validation-list no longer rejects an empty optional field. A match or minlength under a field that may stay empty used to block every submit that left it empty. See Breaking if a field relies on the old behavior.
Added
  • Sub-pages in nldd-list type="navigation". Put the rows of a sub-level in their parent row's slot="children", the slot a tree already uses. The parent renders them as a list inside its list item, so a screen reader hears the level and how many there are; an indent made with a spacer cell alone stayed one flat list. They are always shown and the arrow keys walk them like any other row. Indenting is still yours: add an nldd-spacer-cell per level.

  • max-height on nldd-code-viewer. A CSS length that caps the block, for a long file in a frame of its own: the viewer grows up to it and scrolls vertically beyond it. There was no supported way to do this, short of a stylesheet in the shadow root.

Changed
  • An nldd-menu-bar-item that shows only its icon has a tooltip. With icon-only, or with content-priority="icon" in a compact bar, the text was gone for anyone not using a screen reader. A bar is compact at 200% zoom on a desktop too. The text now shows on hover and focus.
  • Escape closes an nldd-tooltip and nothing else. While a tooltip is showing, by hover or by focus, the first Escape closes the tooltip only. A dialog, sheet or menu around it stays open and closes on the next press, where one press used to close both. The tooltip takes the key in the capture phase on document and stops it there, so a handler of your own for Escape, in a search field or a combobox for instance, does not hear that first press either.
  • A link stays a link in the overflow menu of nldd-menu-bar. An item with href used to become a button in the "Meer opties" menu. It is an <a> now, so it opens in a new tab like the item in the bar, and a click handler on the original item still runs and can cancel the navigation.
  • A failed copy in nldd-code-viewer stays on screen. "Kopiëren mislukt" disappeared after two seconds like the success message. It now stays until you leave the button, press Escape or try again. The button takes focus on click, so leaving it works in Safari too.
Breaking
  • Rules in nldd-validation-list skip an empty value unless the field needs one. An empty value used to fail match, minlength and maxlength like any other. It now passes them, the way the native pattern and minlength leave an empty input alone, unless an item has required or the control itself is required. If you counted on minlength to stop an empty field, add required to the control or add an item with required. For example: <nldd-validation-item id="password-required" required>Vul een wachtwoord in</nldd-validation-item> next to the minlength item.
Fixed
  • nldd-skip-link reaches its target, and Tab continues from there. Three things could leave it doing nothing. Without href it moved focus to the next sibling whatever that was, so a <noscript>, a <script> or a hidden element right after it left the button dead; it now passes those over, and warns in development when nothing follows at all. In Safari the next Tab then left the page when the target was an nldd-* component, because WebKit skips everything inside a shadow host with tabindex="-1". And with an href, Safari kept focus on the link. The skip link now moves focus itself in both forms, so the target needs no tabindex of its own.
  • Escape closes an nldd-tooltip that was opened by pointing at it. Escape only worked while focus was inside the tooltip's trigger, so with the pointer on a button and focus elsewhere it stayed open (WCAG 1.4.13).
  • The current page has aria-current in the overflow menu of nldd-menu-bar. The item was marked visually, but a screen reader heard nothing.
  • An nldd-code-viewer that scrolls vertically is reachable by keyboard. The scroller only became a tab stop with a role and a name when a line was too wide, never when the block was too tall, and never with wrap. It now measures both directions.
  • The scrolling sidebar of nldd-sidebar-section has a role and a name in Firefox. Firefox puts a tab stop on anything that scrolls, and that was an unnamed div inside the landmark. The aside itself scrolls now.

v0.8.97

Compare Source

Highlights
  • Four page patterns for a website. Home, topic page, navigation page and content page now sit together under "Patronen/Pagina's", each with a running example and a test. The home is the starting point of a site and is itself the menu, a topic page is the home for a topic lower in the site, a navigation page helps visitors find the pages below it, and a content page holds the details at the lowest level. A page structure pattern describes the frame all four share, with its header and footer.
  • The text panel of nldd-hero overlaps the image. By default the text panel now falls over the bottom of the image and runs on below it, as far as its content needs. The image keeps a fixed height and sets the mood, the panel carries the page, and a long text no longer has to fit inside the photo.
  • nldd-app-view is now nldd-shell. It is the outer layer of a website as much as of an application, and the old name suggested only the second. Every page needs the rename, since there is no alias; see Breaking.
  • Icons are getting a typeface of their own. We are drawing a typeface for the letters and digits inside icons: a simpler, more geometric version of RijksSans. The twelve icons that hold a letter or a digit are the first in it: heading-1 through heading-6, numbered-list, square-1, bold, strikethrough, underlined and text-format-size.
Added
  • layout on nldd-hero, with overlap (the default) and contained. In overlap the text panel falls over the bottom of the image by overlap-size (any CSS length, 160px by default) and runs on below it as far as its content needs. The image keeps a fixed height (320px on md, 400px on lg, or your own media-height or media-aspect-ratio), so it stays the same whatever the content, and the overlap stays the same whatever the image. A panel shorter than overlap-size ends inside the image; that is up to you, and it says so in development. contained keeps the panel on the image, in any of the eight positions.
  • An icon slot on nldd-menu-bar-item, for something other than an icon in that place: an nldd-avatar for the person who is signed in, for instance. It gets the size of an icon and follows content-priority and icon-only as the icon does, so with content-priority="icon" only the avatar is left on a narrow screen and the text becomes the accessible name.
  • media-height on nldd-hero, a fixed height for the image in any CSS length, next to media-aspect-ratio. It wins over the ratio.
  • vertical-alignment on nldd-one-half-one-half-section, nldd-two-thirds-one-third-section and nldd-one-third-two-thirds-section: top (the default), center or bottom places the shorter column next to the longer one, such as text beside a taller image. It only applies while the columns stand side by side; stacked, they follow each other.
  • grow on every page section, to choose which section takes the height a page has left. Until now that was always the last section, so the footer sat at the bottom of a short page; with grow you can let a hero or a middle section fill instead. Without grow nothing changes. nldd-page marks the growing section with data-growing, a state it derives and never writes back into grow.
  • A page structure pattern (page-structure.md in nldd-design-build), for the frame every page of a website shares: the nldd-shell around everything, one section per block of content, a surface made with background, and one h1. Its header is the bar on top: search and a language menu in the utility slot of the top bar, a back button to the page above on every page but the home, and a skip link around it. Where a site has a personal part, a third item signs you in, and becomes a menu with your name, your profile and a way to sign out once you have. A status bar, when there is something every visitor has to know, goes above the bar. Its footer has the breadcrumbs in a row of their own, a main part each website fills in itself, and a legal bar that links straight to Contact, Toegankelijkheid, Privacy and Over deze website: grouping the privacy statement under an "about" page alone is not enough, since the European data protection guidelines ask for a direct link on every page.
  • Topic page and navigation page patterns (topic-page.md, navigation-page.md in nldd-design-build). A topic page opens with a hero holding a short explanation and its one main task, then has text beside an image, link cards to pages wherever they already live, a list of the pages below the topic, and related topics as link cards in a tinted section at the bottom. The home page shows the same kinds of sections: an image beside text in an nldd-one-half-one-half-section, cards with an intro, and a list of topics beside its title and a short text, laid out like the navigation page. A navigation page shows its choice as a navigation list next to the title and a short intro, in an nldd-one-third-two-thirds-section, or as a full-width collection of link cards below them; the pattern shows both.
  • nldd-list-item and nldd-list-item-segment have current-type, the aria-current value a current row or segment puts on its link. It was always page, which is wrong for a table of contents: every row there points at a section of the page you are already on. Set current-type="location" there. Same attribute and values as on nldd-menu-bar-item.
Breaking
  • main-width on nldd-hero follows the content. 1/2, 2/3 and 3/4 are gone: half the width was too narrow for text on md, and three quarters too wide to read on a large screen. The panel is now as wide as its content needs, between 480px and 640px and never wider than the image allows (main-width="auto", the default). full stays, and any CSS width (560px, 60%) sets it exactly, still never wider than the image allows. A fraction is not a CSS width, so it falls back to auto and says so in development.
  • A hero with an image overlaps by default. nldd-hero used to keep its text panel on the image; it now lets it fall over the bottom edge and run on below, and takes only the horizontal side of main-position. A hero whose panel stands at the top or along a side (top-left, left and so on), or whose panel is too short to reach below the image, needs layout="contained" to stay as it was. A hero without an image does not change.
  • nldd-app-view is now nldd-shell. It is the outer layer of everything, a website as much as an application, and "app view" suggested it was only for the second. Rename the tag in every page, the import (@nldd/design-system/app-view becomes /shell) and the class (NLDDAppView becomes NLDDShell). There is no alias: an nldd-app-view left behind is an unknown element, so the page loses its background and its scroll mode, and the document font, which the stylesheet sets once a shell is on the page. A CSS selector on nldd-app-view needs the new name too.
  • data-width in nldd-rich-text is now data-rich-text-width. The attribute that moves one child to another width zone (main, wide or full) said neither what it belonged to nor that it only works inside a rich text, and it read like the width of a page section, which is something else. There is no alias: a data-width left behind does nothing, and the child falls back to the zone of its kind.
  • is-last is gone from page sections. nldd-page marks the section that takes the leftover height with data-growing instead of the is-last class, since a framework's class binding rewrites class and could wipe it. If you styled .is-last yourself, use [data-growing].
Changed
  • nldd-hero no longer uses height. On the other page sections height is a minimum height for the whole section; on a hero it stretched the text panel once that sat below the image. The height of a hero comes from its image: media-aspect-ratio, or the new media-height. A hero given height ignores it and says so in development.
  • The text panel of nldd-hero always stands on the image. The image in a hero sets the mood and is never the main content, so the panel no longer sits against its edges or beside it. On md and lg it keeps a section gap (24 or 32px) from the edges, so it reads as a panel on the image rather than a frame cut out of it. main-width="full" used to put the image in a strip of its own above or below the panel; it is now a strip across the image, the same gap from the sides. On mobile the image comes first, also for a top position, and the panel follows below it, indented by 16px and overlapping the image by 48px. main-position gains bottom-center and top-center.
  • Page sections, nldd-container, nldd-sheet and nldd-image no longer write their defaults into the DOM. Every section carried width="" and background="inherit", the hero media-aspect-ratio="" and an image without a source src="", whether or not anyone set them. They now only appear when they differ from the default, as the other attributes in the system already did. If you selected on one of those empty or default attributes, select on the value you set instead.
  • The overline and supporting text in nldd-text-cell and nldd-title-cell wrap with text-wrap: pretty, like the main text of a text cell already did, so a description over two lines no longer ends on a single word.
  • A component in nldd-rich-text stays within the line of text. Every nldd-* component used to get the full width, so an nldd-box or nldd-card with a sentence in it grew past the text around it. A component now reads at the main size, like the text, unless it needs the room: nldd-collection and nldd-container keep the full width. nldd-image, nldd-table and nldd-step-bar get the wide accent, like other media and a plain table; an nldd-table and an nldd-step-bar used to get the full width. Code reads at main too: a pre and an nldd-code-viewer used to span the full width, however short their lines, and now fill the line of text and scroll inside their block when a line is longer. Other elements that are not text, such as details or form, read at main too. Set data-rich-text-width="wide" or "full" on a child to give it more.
  • Headings in nldd-rich-text keep their size on every width. They used to grow with the screen, which made an h2 on a wide screen more than twice the size of the text around it (41px next to 18px), so an article broke into blocks at every heading. They now keep the size they have on a phone everywhere (an h2 is 29px). Page and section titles in nldd-title still grow, so the step from a page title to the headings in the text is clearer than before.
  • Every page section grows. Only the hero, the sidebar section and the simple section used to take the leftover height as the last section; a page that ended on one of the other four left the footer floating up. Now all seven do. Outside an nldd-page, a section no longer grows just for being the last child; give it grow.
  • nldd-hero sits closer to the top bar. Its top padding is now half that of the other page sections (8, 16 or 24px instead of 16, 32 or 48px). The full distance is meant to separate two sections, and right under the top bar, where a hero almost always sits, it read as a gap. The bottom keeps the full distance. Set padding-top to place a hero elsewhere.
  • nldd-image shows where an image belongs. Without an image (no src, srcset, lqip or slotted media) it used to leave an empty gap, or nothing at all without aspect-ratio. It now shows a neutral area with an image icon, in the box, shape and caption a real image would get, and 16/9 when there is no aspect-ratio, or the box its parent gives it, such as the media area of a hero. A prototype or a pattern gets the right composition before there are photos, and an image someone forgot stands out instead of leaving a silent hole. While the built-in image loads without an lqip, the same area shows without the icon, and it goes once the image is in. The lqip gradient is now called a loading preview in the docs, to keep it apart from this.
  • Twelve icons with letters or digits are redrawn, in the typeface we are drawing for icons. heading-1 through heading-6 have a new H and new digits, numbered-list and square-1 have new digits to match, and bold, strikethrough, underlined and text-format-size are drawn again. The names stay the same.
  • The profile icon is a contact card. profile and account both pointed at the person in a circle, while an account and a profile are two things that often stand one above the other in the same menu. profile now gives the contact card (person-text-rectangle); account keeps the person in a circle. If you used icon="profile" for the account itself, use account.
  • nldd-status-bar says where it belongs. The bar is the first thing on the screen, above nldd-top-navigation-bar or nldd-top-title-bar and across the whole app. Its docs say so now, and below a top bar it warns in development. A top bar in a sheet or dialog does not count.
  • The sidebar of nldd-sidebar-section no longer draws the eye. Beside the main content it was a tinted box, which pulled attention away from the text it sits next to. It now takes the surface of the section around it, base on a plain page and tinted on a tinted section, and is edged by a divider line, as the panes of a split view are. It still reads as a block, which it needs to be because it can scroll, and a current row in a list inside it now stands out against it. The sheet on narrow screens is unchanged.
  • The content page pattern is now a home page, and the content page is a new one. What used to be content-page.md, with a hero, cards and a call to action, is home-page.md. Its hero now holds the main goal as a button, and each card has a button that leads on. content-page.md now describes a page that explains one thing: the title as the heading, a table of contents in the sidebar of an nldd-sidebar-section that becomes a button under the title on narrow screens and marks the section you are reading, or, for a short page with fewer than three headings, no table of contents and the action beside the text, or no action at all, the text in a rich text with the action below it, and the breadcrumbs in the footer. The frame every page shares, with its header and footer, has its own pattern.
Fixed
  • An nldd-image in the media slot of nldd-hero fills the image area. It took the height of the photo instead, so a portrait photo showed only its top, and a lazy image that had not loaded yet had no height at all, never came into view and never loaded. The hero now tells the image to fill its area, and the photo is cropped from the center.
  • The package no longer ships our sample images. The build copied the folder with the photos the Storybook stories use into dist, twice, along with a page of color palettes. Over 1 MB that no consumer uses is gone from the package.
  • A page scrolls when its shell is defined after it. A page or split view that connected before nldd-shell was defined started out on its own, and nothing made it register once the shell was: in Chrome and Firefox the document did not scroll, in Safari a sidebar did not stick, until you resized the window. That happens whenever a section is imported before the shell, since nldd-sidebar-section defines nldd-page, and an app cannot control that order with code splitting and lazy routes. A page, a split view or a pane now waits for the shell, sheet or modal dialog above it to be defined and registers then.
  • A long word in a heading in nldd-rich-text no longer runs out of the column. The safety net that breaks a word wider than the column was only on paragraphs and list items; headings have it too now. A heading still never gets a hyphen.
  • A chevron at the end of a row no longer touches the text. The application and edit-in-a-sheet patterns put the chevron straight after the text cell; there is now an nldd-spacer-cell between them, as in the other patterns.
  • Link cards in the patterns have a name. The page patterns said a card with href takes its accessible name from its content. It does not: the link lies over the card as an empty anchor, so it needs accessible-label. Every link card in the patterns now has one, set to the card's title.

v0.8.96

Compare Source

Highlights
  • Twelve new icons. Seven file icons for a document's format: file-pdf, file-markdown, and file-odt, file-ods, file-odp, file-odg and file-odf for the OpenDocument formats, each also answering to {format}-document, such as pdf-document. And microscope, share-network, power-plug-socket (also plug-connected) for a plug in its socket, and subscript and superscript for text formatting.

  • nldd-step-bar and nldd-step-cell. The step indicator and the timeline track cell are renamed after what they draw: steps, across and under each other. See Breaking.

  • The --components-* layer is gone. A component's values now sit as local variables in its own stylesheet, and what several components share became a semantics token. Restyling one component through a public token was a quiet way to make it differ from the rest. If you want a component to change, ask in an issue. See Breaking.

Added
  • File icons file-pdf, file-markdown, file-odt, file-ods, file-odp, file-odg and file-odf, with the aliases pdf-document, markdown-document, odt-document, ods-document, odp-document, odg-document and odf-document.

  • Icons microscope, share-network, power-plug-socket (with the alias plug-connected), subscript and superscript.

  • --semantics-brand-ribbon-color, next to the ribbon widths: the color of the Rijksoverheid ribbon, which nldd-top-navigation-bar and nldd-page-footer both draw. It does not follow a theme's accent color, since the ribbon does not either.

Changed
  • Every local variable in a component carries the component's name, such as --_button-background-color instead of --_background-color. A custom property inherits through shadow boundaries, and a generic name on one component reached the elements of another slotted inside it. Locals were never meant to be set from outside; if you did set one, it now has a different name.
Breaking
  • nldd-step-indicator is now nldd-step-bar, and nldd-timeline-track-cell is now nldd-step-cell. They are one family, the steps of a process across and under each other, as nldd-progress-bar and nldd-progress-circle are one family for how much is done. "Timeline" said less than the cell does: most of all it draws steps. Rename the tags, and the classes and imports if you use them:

    Was Now
    nldd-step-indicator, NLDDStepIndicator nldd-step-bar, NLDDStepBar
    nldd-step-indicator-item, NLDDStepIndicatorItem nldd-step-bar-item, NLDDStepBarItem
    nldd-timeline-track-cell, NLDDTimelineTrackCell nldd-step-cell, NLDDStepCell
    @nldd/design-system/step-indicator @nldd/design-system/step-bar
    @nldd/design-system/timeline-track-cell @nldd/design-system/step-cell
    translation keys components.step-indicator.* components.step-bar.*

    The attributes stay the same. An old tag is an unknown element now and renders nothing, without a warning, so search your markup.

  • The --components-* custom properties no longer exist. If you set or read one, nothing happens now, without a warning. Most were never meant to be touched. The ones that more components share moved to semantics:

    Was Now
    --components-code-viewer-token-*-color --semantics-code-syntax-*-color
    --components-list-item-is-*, --components-list-item-indicator-* --semantics-list-items-is-*, --semantics-list-items-indicator-*
    --components-menu-bar-item-inline-padding --semantics-menu-bar-items-inline-padding
    --components-menu-box-shadow --semantics-overlays-box-shadow
    --components-menu-item-is-highlighted-background-color / -content-color --semantics-controls-is-highlighted-indicator-color / -contrast-color

    Search your own CSS for --components- to find what this affects.

Fixed
  • A transparent nldd-toggle-button with variant="text" fills when it is on, also with a selected-icon. A transparent toggle with a selected icon stays without a fill and lets the change of icon show that it is on. With variant="text" the icon does not render, so nothing changed at all when you switched it on.

  • nldd-toolbar no longer leaves an item in the overflow menu that fits. When the toolbar measured while the web font was still loading, an item could take its width from the fallback font, go into the menu, and stay there once the font arrived: a hidden item has no width to watch. The toolbar now measures again when the fonts have loaded. In the toolbar-with-actions pattern at 375px the tab bar went into the menu in 7 of 10 page loads.

v0.8.95

Compare Source

Highlights
  • The plugin is now nldd-design-system, and it moved to the NLDD marketplace. Install it from NederlandseDigitaleDienst/ai-plugins as nldd-design-system@nldd. That marketplace is tool-independent, and the plugin now ships a Cursor manifest next to the Claude Code one. An existing nldd@nldd-plugins install keeps working and keeps updating until 1 March 2027, when the marketplace in this repository goes away. The README has the four commands to move over.

  • The current step in nldd-step-indicator is marked on the step itself, with status="current" on the nldd-step-indicator-item, instead of a number on the parent. Move the attribute when you upgrade. See Breaking.

  • A title in nldd-toolbar keeps its width. Buttons move into the overflow menu first, and the title only truncates once none is left.

Added
  • nldd-design-migrate covers sites built by a static site generator (MkDocs, Hugo, Eleventy). Leave the authors' Markdown alone and convert the rendered HTML in a build hook, take the bundle from the registry without a bundler and pin it with its integrity hash, and decide up front what is left without JavaScript and what loading the whole bundle on every page costs. The behavior check now also strips the base path a site runs under, because a pull request preview runs under a different one than production.
Changed
  • A title in nldd-toolbar keeps its own width while items can still move into the overflow menu. It used to shrink first: next to a few buttons a title like "Aanvraag A-1042" came down to "Aanvraag A-…", or to nothing at all, while every button stayed. Now the items go first, in priority order, and the title only truncates once none is left to move. min-width on nldd-toolbar-title defaults to the width of its text, up to max-width. Set min-width="0" for the old behavior.

  • Only the ribbon and the wordmark text in nldd-top-navigation-bar take a click. The logo link spans the whole width beside the ribbon, which keeps the ribbon centered, and all of that space used to be clickable. It is still one link with one tab stop, named by the wordmark.

  • nldd-blockquote wraps with text-wrap: pretty, the quote as well as the attribution, so neither ends on a single word on its last line.

Breaking
  • The current step in nldd-step-indicator is status="current" on the step. It was a number on the parent (current="2"), which pointed at the wrong step as soon as an app left one out. Now it is the same status a step already had, with the same three values as nldd-timeline-track-cell: current marks where you are and the parent derives the rest from it, while past and future stay an exception for one step. With no step marked, step 1 is current, and with more than one the last wins. Move the attribute: <nldd-step-indicator current="2"> becomes status="current" on the second item. A leftover current on the parent no longer does anything, and a dev build says so in the console, also when a framework sets it later.

  • The long form of a skill name is /nldd-design-system:nldd-design, no longer /nldd:nldd-design, because the prefix follows the plugin name. This holds for existing installs too, from their next update. A permission rule such as Skill(nldd:nldd-design-build) or a hook that matches on the long form stops matching, without an error. The short form (/nldd-design) is unchanged, and so is the skill an assistant picks by itself. The README has a search that finds the places to change.

Fixed
  • Running text no longer grows when a phone turns to landscape. iOS Safari enlarged the paragraphs in nldd-rich-text while the titles kept their size. @nldd/design-system/styles now sets text-size-adjust: 100% on html, in the reset layer, instead of on nldd-rich-text. If you load only the tokens, set it on your own root.

  • The stretching ribbon in nldd-top-navigation-bar is limited to Safari, and to every browser on iOS. Chrome does not draw anything above the top of the page, so on a pull it showed only the piece that holds still at the top, and a hard pull opened a gap between that piece and the logo. Chrome and the other non-WebKit browsers now show the plain gap above the ribbon again, as they did before 0.8.94.

v0.8.94

Compare Source

Highlights
  • The package speaks more languages. One call, setTranslations(enUS) at startup, turns every component English, including the ones another component builds out of your reach, such as the activity indicator in a loading button and the calendar in a date field. US English ships complete, with concept sets in Frisian and in Papiamento as written on Curaçao and Bonaire and on Aruba. Docs/Vertalingen in Storybook explains the layers.

  • nldd-text-editor checks the spelling and handles typeaheads better. It checks the running text and leaves code, addresses and mentions alone. A typeahead query takes accents and a +, a list can decide what may follow its trigger, and an empty list says why instead of closing without a word.

  • nldd-toggle-button can be quiet. It takes four appearances from nldd-button, the two transparent ones included, and with selected-icon a transparent toggle stays without a fill when on: a "Volgen" toggle goes from plus to check-mark and keeps its label.

  • The ribbon in nldd-top-navigation-bar stretches when the page is pulled down, instead of opening a white gap above it.

  • Menus line up, and use fewer icons. One checkbox or radio item gives the whole nldd-menu its check-mark column, so the text of every group starts at one line. A new design guideline says when an icon in a menu adds something, and when it is only filler.

  • Button bars and split buttons work on a colored surface. nldd-button-bar and nldd-split-button take inherit-tinted and inherit-filled, like the buttons inside, instead of a gray block. The inherit buttons now keep one color through hover, press and expanded, so their label keeps the contrast the surface gives it.

  • Attributes say what they do. variant is appearance on nine components where it was a designed style, level on nldd-timeline-track-cell, and mode is variant on nldd-progress-bar and nldd-progress-circle. The values stay the same; search your markup, since a leftover attribute is ignored without a warning. See Breaking.

Added
  • Storybook opens on an introduction. Docs/Introductie says what the system is, how to install it and load the styles, where the components, patterns and design guidelines are, and how to add the Claude Code plugin. It used to open on Button, the first story in alphabetical order. Docs now sits at the top of the sidebar, with the introduction and the design guidelines first.

  • setTranslations() sets the texts for the whole package. Import it from @nldd/design-system/translations and call it once at startup. A component now looks a text up in four layers: an attribute on the element, its translations property, the package-wide layer, and the Dutch default. Calling it again re-renders the components on the page, so a language switch at runtime works too. In development it warns about a key no component knows, which is what an override does after a key is renamed.

  • A complete US English set, @nldd/design-system/translations/en-US, and the Dutch defaults as a template, @nldd/design-system/translations/nl. Spread the English set and add your own keys behind it to change a few texts: setTranslations({ ...enUS, 'components.activity-indicator.loading-label': 'Please wait' }).

  • Concept translations in Frisian (translations/fy) and Papiamento as written on Curaçao and Bonaire (translations/pap-CW) and on Aruba (translations/pap-AW). Every text is translated, also where the wording is a guess, since correcting a text is easier than writing one. No native speaker has checked them yet: report a better wording as an issue and they improve with each release.

  • no-filter on nldd-combo-box and nldd-token-field leaves the options as they are while typing, for a list your server already filtered per keystroke. Without it the field hides every option that does not contain the typed text, which also hides a server match on, say, an e-mail address. The part of an option that matches the typed text is still marked.

  • A typeahead in nldd-text-editor says why its list is empty. It closed without a word, so whoever typed @ could not tell "nobody matches" from "mentions do not work here". Where the list would be it now says "Typ om te zoeken" for an empty query and "Niets gevonden" for one without matches, both translatable. emptyText on a list, and mentionEmptyText for the built-in @, are called with the query and can say more, such as "Kies eerst een kanaal bij Aan"; return null to close without a word, as before. The message is a status a screen reader announces, not an option you can select.

  • A typeahead list in nldd-text-editor decides what may follow its trigger. query on a list, and mentionQuery for the built-in @, take a regular expression for the text after the trigger. A list of people can allow one space, so @sam jansen finds the right Sam. Lists on one trigger share the query of the first that sets one.

  • inherit-tinted and inherit-filled on nldd-button-bar and nldd-split-button, for a group of buttons on a colored surface. The buttons inside already had them, but the bar kept its gray surface behind them. Like a loose button, the group now takes its colors from the text color around it, and inherit-tinted draws its see-through surface once for the whole group, so the tint does not stack.

  • A design guideline on icons in menus. Icons are often used as filler, but are usually not needed and then do not help: add one only where it recognizably belongs to the item and helps people find or understand it, use the same icon for the same action everywhere, and leave it out when no icon makes the action clear at a glance. See Docs/Ontwerprichtlijnen under "Visueel en layout".

  • appearance on nldd-toggle-button and nldd-toggle-button-group: neutral-tinted (the default), neutral-base, neutral-transparent and accent-transparent. A toggle among transparent buttons, such as in a row of light actions under a message, stood out as a gray block. The transparent appearances have no surface at rest; when on, the toggle fills, so the state does not rest on a color alone. neutral-base is for a tinted surface. nldd-toggle-button-group forwards appearance to its buttons, as it does size. New tokens: --semantics-buttons-neutral-transparent-is-selected-* and --semantics-buttons-accent-transparent-is-selected-*.

  • selected-icon on nldd-toggle-button shows another icon while the toggle is on, such as plus to check-mark on a "Volgen" toggle whose label stays the same. On the transparent appearances it replaces the fill: the toggle stays quiet when on, and the change of shape says it is on. On a surface, the surface fills as before.

  • appearance="neutral-base" on nldd-segmented-control, for a segmented control on a tinted surface, as nldd-button-bar has it. The selected segment keeps its fill. For a quiet row without a track, use nldd-toggle-button-group with type="radio" and a transparent appearance.

  • The font files are exported as @nldd/design-system/fonts/*. A site that serves the fonts itself without a bundler, such as a static site that only publishes its own folder, had to copy the woff2 files from node_modules into its own repository. A build step can now take them from the package, with import.meta.resolve('@nldd/design-system/fonts/RijksSansWeb-Regular.woff2'), so the copies and their separate license notes can go. The terms in NOTICES.md do not change: the path is only reachable.

  • A card that is one link or button reacts to hover and press. With href or button, nldd-card steps its surface and its border one shade up on hover and one more while pressed, on base and tinted alike, as a neutral-base button does. A button lifted above the card in its footer does not set it off.

  • loading-text on nldd-button and nldd-icon-button says what the screen reader announces while loading is on, for a button that does more than load: "Aan het bewaren". Without it the indicator says its translated "Laden".

  • The ribbon in nldd-top-navigation-bar stretches when the page is pulled down. Pulling a page past its top used to open a white gap above the ribbon; the ribbon now carries on into it and only grows longer. A bar above the navigation bar, such as nldd-status-bar, stays clear: the ribbon starts at the top of the page, not right above the logo. It works in browsers that support scroll-driven animations; elsewhere the gap stays as it was.

Changed
  • nldd-text-editor checks the spelling, like the other text fields, and no-spellcheck turns it off. It never did: CodeMirror switches spellchecking off. Now it is on for the running text and off for what the editor knows is not: inline code and code blocks, the address of a link and a bare URL (the link text is checked), and mentions. Autocorrect and autocapitalize follow the user's own settings, as in the other fields, also with no-spellcheck. Deleting a character or a selected word keeps the underlines on the rest of the line, as it does in a plain text field. Two limits come from the browser: text that was already there is checked once you edit near it, not when the editor opens, and markup that changes how a line is built, such as starting a list item, hides the underlines on that line until you type on. An editor that should not be checked takes no-spellcheck.

  • The inherit-tinted and inherit-filled buttons keep one color through hover, press and expanded. The label on these buttons has only the contrast the colored surface around it gives, and every state color moved the background toward the label: on a surface that just met 4.5:1, a hovered or pressed button fell below it. In a button bar the states did not show at all, since the bar's own surface lay underneath. This applies to nldd-button, nldd-icon-button, nldd-button-bar and nldd-split-button; the focus ring stays. The forty --semantics-buttons-inherit-*-is-* tokens for those states are gone, as nothing uses them any more.

  • One checkbox or radio item in an nldd-menu gives every item in that menu the check-mark column. Only the checkable items had it, so a group of plain actions below a group of options started its text further left, and the menu could no longer be scanned from top to bottom. The text of the whole menu now starts at one line, as in a native menu. A plain item keeps the column empty and is announced as before. An icon gets no column of its own: it starts where the text of an item without an icon starts. A submenu decides for its own items.

  • nldd-button-bar warns in development about an nldd-toggle-button inside it. The bar is one surface for actions, and it showed a toggle button half: its own size and border, a selected fill under the bar's ring. Use nldd-toggle-button-group for a row of toggles, or nldd-segmented-control for one choice out of a few options.

  • NOTICES.md covers the logo and the house style of the Rijksoverheid as well, not only the fonts. The logo in nldd-top-navigation-bar, the favicon and the touch icon, the ribbon and the house style colors fall outside the EUPL: the Staat der Nederlanden reserved copyright on them, and they are for the Rijksoverheid and parties working on its behalf only. The coat of arms may only be used together with the ribbon. The README and the nldd-design-build skill point to it.

  • Running text wraps with text-wrap: pretty, headings in nldd-rich-text with balance. nldd-text, and the paragraphs, list items, definitions and quotes in nldd-rich-text, no longer end on a single word on their last line, as the cells and the status components already did. Headings in nldd-rich-text had pretty and now break into lines of even length, the way nldd-title does. Browsers without support, Firefox for now, break lines as before.

  • nldd-dropdown fades a long option out instead of ending it with an ellipsis. The field now shows its choice through the native <select>, and WebKit neither keeps that text out of the end padding nor draws an ellipsis there, so every browser fades the text before the icons. Two side effects: desktop Safari draws the options in its popup at the field's text size, 18px at md instead of 16px, and an xs dropdown shows 16px text on touch devices, because iOS zooms in on a smaller select when you tap it.

Breaking
  • variant is now appearance on nldd-button, nldd-button-bar, nldd-icon-button, nldd-split-button, nldd-keyboard-shortcut, nldd-code-viewer, nldd-code-editor, nldd-text-editor and nldd-list. The values stay the same, so variant="primary" becomes appearance="primary", and the property is appearance too. variant meant two different things across the system: how something is drawn, and what kind of thing it is. On these nine it was always the first, a designed style with its color included, so it now has a name of its own. variant stays on the components where it says what kind of thing it is and sets the icon and role with it, such as nldd-banner, nldd-notification, nldd-status-bar and nldd-inline-dialog. A variant left on one of the nine is ignored without a warning and the component falls back to its default style, so search your markup for it. The exported types follow: CodeViewerVariant, CodeEditorVariant, TextEditorVariant, ListVariant and the Variant of nldd-icon-button are now CodeViewerAppearance, CodeEditorAppearance, TextEditorAppearance, ListAppearance and Appearance.

  • variant on nldd-timeline-track-cell is now level. major, minor and none say how far down the hierarchy a row sits: minor is a row that belongs under the one above it. The values stay the same, so variant="minor" becomes level="minor".

  • mode on nldd-progress-bar and nldd-progress-circle is now variant. progress and distribution are two kinds of indicator, progress toward a goal and the parts of a whole, and the screen reader hears something different for each, which is what variant stands for in this system. The values stay the same, so mode="distribution" becomes variant="distribution". The types ProgressBarMode and ProgressCircleMode are now ProgressBarVariant and ProgressCircleVariant.

Fixed
  • A typeahead query in nldd-text-editor takes accents and a +. @józef stopped at the ó and :+1: at the +, so the source never saw the rest. What may follow a trigger is now letters in any script and with any accent, digits, _, ., + and -, for every list. A space still ends the query, as it ends a mention in most systems.

  • nldd-combo-box with allow-custom keeps a value chosen from the menu. Leaving the field, or pressing Enter, committed the shown text as the value whenever it differed from the value. That is the normal state after every choice ("Nederland" for nl), so in a form the label went to the server instead of the value, usually on the click on the submit button. Only text the user typed is committed now, and typing an option's label in full picks that option. nldd-token-field did the same with a typed label: "België" became a token with the value "België" instead of be, on Enter, on a comma or when leaving the field. It now adds the option.

  • nldd-combo-box and nldd-token-field open when the options arrive after the keystroke. A field that queries its server per keystroke slots the matches in a moment later. With allow-custom, and on the token field always, the keystroke found nothing to show and kept the menu shut, and nothing looked again when the options came in, so the list only appeared on the next letter. The options that arrive now open it, as long as the user is still in the field and did not press Escape. A menu whose options all go away closes again.

  • A component that another component builds can be translated. The activity indicator in a loading nldd-button, nldd-icon-button and nldd-inline-dialog, the tokens of nldd-token-field, the overflow menus of nldd-toolbar, nldd-menu-bar and nldd-document-tab-bar, and the pickers of nldd-date-field and nldd-time-field sit in a shadow root, so the translations you set on the outer element never reached them and they stayed Dutch. They read setTranslations() now.

  • nldd-dropdown shows the value your app sets. A value set with select.value, selectedIndex or option.selected kept the old label on screen until someone picked an option by hand, so a form that loaded saved data showed a different choice than it held. The label was a copy in the shadow DOM that only updated on slotchange and change. It is gone: the <select> now shows its own choice, so there is nothing left to go stale.

  • The changelog no longer repeats its introduction under 0.8.93.

  • The global and utility slots of nldd-top-navigation-bar are documented. The component has always rendered both, each taking an nldd-menu-bar, but neither had an @slot line. custom-elements.json and the reference in nldd-design therefore listed no slots for it, and a check that validates markup against the manifest rejected <nldd-menu-bar slot="global">. The default slot of nldd-progress-circle, where its segment indicators go, was missing the same way.

v0.8.93

Compare Source

Highlights
  • The patterns are live in Storybook, with their examples running and a test on what each one promises. The pages in the skill are generated from that same markup, so what you copy is what you saw.

  • The skills are split and renamed, so the name says the task. nldd-design holds the reference, the changelog and the design guidelines, and nldd-design-build, nldd-design-migrate, nldd-design-upgrade and nldd-design-contribute each cover one job. A skill named nldd stays behind to catch the old name until 1 March 2027. Update the references in your own instruction files first: a skill that is not found warns nobody, it just makes the answer worse.

  • Four design guidelines come with this release, on where work that needs its context belongs, on a filtered list as a mode, on sticky headers, and on the two shapes a heading can take. They are in nldd-design, and Storybook has them under Docs.

Breaking
  • The page sections no longer take scheme. nldd-simple-section, nldd-full-bleed-section, nldd-hero, nldd-sidebar-section and the two- and three-column sections could pin light, dark or inverted on a band, which made one section decide the color scheme for everything inside it. A section still draws its surface with background, which is what the components inside read; light and dark stay a choice for the page, through color-scheme on a root element. nldd-window keeps its own scheme.

  • nldd-button-group follows its own width, and that is its default. orientation was horizontal or vertical, with vertical as the default, so every group that did not say otherwise stacked its buttons at every width. It now takes auto as well, and that is the new default: a row, and stacked over the full width once the group itself is narrower than the sm breakpoint. The group is its own container query, so the same group is a row in a page and a stack in a sheet beside it, without a media query of yours. A group that wants to keep stacking everywhere says orientation="vertical". A stacked group stretches the buttons through --context-button-width, which nldd-button now reads, so a button follows the parent that stacks it without anyone setting width="full". The group used to write that attribute onto its children and take it off again; it no longer touches them, so CSS or a test of yours that keys on [width="full"] inside a group stops matching.

  • The skills are now nldd-design, nldd-design-build, nldd-design-migrate, nldd-design-upgrade and nldd-design-contribute. nldd meant four things at once: the organization, the npm package, the plugin and the skill inside it, so the name said nothing about what the skill was for and its description had to carry an anti-trigger instead. The names now say the task. What is shared between them, the component reference, the changelog and the design guidelines, moves to nldd-design: that is reference material whether you are building something new or converting something old, and a migration needs it as much as a new app does.

    Raising the version of an app that already runs on this system is its own skill, nldd-design-upgrade. It sat as a section inside the build skill, which is the wrong place twice over: an upgrade is not building something new, and it is not a migration either, so whichever of the two you reached for, the guidance was in the other one. It matters here more than in most systems because this project releases everything as a patch, including a breaking change, so the version number tells you nothing about whether a jump is safe. That is a deliberate choice in .releaserc.json, not how semantic-release behaves by default, which makes it easy to assume the usual semver signal is there when it is not.

    A skill named nldd stays behind to catch the old name, and does nothing but point at the ones that replaced it. It is deliberately findable by the model and not just by /nldd, because the reference that breaks most quietly is a line in your own CLAUDE.md saying "use the nldd skill": nobody types anything there, so a slash command would not catch it. It is removed after 1 March 2027, so update your references rather than lean on it.

    The plugin is still called nldd. Installing it does not change, and enabledPlugins and extraKnownMarketplaces point at nldd@nldd-plugins, the plugin, so leave those alone.

    What to check, quietest first, because the first two give you no error at all:

    1. The skill name in your own instruction files: CLAUDE.md, .claude/rules/*.md, AGENTS.md, or the body of a skill of your own that says "use the nldd skill". Claude reads the instruction, does not find the skill, and carries on without it. Nothing warns; the output is just worse.
    2. The skill name in subagent definitions (.claude/agents/*.md) and in hooks that match on it. Equally silent.
    3. Skill(nldd) in permission rules. It stops matching, so you get a permission prompt where you had none.
    4. Scripts or CI that call claude -p "/nldd ...". Since Claude Code 2.1.273 an unknown slash command is no longer a free deterministic rejection but a model call that answers with a "did you mean" text, so a script checking the exit code still sees 0 and now gets billed, variable output instead of a fixed error.
    5. Typing /nldd interactively. The loudest and least harmful.

    Invoke a skill either way: /nldd-design-build is the short form, and /nldd:nldd-design-build always resolves to ours even when a skill of your own carries the same name.

  • The subtitle slot of nldd-title is now supporting-text. That is what the text under a title is called in every other component, including nldd-top-title-bar. Rename slot="subtitle" to slot="supporting-text", or use the new supporting-text attribute for plain text. Content still in slot="subtitle" is not shown, and in development the console says once which rename it needs.

  • nldd-form-section calls its supporting text supporting-text throughout. The span in the legend is now .form-section__supporting-text instead of .form-section__subtitle, and its token --semantics-forms-section-supporting-text-font instead of --semantics-forms-section-subtitle-font. The attribute already had that name. Rename the class in your CSS and the token where you override it: the old ones do nothing any more, without a warning.

  • nldd-page in a split-view pane no longer carries the document's landmarks. A page carries them: its header is the banner, its content the main landmark, its footer the contentinfo. A document has one of each, so two pages beside each other were two of each, which is invalid HTML that nothing on screen gives away. A page in a pane of a navigation, side-by-side or stacked split view, or inside an overlay, now renders a section and a plain div instead, which drops all three at once: a header inside sectioning content is no longer a banner.

    Set landmarks="page" on the page in the pane that holds your primary content, because only the application knows which pane that is. Nothing warns when you do not: the app shell simply has no main landmark, and a screen reader user loses the jump to the content. Give the other panes an accessible-label and they are named regions instead, which is a landmark worth having. landmarks also takes region to step down anywhere else, and a second page that still renders a main says so in development.

  • nldd-icon takes icon instead of name. Every other component that renders an icon already called it icon, so you had to remember the one exception. Rename name="…" to icon="…" on every nldd-icon. An icon that still has name draws the dashed placeholder circle, and in development the console says once which rename it needs.

  • The --components-title-* tokens are gone. --components-title-{sm,md,lg}-overline-font and --components-title-{sm,md,lg}-subtitle-font stood in variables.css, but nldd-title never read them, so overriding one changed nothing. The overline and the supporting text take --primitives-font-body-sm-regular-tight and --primitives-font-body-md-regular-tight. The two names are removed rather than renamed, so a var() of your own that points at one resolves to nothing.

Added
  • nldd-list-item-segment can be the button that opens a menu. It takes popup-type, popovertarget and the popover-invoker properties the buttons already had, so a row can carry a "more" action that looks like part of the row instead of a button dropped on top of it. An nldd-menu anchored to the segment seeds its own type and keeps aria-expanded in step, the same as with nldd-icon-button.

  • nldd-button takes a form attribute. A save button in a sticky footer sits outside the form it saves, and pointing it at that form did not work: the platform resolves form to a real <form> element, while nldd-form renders its own form without handing it the id you wrote. So the button found an element that was not a form, ended up with no form owner, and did nothing at all when clicked. It now resolves the id itself and takes the form an nldd-form renders, as well as a plain <form>. An id that finds nothing, or an nldd-form that has not rendered its form yet, says so in development instead of letting the click do nothing.

  • A skill for migrating an existing codebase (nldd-design-migrate). What goes wrong when you convert an application that already exists, and how you notice before your users do. The system fails silently, so the skill is built around checks that make the silence audible: what to verify before you convert anything, how to measure what a page still does rather than how it looks, and what to do when the fault is ours rather than yours. Separate files cover coming from Tailwind and rendering HTML on the server with fragment swaps (htmx, Turbo, Unpoly, LiveView), where one rule explains most of the trouble: a swap does not run a component's lifecycle the way a page load does.

  • A skill for raising the version (nldd-design-upgrade). Reading the changelog as an upgrade path: which entries to read first, what to search your own code for, and why renamed CSS variables are the trap that catches most people. Your own theme overrides then point at a name that no longer exists, with no error and no visible break, just a silent fall back to the default.

  • A skill for proposing a change (nldd-design-contribute). Where a report goes first, which depends on who you are: inside NLDD it goes to the design system channel on Mattermost, which is shorter than an issue and where the maintainer reads along, and from outside NLDD it goes to a GitHub issue. Then how to write it so it gets somewhere: describe the problem in your interface rather than only the component you have in mind, because often something existing already does it, and when it does not, your context shapes the design. It also states plainly what to expect, that the maintainer decides and a rejection comes with a reason, and it carries the rule that keeps the pattern set small: a composition used by several teams is a pattern of the system, one that lives in a single app is that app's habit for now. CONTRIBUTING.md stays the source for maintainers; this is the consumer's half of it.

  • The patterns are live in Storybook. Every pattern of nldd-design-build has a page under "Patronen", with its example running and a test on what the pattern promises: that the sheet closes once, that a confirmation puts the way out first, that a page has one h1. The pattern pages in the skill are generated from the same markup, so the example you copy from the skill is the one that is tested. Rules about a single component moved out of the patterns and into that component's documentation, and a design rule is stated once, in the design guidelines. The content page came along as a pattern of its own: it used to travel as a loose example, without a running example and without a test.

  • Four design guidelines, and a section that says what it holds. Work that needs its context belongs in a sheet, not a modal or a page of its own, and a sheet buys you the full height of the screen. A filtered list is a mode as soon as you cannot see which filters are on. Avoid a sticky header: the content matters more than the bar above it, with the title bar that says what you are looking at as the one exception. And a heading is either a short summary written as a sentence or a label kept as short as it goes, which is a choice about what the reader is doing rather than about the kind of page. "Microcopy en toon" is now "Copywriting", because it covers headings as well as the small print.

  • open on nldd-sheet, nldd-modal-dialog, nldd-window and nldd-popover. Bind it instead of calling show() and hide() from your own code, for example <nldd-sheet :open="isOpen" @close="isOpen = false"> in Vue. The overlay clears it when it closes another way, by Escape, the backdrop or its close button. show() and hide() keep working and set it too. On nldd-popover it replaces the read-only open property, and opening still needs an anchor. The build skill, its Vue example and the patterns now bind open instead of calling show() and hide() from a watcher, and the migration skill tells a server-rendered app to put open in the markup, which needs no JavaScript at all.

  • text, supporting-text, overline and heading-level on nldd-title. size sets how big the title looks, heading-level which heading it is, and you now see both side by side on the element. Without heading-level the text is a paragraph, for a title that is not a heading. Each text keeps a slot for content that is more than text, such as a link: the default slot, overline and supporting-text. A filled slot takes the place of its attribute.

  • heading-level on nldd-top-title-bar. The title was always an h1. It still is by default, and you can lower it where the bar is not the top of the page.

Changed
  • A stacked nldd-button-group leaves an icon button at its own size. Everything in a stack fills the width, which turned an nldd-icon-button into a full-width bar with one glyph in the middle: wider, not a bigger target. Only auto is a container query now, so only auto has to take its width from its parent: a group pinned to horizontal or vertical sizes itself again, which it could not do in a parent that shrink-wraps (an inline-flex box, a float, a table cell, a flex item at width: auto). An auto group that ends up in such a parent measures zero and says so in development.

  • The edge of a surface is the same grey as a line inside it again. --semantics-surfaces-base-border-color and --semantics-surfaces-tinted-border-color go back to neutral-75 in light mode and neutral-200 in dark, the values --semantics-dividers-color carries, which undoes the lighter edge of 0.8.89. Everything that draws its outline from these tokens is a step more present: nldd-table, nldd-list, nldd-code-viewer, nldd-rich-text and the boxes that follow them. Override the two tokens to keep the lighter edge.

  • nldd-sheet and nldd-window take their name from the title bar. Without accessible-label, a screen reader called them "Venster" unless you repeated the title there. They now take the text of the nldd-top-title-bar inside them, and follow it when it changes. accessible-label still wins, for a name that has to differ from the title. The development warning only appears when neither is there.

  • nldd-list-item warns about anything in a row that is not a cell or a segment. Bare text or a loose element gets none of the typography, size and alignment a cell brings, and in a clickable row bare text falls back to the browser's button font. The row now says so once in development. Wrap the content in a cell.

  • nldd-list-item warns about a control inside a row that is its own control. An icon button or a segment in a row with href, button, checkbox or radio nests a control inside a control: invalid HTML, and a second tab stop. The documentation already said the row warned about this, but it did not. A decorative checkbox or radio button, which only shows the row's state, is fine.

  • nldd-toolbar-item warns when it has nothing in slot="overflow". On a narrow toolbar such an item moves into the overflow menu and its action is gone, which you never see on a wide screen. The item now says so once at load in development. A tab bar is no exception: its alternative is a menu group of type="radio" items.

  • nldd-rich-text looks through a single wrapper div. The rhythm and the width zones apply to the direct children, so content wrapped in one div became a single block and its paragraphs sat against each other. A markdown renderer or the root of a framework component produces exactly that wrapper, and you cannot always remove it. A lone div without class, style, role or data-width is now passed through, and its children are laid out as if they were direct. A wrapper with any of those stays one block, since you gave it something of its own.

  • The element that holds the notifications is nldd-notifications-area. It was nldd-notification-region, a singular name for the thing that owns every notification at once, and "region" named its ARIA role rather than its job. The id is the only part of it you can see, in the DOM; nothing about the notifications themselves changed. The three overlays that take it in, nldd-sheet, nldd-window and nldd-modal-dialog, now document their notifications slot, which the package fills itself.

  • The CSS variables are documented as internal. They are the wiring of the components, not a public API: they get renamed, merged and removed whenever a component asks for it, and the changelog describes such a change from that component, not from your stylesheet. Steer a component through its attributes. Reach for a variable only for something that is not a component at all, and then at your own risk.

  • nldd-token names its buttons after itself. The dismiss button was called "Verwijder" on every token, so a row of filters read as a row of identical buttons unless you composed a dismiss-text per token. Unset, it is now Verwijder "{text}", and the menu button Toon opties voor "{text}", with the token's own text in the quotes. A dismiss-text or menu-text you set still replaces the whole label. Both properties now default to an empty string instead of the bare word. The words themselves come from translations, like every other user-facing string in the package: components.token.dismiss-action, components.token.open-menu-action and components.token.open-token-menu-action. nldd-token-field names its tokens the same way, through its own translations, where components.token-field.token-menu-action reads "Toon acties voor" so the token's text can follow it.

Fixed
  • nldd-window opens when show() comes before its first render. Sheet and modal already waited for their dialog. The window did nothing and said nothing, so a window opened in the same tick it was created stayed shut.

  • The validation icon of nldd-token-field stays in the top corner. It was centered over the whole field, so the moment the tokens wrapped to a second row it drifted down the side, away from the row it belongs to. It now sits where nldd-multi-line-text-field puts its own: at the top, level with the first row.

  • A tree row's divider no longer jumps when the branch opens. The chevron turned by rotating the whole nldd-icon-cell, and a rotated element reports a turned box to getBoundingClientRect(). That box is what the row measures to place its divider, so the same row drew its line 12px further left while it was expanded. The cell now turns its glyph instead, through the icon part it exposes, and keeps its own box where it was.

  • nldd-list-item documents where a row's divider starts. divider-start and divider-end go on a cell in the row and move the line off its default, the first text or title cell. The item has always read them, but only its prose said so, so neither the reference nor the markup validator knew they existed. An indented tree row could not get its line to start at the icon without guessing.

  • nldd-bar-split-view documents the order attributes of its panels. The component reads sm-order, md-order and lg-order off its children to place a bar above or below the content per breakpoint, but only its prose said so, so the reference listed neither the attributes nor what they do. A bottom bar on a phone was there all along and nobody could find it.

  • nldd-validation-item has a description in the reference. The component reference takes the prose above the first @element in a file. Two components that share a file write their own prose under their own @element, and that was thrown away, so the item shipped as a bare table of attributes and the rule about giving it an id that names its field reached nobody. nldd-navigation-split-view lost a line the same way. Both are back, and nldd-form now says when it marks a field as invalid.

  • hidden now hides every component. Nine components stayed visible with hidden set, because their own display beat the browser's rule for the attribute. nldd-list, nldd-sheet, nldd-navigation-split-view, nldd-menu, nldd-progress-bar-segment-indicator and nldd-form never hid. nldd-number-field with width="full", nldd-pagination with centered and an nldd-activity-indicator around content did not hide either.


Configuration

📅 Schedule: (in timezone Europe/Amsterdam)

  • Branch creation
    • "before 6am on sunday"
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@nldd/design-system](https://github.com/NederlandseDigitaleDienst/design-system) | [`^0.8.92` → `^0.10.0`](https://renovatebot.com/diffs/npm/@nldd%2fdesign-system/0.8.92/0.10.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@nldd%2fdesign-system/0.10.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nldd%2fdesign-system/0.8.92/0.10.0?slim=true) | --- ### Release Notes <details> <summary>NederlandseDigitaleDienst/design-system (@&#8203;nldd/design-system)</summary> ### [`v0.10.0`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0100-2026-10-21) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.9.0...v0.10.0) ##### Highlights - **Themes for 17 Rijkshuisstijl colors.** Set `data-nldd-theme` on `<html>` and buttons, selections, links, the focus ring, the hero and the badge take that color instead of lintblauw, in light and dark mode. The ribbon and the logo stay lintblauw. - **A favicon and touch icon in the color of your theme.** The field behind the ribbon takes the theme color, so the tab and the home screen match the site. They ship as `@nldd/design-system/favicon/geel/` and so on. ##### Added - **A stylesheet per theme.** Import `@nldd/design-system/themes/geel.css` and set `data-nldd-theme="geel"` on `<html>`. `@nldd/design-system/themes` holds all of them, for a site that switches without a reload. Lintblauw is the default and needs no file. A theme sets the accent scale, the tokens per role and, for cool colors, a gray with a hint of the theme color. The "Thema's" page in Storybook explains what each role does. - **A favicon and touch icon per theme.** `@nldd/design-system/favicon/geel/favicon.svg` and `…/geel/touch-icon.png`, and the same for every theme, have the field behind the ribbon in the theme color. The ribbon stays lintblauw and the coat of arms white. Without a theme, `@nldd/design-system/favicon.svg` and `touch-icon.png` stay as they are. - **Surface tokens in the theme color.** `--semantics-surfaces-accent-tinted-*` is a tint of the theme color with the contrast of `tinted`. `--semantics-surfaces-accent-filled-*` is the panel of the hero, with `--semantics-content-on-accent-filled-*` for the text on it. - **`background="accent-tinted"` on `nldd-box`, `nldd-card` and the page sections.** The area takes the tint of the theme color. - **`color="inherit"` on `nldd-checkbox`, `nldd-radio-button` and `nldd-switch`, and on their fields.** A checked control takes the text color of the area it sits on, and the color of that area for its mark. Use it on the accent panel of the hero, where the theme color would not stand out. - **A `--components-*` layer, only for what a theme sets.** A theme reaches `:root`, not the styles of a component, so the few values a theme changes for one component live in `variables.css` as `--components-{component}-*`: the accent badge and status bar, the icon of the accent banner, the mention in the text editor and the current tab of the tab bar. It is not the old component layer: a component reads only its own tokens, and the style check fails on any other. Everything else stays a local variable or a semantics token. ##### Changed - **`--semantics-controls-is-highlighted-*` is now `--semantics-controls-is-selected-*`.** It is the color of a checked, selected or current control, so the name says that, as `--semantics-buttons-*-is-selected-*` already did. The highlighted item of a menu or mention list, where the keyboard or pointer is, reads `--semantics-list-items-is-highlighted-*` instead, like the highlighted row of a list, and that token has its own values now. If your own CSS reads one of these tokens, rename it. - **Categories are for telling groups apart; surfaces are for areas.** Only the tag and the progress bar and circle read `--semantics-categories-*` now. The banner draws on `--semantics-surfaces-{tinted,accent-tinted,success-tinted,warning-tinted,critical-tinted}-*`, new for success, warning and critical; `nldd-box background="critical"` takes a surface too. The badge, status bar, date picker and image keep their colors in their own styles, and a mention in the text editor reads `--components-text-editor-mention-*`, which a theme can set. The neutral and accent banner are one step lighter, on the same tint as `background="tinted"`, and the warning and success icons of the banner are a lighter orange and green in light mode. - **The `reference` category style is gone.** `--semantics-categories-{color}-reference-*` drew the panel of the hero, which now reads `--semantics-surfaces-accent-filled-*` and `--semantics-content-on-accent-filled-*`. No component used it anymore. If your own CSS reads one of these tokens, take the accent-filled surface for the theme color, or the `filled` style of the color. - **The surface border tokens are called `highlight-border`, as everywhere else.** `--semantics-surfaces-border-width` is now `--semantics-surfaces-highlight-border-width`, and `--semantics-surfaces-base-border-color` and `--semantics-surfaces-tinted-border-color` are now `-highlight-border-color`. The components follow by themselves. If your own CSS reads one of these tokens, rename it. - **Warning is a lighter orange on the badge and the status bar.** They take orange step 300 instead of 400 (700 instead of 600 in dark mode), which reads clearer next to black text. Their border stays at 3:1 against the page. - **The focus ring is lighter in dark mode.** It takes the color of the button when that reaches 4.5:1 against the page, so with the default theme it is lintblauw 650 instead of 600. - **A checked control has a mark in the color of the page in dark mode.** The check of a checkbox, the dot of a radio button and the knob of a switch were white and now read as a cut-out of the page. The new `--semantics-controls-is-selected-mark-color` sets that color. - **The accent badge and status bar match the accent button in dark mode.** They take lintblauw 650 with white text instead of 400 with black text. - **The wordmark of `nldd-top-navigation-bar` stands where the printed logo has it.** On md and lg it is 10px from the ribbon instead of 8px, so the first letter is as far from the ribbon as in the logo. On a small screen a wordmark taller than the ribbon keeps 16px from the top instead of 12px. ##### Fixed - **Components switch to their narrow layout when you zoom in Safari.** With page zoom, Safari measured the width of a container that takes its size from the layout in zoomed pixels, so a list 537px wide counted as wider than 641px and kept its desktop layout, with a column of one word per line. The breakpoints in the component styles are now in rem (`40rem` instead of `640px`), which scale with the zoom, and so are the thresholds of their own in rich text, the split sections, the progress bar, pagination and the document tab bar. The style check now fails on a px length in a query condition. At the default font size of 16px nothing changes; with a larger default font size the narrow layout comes earlier. `@nldd/design-system/breakpoints` adds `queryBreakpoints` (the rem values), and `breakpointPx()` and `rootFontSize()` for a width you measure in script; `breakpoints` keeps its px values. A `hide-below` or `hide-above` with a px value of your own still has the problem in Safari: write it in rem. - **On a small screen `nldd-hero` keeps the full distance at the top again.** Half the distance (8px) put the hero too close to the top bar on mobile, so there it is 16px again, as for the other page sections. On md and lg the top stays at half. ##### Breaking - **`nldd-badge` no longer takes a Rijkshuisstijl color.** `color` is the same set as `nldd-status-bar`, plus `inherit`: `critical` (the default), `accent`, `neutral`, `warning`, `success` and `inherit`. A badge is a signal, not a category, and a color of its own clashed with the theme. A badge with `color="hemelblauw"` or another named color now gets the accent, and says so in the console during development. Pick the color for the whole site with a theme, or use `custom-color` for a color of its own. - **`nldd-hero` no longer takes a Rijkshuisstijl color for its panel.** `main-background` is `accent` (the default) or `base`. A color per hero came before themes. A theme now picks the color for the whole site. A hero with `main-background="donkerblauw"` or another named color gets the accent instead, and says so in the console during development. To keep the color, set the theme on `<html>` (`data-nldd-theme="donkerblauw"`, with `@nldd/design-system/themes/donkerblauw.css`) and remove the attribute. Without a theme the accent is lintblauw. ### [`v0.9.0`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#090-2026-10-19) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.100...v0.9.0) ##### Highlights - **Links say where they go to a screen reader.** A link to another domain adds "andere website" to its name by itself, in every component with an `href`. Nobody has to set anything, so nobody can forget it. - **A table of contents in a sheet takes you to the heading.** A link in the collapsed sidebar of `nldd-sidebar-section` closes the sheet and moves focus to the heading it points at, in view. - **`accessible-label` works the same everywhere.** It names a navigation list, and `nldd-list-item` has one too. - **A step stands beside its title.** `nldd-step-cell` puts its dot at the top of a row with `vertical-alignment="top"`, or beside a first line of any height with `marker-offset`, so a step with a title and a paragraph no longer has its dot halfway down the text. - **The corner of a hero without an image is smaller.** On a hero with a single title the corner took up most of its height, so the panel looked like a drop. Without media it now takes half the radius, and in any hero never more than a third of the height. ##### Added - **A hint for a link to another website.** An `href` to another origin than the page adds a visually hidden "andere website" to the link's name, in one sentence with "opent in nieuw tabblad" when both apply: "Lees de startnotitie, andere website, opent in nieuw tabblad". It works in `nldd-button`, `nldd-icon-button`, `nldd-link`, `nldd-card`, `nldd-avatar`, `nldd-toolbar`, `nldd-list-item` and `nldd-list-item-segment`. Only `http:` and `https:` links count, a subdomain counts as another website too, and there is no way to switch it off: another domain has its own heading, navigation and title. An `external-link` icon stays your own choice. The hint is translated in English, Frisian and Papiamento. - **A design guideline: don't explain the interface, improve it.** A sentence that says where to click or what a button or filter does shows that the interface does not say it by itself. People read it only once they get stuck, and it goes stale as soon as the interface changes. Change the label, the order or the component instead. Where a hint is still needed, keep it short and put it next to the part it is about, not in an introduction above. - **`accessible-label` on `nldd-list-item`, the name of the row's action.** For a row whose text does not say enough on its own. It replaces the content of the whole row for a screen reader, the supporting text and a status included, so set it only on a row without text of its own, or put everything that matters in it. - **`vertical-alignment` and `marker-offset` on `nldd-step-cell`, for a step in a row higher than one line.** The dot stood in the middle of the row, so beside a title with a paragraph under it, it hung halfway down the text. `vertical-alignment="top"` puts it against the row's top padding and `bottom` against its bottom padding, as a whole dot would stand, so a `minor` dot lines up with a `major` one. To line it up with what stands beside it, such as the first line of a text cell or an `nldd-title`, `marker-offset` says how far below the top of the content the middle of the dot stands, measured after the row's padding, as a length or as a percentage of the content's height. Write it in `rem`, so the dot moves along when someone sets a larger font size. The track runs to the middle of the dot, so rows still connect. ##### Changed - **The hint for a new tab follows the name after a comma, in lowercase.** "Lees de startnotitie, opent in nieuw tabblad". The hidden text ran on without a pause, and the hint in an `aria-label` started with a capital after the comma. `nldd-list-item-segment` now gives the hint as well. - **A link in the sheet of `nldd-sidebar-section` closes it and moves focus to the place it points at.** Left to the browser, the page scrolled under a sheet that was still open, and closing it gave focus back to the trigger without scrolling to it, so focus ended up out of sight. The section now closes the sheet, scrolls to the heading and gives it focus with a temporary tab stop, as `nldd-skip-link` does. A link to another page, in a new tab, with a modifier key or into the sidebar itself is left alone, as is a click you already handled with `preventDefault()`. The content page pattern no longer needs its own click handler. - **`accessible-label` names a navigation list.** With `type="navigation"` it did nothing, and the landmark kept the default name "Navigatie". It now names the landmark, as it names the list and the search field in the other types. An `aria-label` or `aria-labelledby` on the element still wins. The page patterns use `accessible-label` on their navigation lists. - **The corner of an `nldd-hero` without media is smaller.** On a hero with a single title, the radius of 60px took up more than 80% of a panel 73px high. Without an image the panel is the whole hero, so it now takes the radius of a panel: half, 0.75X on small screens and 1X above. In any hero the radius is never more than a third of the shortest side of the area it rounds, which also protects a hero with a small `media-height`. Without media the corner applies in every layout, overlap included, and the hero chooses top-right, or top-left for a panel on the right. ##### Breaking - **The translation key for the new-tab hint is renamed.** `components.{name}.opens-in-new-tab-label` is now `components.{name}.link-hint-new-tab-lowercase-label`, next to the new `link-hint-external-lowercase-label` and `link-hint-external-new-tab-lowercase-label`, so the three hints of a link sit together. The text always follows a name after a comma, so the default is lowercase: "opent in nieuw tabblad". If you override this text with `translations` or `setTranslations()`, rename the key and write the text in lowercase. The old key does nothing anymore. ### [`v0.8.100`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#08100-2026-10-16) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.99...v0.8.100) ##### Highlights - **`nldd-hero` can take the rounded corner of the Rijkshuisstijl.** `corner` rounds one corner of the image and half a one on the panel, in a contained hero with the panel in a corner or along a side. - **Room to play with typography.** `nldd-title` takes `sm-`, `md-` and `lg-custom-size` for a statement larger than size 1, set per breakpoint and never smaller than size 1. - **Icons are easier to find.** The icon gallery has its own page under Docs › Iconen, where it used to be the last story of `nldd-icon`. Search every icon and alias there, or see what is new or updated. - **A design guideline for link text.** A link names where it goes: no "klik hier", "lees meer" or "meer info", which say nothing to someone scanning the page or to a screen reader listing its links. - **The examples follow the design guidelines.** Button labels in the imperative, no "Annuleer" next to the primary action, the safe way out first in a destructive dialog, link texts that name their destination, and Dutch text with the fixed example cast. ##### Added - **`item-max-width` on `nldd-collection`, the largest width of an item in a horizontal scroll.** A scroll with only one or two items, such as an agenda that starts small, keeps them at a readable width instead of filling the container. It takes a CSS length such as `400px` or `25rem`, is never narrower than `item-min-width` and never wider than the container. Once the items overflow, scrolling, the edge fade and the previous and next buttons work as before. Grid, lanes and stack ignore it. A grid leaves empty columns rather than stretching an item, so the problem does not occur there, and a maximum would change how many columns fit. - **A design guideline for link text: say where the link goes, no "click here".** A screen reader can read every link on a page as a list of its own, and people scanning a page read the underlined words. Out of context, "klik hier", "lees meer" and "meer info" say nothing. The guideline asks for the destination or subject as the link, the distinguishing words first, a different text for every destination, and the format and size of a file. WCAG 2.4.4 accepts a generic link when the sentence around it gives the context. This guideline is stricter, because that context only helps whoever reads the sentence. The examples in Storybook follow it now. - **`corner` on `nldd-hero`, the rounded corner of the Rijkshuisstijl shape language.** `<nldd-hero corner>` (or `corner="auto"`) rounds one corner of the image and lets the hero choose one the panel leaves free; `corner="top-left"` and the other three choose it yourself. The panel gets a corner at half the radius, the one pointing into the image, and stands against the edge of the image, so a `main-width` of 33.33% or 50% is that share of the image. The radius follows the ribbon width: 1.5X on small screens, 2X above. It applies with `layout="contained"` and the panel in a corner or along a side; with overlap or a centered panel the hero stays rectangular and says so in development, as it does for a chosen corner that sits under the panel or a corner with `width="full"`. Without `corner` the hero is rectangular, as before. - **`sm-custom-size`, `md-custom-size` and `lg-custom-size` on `nldd-title`, for a statement larger than size 1.** Size 1 tops out at 52px, which is small for a title that has to make an impression. These take any CSS length per breakpoint, with the weight, typeface and line height of size 1. They never go below size 1 at the same breakpoint: a smaller value shows as size 1 and says so in development, so they are no way around the scale for an ordinary heading. There is no plain `custom-size` on purpose: a breakpoint you leave out keeps the size from `size`, so a title made large for a wide screen does not break a narrow one. - **`no-results` on `nldd-table`, for a table whose rows are all filtered away.** An empty table and a filtered one said the same thing, because the table had only `empty`. When every body row is `[hidden]`, the table now shows `[slot="no-results"]`: say that nothing matches and how to get rows back, and keep `empty` for a table that has no rows yet. Without `no-results` it falls back to `empty`, the same as `nldd-list`. ##### Changed - **`nldd-modal-dialog` says so in development when it opens with one action.** A dialog with one button offers nothing to choose, which the design guidelines advise against. Tell the user with an `nldd-notification` or an inline message instead, or give the dialog a real choice. It warns once per dialog. - **The component docs point to the design guidelines where an attribute invites misuse.** `disabled` and `loading` on the buttons, `nldd-dropdown` as a last resort after visible options and a combo box, when an `nldd-modal-dialog` is right, and horizontal scroll in `nldd-collection` as more than a carousel. The examples in Storybook follow the guidelines as well: labels in the imperative, no "Annuleer" next to the primary action, the safe way out first in a destructive dialog, and Dutch text with the fixed example cast. They are built from the system's own components too: `nldd-container` for layout, `nldd-text` for captions with an `nldd-spacer` to the example, and cells inside an `nldd-list`, so the code you copy from Storybook has no inline layout CSS. - **The icon gallery has its own page, Docs › Iconen.** It was the last story of `nldd-icon`, where nobody looking for an icon name thought to look. The page shows every icon and alias, two across on a phone, with a search field and a filter for the new and updated ones. - **Inline elements in `nldd-text` look as they do in `nldd-rich-text`.** `<em>` is italic, `<a>` an underlined link, `<code>` sits on a tinted surface in the monospace font and `<mark>` is highlighted, beside the bold `<strong>` it already had. A short text with a code word or a link no longer needs a rich-text block. - **The form pattern allows a format requirement on an optional field.** An optional field is not `required`, and an empty value passes every requirement, so a phone number you may leave out can still be checked when it is filled in. - **The title of the wordmark in `nldd-top-navigation-bar` is semi-bold.** It was medium, close enough to the subtitle below it that the two read as one block. One step heavier sets the name apart without competing with the page title. - **A menu under an `nldd-menu-bar-item` opens against its indicator.** The indicator stops 6px short of the item's bottom edge, and the menu hung off the item, so it opened with a gap below the gray box that marked the open item. It now touches the indicator, which keeps its rounded corners. ##### Breaking - **Items in a horizontal-scroll `nldd-collection` stop at 480px.** One or two items that fit grew to the full width of the container, so a card of 320px became more than 1000px wide on a desktop. They now grow up to 480px and stay at the start. An `item-min-width` wider than 480px raises the limit with it, and `item-max-width` sets your own; `item-max-width="100%"` brings back the old behavior. - **`item-width` on `nldd-collection` is now `item-min-width`.** It was a minimum in every layout: in a grid the narrowest a column gets, in a horizontal scroll the width an item never shrinks below. The new name says so, and pairs with `item-max-width`. There is no alias. An `item-width` left on a collection does nothing, so its items fall back to the default of 280px; in development the collection says so once, with the renamed attribute. Rename the attribute on every `nldd-collection`. ##### Fixed - **`nldd-container width="fit-content"` takes the width of its content.** The container measures its own width for its breakpoint padding and gap, and that measuring left a fit-content container 0px wide, so whatever was in it piled up on its neighbours. A fit-content container no longer measures itself; its breakpoints follow the container around it. ### [`v0.8.99`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0899-2026-10-14) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.98...v0.8.99) ##### Highlights - **`nldd-menu` can be a navigation.** With `variant="navigation"` it is a list of links instead of a menu of actions, so a submenu in the site navigation is read as what it is. - **Tabs that do not fit go to a menu.** On a narrow screen `nldd-tab-bar` puts the tabs that do not fit behind a "Meer tabs" button instead of cutting off every tab, and the current tab always stays in the bar. In an `nldd-toolbar` the other items make room first. - **Closing tabs one after another keeps the next close button under the pointer.** The tabs in an `nldd-document-tab-bar` keep their width while you close them, and grow into the space once the pointer leaves the bar. - **Notifications can be raised from code.** `NLDDNotification.show()` creates, shows and cleans up a notification, which is the way to raise one from a framework. - **`nldd-visually-hidden` is new**, for text that only a screen reader reads, such as the header of a column of checkboxes. ##### Added - **`variant="navigation"` on `nldd-menu`, for a submenu in a site navigation.** A submenu in `nldd-top-navigation-bar` was a menu of actions: `role="menu"` with menu items. For site navigation that is the wrong role, since a screen reader switches to an application mode in a menu where a visitor expects a list of links. With `variant="navigation"` the menu is a list (`role="list"`) and each item a list item around a real link; it looks the same. Tab reaches every link, the arrow keys, Home and End move between them, Escape closes and returns focus to the trigger, and the menu closes when focus leaves it. The `nldd-menu-bar-item` that opens it says `aria-expanded` and no longer `aria-haspopup="menu"`. A submenu and a group inside it follow along. Checkbox and radio items, shortcuts and `filter()` belong to actions and warn in development here. Give every item an `href`, and keep the default variant for menus that do things, such as an account menu or a language switch. - **`NLDDNotification.show()`, to raise a notification from code.** An `nldd-notification` places itself, which is why it does not matter where you write it. It also means a framework cannot render one: the element is no longer where the framework left it, so a keyed list (`v-for` with a `:key`) fails on its next render and a removed row leaves its notification on screen. `NLDDNotification.show({ text, supportingText, variant, icon, duration, actions })` creates the element, shows it and removes it once it is dismissed. An action is `{ text, onClick }`, at most two, and a click on one takes the notification away as well. It returns a handle with `dismiss()` and `update(options)`. An update changes the message, puts the notification in front and starts its clock over, so a status that changes often stays one notification, and the clock still pauses on hover and focus. The declarative element stays as it is; raise notifications with `show()` from a framework. - **`nldd-visually-hidden`, text for a screen reader only.** It stays in the accessibility tree and the reading order and takes no room on the page. Use it for a name that is visually redundant, such as the header of a column of checkboxes. The recipe is the one the components already use inside, so a site no longer needs a `.visually-hidden` class of its own. It is not for repairing structure that is missing, nor for a status: a status that matters to a screen reader matters to anyone, so show it. ##### Changed - **Tabs in `nldd-tab-bar` that do not fit go to a menu instead of being cut off.** On a narrow screen every tab was cut off with an ellipsis, and the rest of its text could not be read anywhere, often the very part that told the tabs apart. Tabs that do not fit now go behind a "Meer tabs" button at the end of the bar, in a menu. The current tab always stays in the bar. While tabs are in the menu, the bar fills its container and the tabs in it share the width in proportion to their own; choosing a tab in the bar leaves the rest where it is, and one chosen from the menu swaps places with the last tab in the bar, so the bar does not jump when you switch. In an `nldd-toolbar` the other items go to the toolbar's menu first; when it is the tab bar's turn, it narrows down to the current tab beside its own button, and only then goes into the toolbar's menu as a whole. Tabs are hidden, never moved in the DOM, so a framework that renders them finds them where it put them. Only a tab that does not fit on its own is still cut off. The label of the button can be translated with `components.tab-bar.overflow-action`. - **`nldd-code-viewer` scrolls across its whole box.** The padding sat on the box and the scrolling on the code inside it, so a long line stopped short of the edge, the scrollbar was inset, and the room for the copy button kept the whole right side free. The scroll area is now the box itself, with the padding inside it: a line scrolls out to the edge, the scrollbar runs from corner to corner, and at the end of a long line the last character stops beside the copy button instead of behind it. - **Closing tabs in `nldd-document-tab-bar` one after another keeps the next close button under the pointer.** Closing a tab with the pointer used to spread the others over the space at once, so the close button of the next tab moved away from the pointer. The tabs now keep their width until the pointer leaves the bar, and the next close button slides in under the pointer. Then they grow into the space, without motion for anyone who asks for reduced motion. Closing the last tab of the row, with none left in the overflow, lets them grow into the space at once; closing from the keyboard spreads them at once. ##### Breaking - **`label` on `nldd-toolbar` is now `accessible-label`.** It was the one place where an accessible name was called `label`; every other component says `accessible-label`, and on `nldd-toolbar-item` `label` is the visible text below the item, which made the two easy to mix up. There is no alias: a `label` left on a toolbar does nothing, so the toolbar loses its name. Rename the attribute on every `nldd-toolbar`. The `label` on `nldd-toolbar-item` stays as it is. ##### Fixed - **Text in an `nldd-popover` under a button can be selected.** `nldd-button`, `nldd-icon-button`, `nldd-menu-bar-item` and `nldd-menu-bar` switch text selection off for themselves and everything in them, and a popover in their `popup` slot is in them. The popover now switches it back on, so its text can be selected and copied. - **A card that is a link or button no longer stays pressed when a touch turns into a scroll.** The pressed shade of `nldd-card` came from `:active`, which can flash or linger while a touch scrolls the page. The card now sets it on a press and clears it on release, or when the browser hands the touch to scrolling, as `nldd-list-item` already did. - **The ribbon of `nldd-top-navigation-bar` starts at the top of the bar again with `logo-href`.** With a link on the logo the ribbon sat in a span as an inline image, on the text baseline with room below it for descenders, and centering that taller box lifted the ribbon 2 to 4 pixels above the bar. Anything placed above the bar, such as an `nldd-status-bar`, was overlapped by it. - **The current item in the menu sheet of `nldd-top-navigation-bar` has `aria-current`.** Behind the Menu button on a narrow screen the current item was only painted. The list in that sheet is a navigation list now, named after the global menu bar, so the link of the current item carries `aria-current` with the `current-type` of its menu bar item. ### [`v0.8.98`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0898-2026-10-13) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.97...v0.8.98) ##### Highlights - **Navigation lists can nest.** A sub-page in an `nldd-list type="navigation"` goes in its parent row's `slot="children"` and is then a list inside a list item, where it used to be an indented row in one flat list. - **A round of accessibility fixes.** A skip link that could silently do nothing, a tooltip you could not close with Escape while pointing at it, a copy failure that vanished after two seconds, and a scrolling sidebar that Firefox focused without a role or a name. - **A rule in `nldd-validation-list` no longer rejects an empty optional field.** A `match` or `minlength` under a field that may stay empty used to block every submit that left it empty. See Breaking if a field relies on the old behavior. ##### Added - **Sub-pages in `nldd-list type="navigation"`.** Put the rows of a sub-level in their parent row's `slot="children"`, the slot a tree already uses. The parent renders them as a list inside its list item, so a screen reader hears the level and how many there are; an indent made with a spacer cell alone stayed one flat list. They are always shown and the arrow keys walk them like any other row. Indenting is still yours: add an `nldd-spacer-cell` per level. - **`max-height` on `nldd-code-viewer`.** A CSS length that caps the block, for a long file in a frame of its own: the viewer grows up to it and scrolls vertically beyond it. There was no supported way to do this, short of a stylesheet in the shadow root. ##### Changed - **An `nldd-menu-bar-item` that shows only its icon has a tooltip.** With `icon-only`, or with `content-priority="icon"` in a compact bar, the text was gone for anyone not using a screen reader. A bar is compact at 200% zoom on a desktop too. The text now shows on hover and focus. - **Escape closes an `nldd-tooltip` and nothing else.** While a tooltip is showing, by hover or by focus, the first Escape closes the tooltip only. A dialog, sheet or menu around it stays open and closes on the next press, where one press used to close both. The tooltip takes the key in the capture phase on `document` and stops it there, so a handler of your own for Escape, in a search field or a combobox for instance, does not hear that first press either. - **A link stays a link in the overflow menu of `nldd-menu-bar`.** An item with `href` used to become a button in the "Meer opties" menu. It is an `<a>` now, so it opens in a new tab like the item in the bar, and a click handler on the original item still runs and can cancel the navigation. - **A failed copy in `nldd-code-viewer` stays on screen.** "Kopiëren mislukt" disappeared after two seconds like the success message. It now stays until you leave the button, press Escape or try again. The button takes focus on click, so leaving it works in Safari too. ##### Breaking - **Rules in `nldd-validation-list` skip an empty value unless the field needs one.** An empty value used to fail `match`, `minlength` and `maxlength` like any other. It now passes them, the way the native `pattern` and `minlength` leave an empty input alone, unless an item has `required` or the control itself is `required`. If you counted on `minlength` to stop an empty field, add `required` to the control or add an item with `required`. For example: `<nldd-validation-item id="password-required" required>Vul een wachtwoord in</nldd-validation-item>` next to the `minlength` item. ##### Fixed - **`nldd-skip-link` reaches its target, and Tab continues from there.** Three things could leave it doing nothing. Without `href` it moved focus to the next sibling whatever that was, so a `<noscript>`, a `<script>` or a hidden element right after it left the button dead; it now passes those over, and warns in development when nothing follows at all. In Safari the next Tab then left the page when the target was an `nldd-*` component, because WebKit skips everything inside a shadow host with `tabindex="-1"`. And with an `href`, Safari kept focus on the link. The skip link now moves focus itself in both forms, so the target needs no `tabindex` of its own. - **Escape closes an `nldd-tooltip` that was opened by pointing at it.** Escape only worked while focus was inside the tooltip's trigger, so with the pointer on a button and focus elsewhere it stayed open (WCAG 1.4.13). - **The current page has `aria-current` in the overflow menu of `nldd-menu-bar`.** The item was marked visually, but a screen reader heard nothing. - **An `nldd-code-viewer` that scrolls vertically is reachable by keyboard.** The scroller only became a tab stop with a role and a name when a line was too wide, never when the block was too tall, and never with `wrap`. It now measures both directions. - **The scrolling sidebar of `nldd-sidebar-section` has a role and a name in Firefox.** Firefox puts a tab stop on anything that scrolls, and that was an unnamed `div` inside the landmark. The `aside` itself scrolls now. ### [`v0.8.97`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0897-2026-10-13) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.96...v0.8.97) ##### Highlights - **Four page patterns for a website.** Home, topic page, navigation page and content page now sit together under "Patronen/Pagina's", each with a running example and a test. The home is the starting point of a site and is itself the menu, a topic page is the home for a topic lower in the site, a navigation page helps visitors find the pages below it, and a content page holds the details at the lowest level. A page structure pattern describes the frame all four share, with its header and footer. - **The text panel of `nldd-hero` overlaps the image.** By default the text panel now falls over the bottom of the image and runs on below it, as far as its content needs. The image keeps a fixed height and sets the mood, the panel carries the page, and a long text no longer has to fit inside the photo. - **`nldd-app-view` is now `nldd-shell`.** It is the outer layer of a website as much as of an application, and the old name suggested only the second. Every page needs the rename, since there is no alias; see Breaking. - **Icons are getting a typeface of their own.** We are drawing a typeface for the letters and digits inside icons: a simpler, more geometric version of RijksSans. The twelve icons that hold a letter or a digit are the first in it: `heading-1` through `heading-6`, `numbered-list`, `square-1`, `bold`, `strikethrough`, `underlined` and `text-format-size`. ##### Added - **`layout` on `nldd-hero`**, with `overlap` (the default) and `contained`. In `overlap` the text panel falls over the bottom of the image by `overlap-size` (any CSS length, 160px by default) and runs on below it as far as its content needs. The image keeps a fixed height (320px on md, 400px on lg, or your own `media-height` or `media-aspect-ratio`), so it stays the same whatever the content, and the overlap stays the same whatever the image. A panel shorter than `overlap-size` ends inside the image; that is up to you, and it says so in development. `contained` keeps the panel on the image, in any of the eight positions. - **An `icon` slot on `nldd-menu-bar-item`**, for something other than an icon in that place: an `nldd-avatar` for the person who is signed in, for instance. It gets the size of an icon and follows `content-priority` and `icon-only` as the icon does, so with `content-priority="icon"` only the avatar is left on a narrow screen and the text becomes the accessible name. - **`media-height` on `nldd-hero`**, a fixed height for the image in any CSS length, next to `media-aspect-ratio`. It wins over the ratio. - **`vertical-alignment` on `nldd-one-half-one-half-section`, `nldd-two-thirds-one-third-section` and `nldd-one-third-two-thirds-section`**: `top` (the default), `center` or `bottom` places the shorter column next to the longer one, such as text beside a taller image. It only applies while the columns stand side by side; stacked, they follow each other. - **`grow` on every page section**, to choose which section takes the height a page has left. Until now that was always the last section, so the footer sat at the bottom of a short page; with `grow` you can let a hero or a middle section fill instead. Without `grow` nothing changes. `nldd-page` marks the growing section with `data-growing`, a state it derives and never writes back into `grow`. - **A page structure pattern** (`page-structure.md` in `nldd-design-build`), for the frame every page of a website shares: the `nldd-shell` around everything, one section per block of content, a surface made with `background`, and one `h1`. Its header is the bar on top: search and a language menu in the utility slot of the top bar, a back button to the page above on every page but the home, and a skip link around it. Where a site has a personal part, a third item signs you in, and becomes a menu with your name, your profile and a way to sign out once you have. A status bar, when there is something every visitor has to know, goes above the bar. Its footer has the breadcrumbs in a row of their own, a main part each website fills in itself, and a legal bar that links straight to Contact, Toegankelijkheid, Privacy and Over deze website: grouping the privacy statement under an "about" page alone is not enough, since the European data protection guidelines ask for a direct link on every page. - **Topic page and navigation page patterns** (`topic-page.md`, `navigation-page.md` in `nldd-design-build`). A topic page opens with a hero holding a short explanation and its one main task, then has text beside an image, link cards to pages wherever they already live, a list of the pages below the topic, and related topics as link cards in a tinted section at the bottom. The home page shows the same kinds of sections: an image beside text in an `nldd-one-half-one-half-section`, cards with an intro, and a list of topics beside its title and a short text, laid out like the navigation page. A navigation page shows its choice as a navigation list next to the title and a short intro, in an `nldd-one-third-two-thirds-section`, or as a full-width collection of link cards below them; the pattern shows both. - **`nldd-list-item` and `nldd-list-item-segment` have `current-type`**, the `aria-current` value a `current` row or segment puts on its link. It was always `page`, which is wrong for a table of contents: every row there points at a section of the page you are already on. Set `current-type="location"` there. Same attribute and values as on `nldd-menu-bar-item`. ##### Breaking - **`main-width` on `nldd-hero` follows the content.** `1/2`, `2/3` and `3/4` are gone: half the width was too narrow for text on md, and three quarters too wide to read on a large screen. The panel is now as wide as its content needs, between 480px and 640px and never wider than the image allows (`main-width="auto"`, the default). `full` stays, and any CSS width (`560px`, `60%`) sets it exactly, still never wider than the image allows. A fraction is not a CSS width, so it falls back to `auto` and says so in development. - **A hero with an image overlaps by default.** `nldd-hero` used to keep its text panel on the image; it now lets it fall over the bottom edge and run on below, and takes only the horizontal side of `main-position`. A hero whose panel stands at the top or along a side (`top-left`, `left` and so on), or whose panel is too short to reach below the image, needs `layout="contained"` to stay as it was. A hero without an image does not change. - **`nldd-app-view` is now `nldd-shell`.** It is the outer layer of everything, a website as much as an application, and "app view" suggested it was only for the second. Rename the tag in every page, the import (`@nldd/design-system/app-view` becomes `/shell`) and the class (`NLDDAppView` becomes `NLDDShell`). There is no alias: an `nldd-app-view` left behind is an unknown element, so the page loses its background and its scroll mode, and the document font, which the stylesheet sets once a shell is on the page. A CSS selector on `nldd-app-view` needs the new name too. - **`data-width` in `nldd-rich-text` is now `data-rich-text-width`.** The attribute that moves one child to another width zone (`main`, `wide` or `full`) said neither what it belonged to nor that it only works inside a rich text, and it read like the `width` of a page section, which is something else. There is no alias: a `data-width` left behind does nothing, and the child falls back to the zone of its kind. - **`is-last` is gone from page sections.** `nldd-page` marks the section that takes the leftover height with `data-growing` instead of the `is-last` class, since a framework's class binding rewrites `class` and could wipe it. If you styled `.is-last` yourself, use `[data-growing]`. ##### Changed - **`nldd-hero` no longer uses `height`.** On the other page sections `height` is a minimum height for the whole section; on a hero it stretched the text panel once that sat below the image. The height of a hero comes from its image: `media-aspect-ratio`, or the new `media-height`. A hero given `height` ignores it and says so in development. - **The text panel of `nldd-hero` always stands on the image.** The image in a hero sets the mood and is never the main content, so the panel no longer sits against its edges or beside it. On md and lg it keeps a section gap (24 or 32px) from the edges, so it reads as a panel on the image rather than a frame cut out of it. `main-width="full"` used to put the image in a strip of its own above or below the panel; it is now a strip across the image, the same gap from the sides. On mobile the image comes first, also for a top position, and the panel follows below it, indented by 16px and overlapping the image by 48px. `main-position` gains `bottom-center` and `top-center`. - **Page sections, `nldd-container`, `nldd-sheet` and `nldd-image` no longer write their defaults into the DOM.** Every section carried `width=""` and `background="inherit"`, the hero `media-aspect-ratio=""` and an image without a source `src=""`, whether or not anyone set them. They now only appear when they differ from the default, as the other attributes in the system already did. If you selected on one of those empty or default attributes, select on the value you set instead. - **The overline and supporting text in `nldd-text-cell` and `nldd-title-cell` wrap with `text-wrap: pretty`**, like the main text of a text cell already did, so a description over two lines no longer ends on a single word. - **A component in `nldd-rich-text` stays within the line of text.** Every `nldd-*` component used to get the full width, so an `nldd-box` or `nldd-card` with a sentence in it grew past the text around it. A component now reads at the `main` size, like the text, unless it needs the room: `nldd-collection` and `nldd-container` keep the full width. `nldd-image`, `nldd-table` and `nldd-step-bar` get the `wide` accent, like other media and a plain `table`; an `nldd-table` and an `nldd-step-bar` used to get the full width. Code reads at `main` too: a `pre` and an `nldd-code-viewer` used to span the full width, however short their lines, and now fill the line of text and scroll inside their block when a line is longer. Other elements that are not text, such as `details` or `form`, read at `main` too. Set `data-rich-text-width="wide"` or `"full"` on a child to give it more. - **Headings in `nldd-rich-text` keep their size on every width.** They used to grow with the screen, which made an `h2` on a wide screen more than twice the size of the text around it (41px next to 18px), so an article broke into blocks at every heading. They now keep the size they have on a phone everywhere (an `h2` is 29px). Page and section titles in `nldd-title` still grow, so the step from a page title to the headings in the text is clearer than before. - **Every page section grows.** Only the hero, the sidebar section and the simple section used to take the leftover height as the last section; a page that ended on one of the other four left the footer floating up. Now all seven do. Outside an `nldd-page`, a section no longer grows just for being the last child; give it `grow`. - **`nldd-hero` sits closer to the top bar.** Its top padding is now half that of the other page sections (8, 16 or 24px instead of 16, 32 or 48px). The full distance is meant to separate two sections, and right under the top bar, where a hero almost always sits, it read as a gap. The bottom keeps the full distance. Set `padding-top` to place a hero elsewhere. - **`nldd-image` shows where an image belongs.** Without an image (no `src`, `srcset`, `lqip` or slotted media) it used to leave an empty gap, or nothing at all without `aspect-ratio`. It now shows a neutral area with an image icon, in the box, shape and caption a real image would get, and 16/9 when there is no `aspect-ratio`, or the box its parent gives it, such as the media area of a hero. A prototype or a pattern gets the right composition before there are photos, and an image someone forgot stands out instead of leaving a silent hole. While the built-in image loads without an `lqip`, the same area shows without the icon, and it goes once the image is in. The `lqip` gradient is now called a loading preview in the docs, to keep it apart from this. - **Twelve icons with letters or digits are redrawn**, in the typeface we are drawing for icons. `heading-1` through `heading-6` have a new H and new digits, `numbered-list` and `square-1` have new digits to match, and `bold`, `strikethrough`, `underlined` and `text-format-size` are drawn again. The names stay the same. - **The `profile` icon is a contact card.** `profile` and `account` both pointed at the person in a circle, while an account and a profile are two things that often stand one above the other in the same menu. `profile` now gives the contact card (`person-text-rectangle`); `account` keeps the person in a circle. If you used `icon="profile"` for the account itself, use `account`. - **`nldd-status-bar` says where it belongs.** The bar is the first thing on the screen, above `nldd-top-navigation-bar` or `nldd-top-title-bar` and across the whole app. Its docs say so now, and below a top bar it warns in development. A top bar in a sheet or dialog does not count. - **The sidebar of `nldd-sidebar-section` no longer draws the eye.** Beside the main content it was a tinted box, which pulled attention away from the text it sits next to. It now takes the surface of the section around it, base on a plain page and tinted on a tinted section, and is edged by a divider line, as the panes of a split view are. It still reads as a block, which it needs to be because it can scroll, and a `current` row in a list inside it now stands out against it. The sheet on narrow screens is unchanged. - **The content page pattern is now a home page, and the content page is a new one.** What used to be `content-page.md`, with a hero, cards and a call to action, is `home-page.md`. Its hero now holds the main goal as a button, and each card has a button that leads on. `content-page.md` now describes a page that explains one thing: the title as the heading, a table of contents in the sidebar of an `nldd-sidebar-section` that becomes a button under the title on narrow screens and marks the section you are reading, or, for a short page with fewer than three headings, no table of contents and the action beside the text, or no action at all, the text in a rich text with the action below it, and the breadcrumbs in the footer. The frame every page shares, with its header and footer, has its own pattern. ##### Fixed - **An `nldd-image` in the media slot of `nldd-hero` fills the image area.** It took the height of the photo instead, so a portrait photo showed only its top, and a lazy image that had not loaded yet had no height at all, never came into view and never loaded. The hero now tells the image to fill its area, and the photo is cropped from the center. - **The package no longer ships our sample images.** The build copied the folder with the photos the Storybook stories use into `dist`, twice, along with a page of color palettes. Over 1 MB that no consumer uses is gone from the package. - **A page scrolls when its shell is defined after it.** A page or split view that connected before `nldd-shell` was defined started out on its own, and nothing made it register once the shell was: in Chrome and Firefox the document did not scroll, in Safari a sidebar did not stick, until you resized the window. That happens whenever a section is imported before the shell, since `nldd-sidebar-section` defines `nldd-page`, and an app cannot control that order with code splitting and lazy routes. A page, a split view or a pane now waits for the shell, sheet or modal dialog above it to be defined and registers then. - **A long word in a heading in `nldd-rich-text` no longer runs out of the column.** The safety net that breaks a word wider than the column was only on paragraphs and list items; headings have it too now. A heading still never gets a hyphen. - **A chevron at the end of a row no longer touches the text.** The application and edit-in-a-sheet patterns put the chevron straight after the text cell; there is now an `nldd-spacer-cell` between them, as in the other patterns. - **Link cards in the patterns have a name.** The page patterns said a card with `href` takes its accessible name from its content. It does not: the link lies over the card as an empty anchor, so it needs `accessible-label`. Every link card in the patterns now has one, set to the card's title. ### [`v0.8.96`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0896-2026-10-07) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.95...v0.8.96) ##### Highlights - **Twelve new icons.** Seven file icons for a document's format: `file-pdf`, `file-markdown`, and `file-odt`, `file-ods`, `file-odp`, `file-odg` and `file-odf` for the OpenDocument formats, each also answering to `{format}-document`, such as `pdf-document`. And `microscope`, `share-network`, `power-plug-socket` (also `plug-connected`) for a plug in its socket, and `subscript` and `superscript` for text formatting. - **`nldd-step-bar` and `nldd-step-cell`.** The step indicator and the timeline track cell are renamed after what they draw: steps, across and under each other. See Breaking. - **The `--components-*` layer is gone.** A component's values now sit as local variables in its own stylesheet, and what several components share became a semantics token. Restyling one component through a public token was a quiet way to make it differ from the rest. If you want a component to change, ask in an issue. See Breaking. ##### Added - **File icons** `file-pdf`, `file-markdown`, `file-odt`, `file-ods`, `file-odp`, `file-odg` and `file-odf`, with the aliases `pdf-document`, `markdown-document`, `odt-document`, `ods-document`, `odp-document`, `odg-document` and `odf-document`. - **Icons** `microscope`, `share-network`, `power-plug-socket` (with the alias `plug-connected`), `subscript` and `superscript`. - **`--semantics-brand-ribbon-color`**, next to the ribbon widths: the color of the Rijksoverheid ribbon, which `nldd-top-navigation-bar` and `nldd-page-footer` both draw. It does not follow a theme's accent color, since the ribbon does not either. ##### Changed - **Every local variable in a component carries the component's name**, such as `--_button-background-color` instead of `--_background-color`. A custom property inherits through shadow boundaries, and a generic name on one component reached the elements of another slotted inside it. Locals were never meant to be set from outside; if you did set one, it now has a different name. ##### Breaking - **`nldd-step-indicator` is now `nldd-step-bar`, and `nldd-timeline-track-cell` is now `nldd-step-cell`.** They are one family, the steps of a process across and under each other, as `nldd-progress-bar` and `nldd-progress-circle` are one family for how much is done. "Timeline" said less than the cell does: most of all it draws steps. Rename the tags, and the classes and imports if you use them: | Was | Now | | --------------------------------------------------- | --------------------------------------- | | `nldd-step-indicator`, `NLDDStepIndicator` | `nldd-step-bar`, `NLDDStepBar` | | `nldd-step-indicator-item`, `NLDDStepIndicatorItem` | `nldd-step-bar-item`, `NLDDStepBarItem` | | `nldd-timeline-track-cell`, `NLDDTimelineTrackCell` | `nldd-step-cell`, `NLDDStepCell` | | `@nldd/design-system/step-indicator` | `@nldd/design-system/step-bar` | | `@nldd/design-system/timeline-track-cell` | `@nldd/design-system/step-cell` | | translation keys `components.step-indicator.*` | `components.step-bar.*` | The attributes stay the same. An old tag is an unknown element now and renders nothing, without a warning, so search your markup. - **The `--components-*` custom properties no longer exist.** If you set or read one, nothing happens now, without a warning. Most were never meant to be touched. The ones that more components share moved to semantics: | Was | Now | | --------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | `--components-code-viewer-token-*-color` | `--semantics-code-syntax-*-color` | | `--components-list-item-is-*`, `--components-list-item-indicator-*` | `--semantics-list-items-is-*`, `--semantics-list-items-indicator-*` | | `--components-menu-bar-item-inline-padding` | `--semantics-menu-bar-items-inline-padding` | | `--components-menu-box-shadow` | `--semantics-overlays-box-shadow` | | `--components-menu-item-is-highlighted-background-color` / `-content-color` | `--semantics-controls-is-highlighted-indicator-color` / `-contrast-color` | Search your own CSS for `--components-` to find what this affects. ##### Fixed - **A transparent `nldd-toggle-button` with `variant="text"` fills when it is on, also with a `selected-icon`.** A transparent toggle with a selected icon stays without a fill and lets the change of icon show that it is on. With `variant="text"` the icon does not render, so nothing changed at all when you switched it on. - **`nldd-toolbar` no longer leaves an item in the overflow menu that fits.** When the toolbar measured while the web font was still loading, an item could take its width from the fallback font, go into the menu, and stay there once the font arrived: a hidden item has no width to watch. The toolbar now measures again when the fonts have loaded. In the toolbar-with-actions pattern at 375px the tab bar went into the menu in 7 of 10 page loads. ### [`v0.8.95`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0895-2026-10-06) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.94...v0.8.95) ##### Highlights - **The plugin is now `nldd-design-system`, and it moved to the NLDD marketplace.** Install it from [`NederlandseDigitaleDienst/ai-plugins`](https://github.com/NederlandseDigitaleDienst/ai-plugins) as `nldd-design-system@nldd`. That marketplace is tool-independent, and the plugin now ships a Cursor manifest next to the Claude Code one. An existing `nldd@nldd-plugins` install keeps working and keeps updating until 1 March 2027, when the marketplace in this repository goes away. The README has the four commands to move over. - **The current step in `nldd-step-indicator` is marked on the step itself**, with `status="current"` on the `nldd-step-indicator-item`, instead of a number on the parent. Move the attribute when you upgrade. See Breaking. - **A title in `nldd-toolbar` keeps its width.** Buttons move into the overflow menu first, and the title only truncates once none is left. ##### Added - **`nldd-design-migrate` covers sites built by a static site generator** (MkDocs, Hugo, Eleventy). Leave the authors' Markdown alone and convert the rendered HTML in a build hook, take the bundle from the registry without a bundler and pin it with its integrity hash, and decide up front what is left without JavaScript and what loading the whole bundle on every page costs. The behavior check now also strips the base path a site runs under, because a pull request preview runs under a different one than production. ##### Changed - **A title in `nldd-toolbar` keeps its own width while items can still move into the overflow menu.** It used to shrink first: next to a few buttons a title like "Aanvraag A-1042" came down to "Aanvraag A-…", or to nothing at all, while every button stayed. Now the items go first, in `priority` order, and the title only truncates once none is left to move. `min-width` on `nldd-toolbar-title` defaults to the width of its text, up to `max-width`. Set `min-width="0"` for the old behavior. - **Only the ribbon and the wordmark text in `nldd-top-navigation-bar` take a click.** The logo link spans the whole width beside the ribbon, which keeps the ribbon centered, and all of that space used to be clickable. It is still one link with one tab stop, named by the wordmark. - **`nldd-blockquote` wraps with `text-wrap: pretty`**, the quote as well as the attribution, so neither ends on a single word on its last line. ##### Breaking - **The current step in `nldd-step-indicator` is `status="current"` on the step.** It was a number on the parent (`current="2"`), which pointed at the wrong step as soon as an app left one out. Now it is the same `status` a step already had, with the same three values as `nldd-timeline-track-cell`: `current` marks where you are and the parent derives the rest from it, while `past` and `future` stay an exception for one step. With no step marked, step 1 is current, and with more than one the last wins. Move the attribute: `<nldd-step-indicator current="2">` becomes `status="current"` on the second item. A leftover `current` on the parent no longer does anything, and a dev build says so in the console, also when a framework sets it later. - **The long form of a skill name is `/nldd-design-system:nldd-design`**, no longer `/nldd:nldd-design`, because the prefix follows the plugin name. This holds for existing installs too, from their next update. A permission rule such as `Skill(nldd:nldd-design-build)` or a hook that matches on the long form stops matching, without an error. The short form (`/nldd-design`) is unchanged, and so is the skill an assistant picks by itself. The README has a search that finds the places to change. ##### Fixed - **Running text no longer grows when a phone turns to landscape.** iOS Safari enlarged the paragraphs in `nldd-rich-text` while the titles kept their size. `@nldd/design-system/styles` now sets `text-size-adjust: 100%` on `html`, in the reset layer, instead of on `nldd-rich-text`. If you load only the tokens, set it on your own root. - **The stretching ribbon in `nldd-top-navigation-bar` is limited to Safari, and to every browser on iOS.** Chrome does not draw anything above the top of the page, so on a pull it showed only the piece that holds still at the top, and a hard pull opened a gap between that piece and the logo. Chrome and the other non-WebKit browsers now show the plain gap above the ribbon again, as they did before 0.8.94. ### [`v0.8.94`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0894-2026-10-05) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.93...v0.8.94) ##### Highlights - **The package speaks more languages.** One call, `setTranslations(enUS)` at startup, turns every component English, including the ones another component builds out of your reach, such as the activity indicator in a loading button and the calendar in a date field. US English ships complete, with concept sets in Frisian and in Papiamento as written on Curaçao and Bonaire and on Aruba. Docs/Vertalingen in Storybook explains the layers. - **`nldd-text-editor` checks the spelling and handles typeaheads better.** It checks the running text and leaves code, addresses and mentions alone. A typeahead query takes accents and a `+`, a list can decide what may follow its trigger, and an empty list says why instead of closing without a word. - **`nldd-toggle-button` can be quiet.** It takes four appearances from `nldd-button`, the two transparent ones included, and with `selected-icon` a transparent toggle stays without a fill when on: a "Volgen" toggle goes from `plus` to `check-mark` and keeps its label. - **The ribbon in `nldd-top-navigation-bar` stretches when the page is pulled down**, instead of opening a white gap above it. - **Menus line up, and use fewer icons.** One checkbox or radio item gives the whole `nldd-menu` its check-mark column, so the text of every group starts at one line. A new design guideline says when an icon in a menu adds something, and when it is only filler. - **Button bars and split buttons work on a colored surface.** `nldd-button-bar` and `nldd-split-button` take `inherit-tinted` and `inherit-filled`, like the buttons inside, instead of a gray block. The inherit buttons now keep one color through hover, press and expanded, so their label keeps the contrast the surface gives it. - **Attributes say what they do.** `variant` is `appearance` on nine components where it was a designed style, `level` on `nldd-timeline-track-cell`, and `mode` is `variant` on `nldd-progress-bar` and `nldd-progress-circle`. The values stay the same; search your markup, since a leftover attribute is ignored without a warning. See Breaking. ##### Added - **Storybook opens on an introduction.** Docs/Introductie says what the system is, how to install it and load the styles, where the components, patterns and design guidelines are, and how to add the Claude Code plugin. It used to open on Button, the first story in alphabetical order. Docs now sits at the top of the sidebar, with the introduction and the design guidelines first. - **`setTranslations()` sets the texts for the whole package.** Import it from `@nldd/design-system/translations` and call it once at startup. A component now looks a text up in four layers: an attribute on the element, its `translations` property, the package-wide layer, and the Dutch default. Calling it again re-renders the components on the page, so a language switch at runtime works too. In development it warns about a key no component knows, which is what an override does after a key is renamed. - **A complete US English set, `@nldd/design-system/translations/en-US`, and the Dutch defaults as a template, `@nldd/design-system/translations/nl`.** Spread the English set and add your own keys behind it to change a few texts: `setTranslations({ ...enUS, 'components.activity-indicator.loading-label': 'Please wait' })`. - **Concept translations in Frisian (`translations/fy`) and Papiamento as written on Curaçao and Bonaire (`translations/pap-CW`) and on Aruba (`translations/pap-AW`).** Every text is translated, also where the wording is a guess, since correcting a text is easier than writing one. No native speaker has checked them yet: report a better wording as an issue and they improve with each release. - **`no-filter` on `nldd-combo-box` and `nldd-token-field`** leaves the options as they are while typing, for a list your server already filtered per keystroke. Without it the field hides every option that does not contain the typed text, which also hides a server match on, say, an e-mail address. The part of an option that matches the typed text is still marked. - **A typeahead in `nldd-text-editor` says why its list is empty.** It closed without a word, so whoever typed `@` could not tell "nobody matches" from "mentions do not work here". Where the list would be it now says "Typ om te zoeken" for an empty query and "Niets gevonden" for one without matches, both translatable. `emptyText` on a list, and `mentionEmptyText` for the built-in `@`, are called with the query and can say more, such as "Kies eerst een kanaal bij Aan"; return null to close without a word, as before. The message is a status a screen reader announces, not an option you can select. - **A typeahead list in `nldd-text-editor` decides what may follow its trigger.** `query` on a list, and `mentionQuery` for the built-in `@`, take a regular expression for the text after the trigger. A list of people can allow one space, so `@sam jansen` finds the right Sam. Lists on one trigger share the query of the first that sets one. - **`inherit-tinted` and `inherit-filled` on `nldd-button-bar` and `nldd-split-button`**, for a group of buttons on a colored surface. The buttons inside already had them, but the bar kept its gray surface behind them. Like a loose button, the group now takes its colors from the text color around it, and `inherit-tinted` draws its see-through surface once for the whole group, so the tint does not stack. - **A design guideline on icons in menus.** Icons are often used as filler, but are usually not needed and then do not help: add one only where it recognizably belongs to the item and helps people find or understand it, use the same icon for the same action everywhere, and leave it out when no icon makes the action clear at a glance. See Docs/Ontwerprichtlijnen under "Visueel en layout". - **`appearance` on `nldd-toggle-button` and `nldd-toggle-button-group`: `neutral-tinted` (the default), `neutral-base`, `neutral-transparent` and `accent-transparent`.** A toggle among transparent buttons, such as in a row of light actions under a message, stood out as a gray block. The transparent appearances have no surface at rest; when on, the toggle fills, so the state does not rest on a color alone. `neutral-base` is for a tinted surface. `nldd-toggle-button-group` forwards `appearance` to its buttons, as it does `size`. New tokens: `--semantics-buttons-neutral-transparent-is-selected-*` and `--semantics-buttons-accent-transparent-is-selected-*`. - **`selected-icon` on `nldd-toggle-button`** shows another icon while the toggle is on, such as `plus` to `check-mark` on a "Volgen" toggle whose label stays the same. On the transparent appearances it replaces the fill: the toggle stays quiet when on, and the change of shape says it is on. On a surface, the surface fills as before. - **`appearance="neutral-base"` on `nldd-segmented-control`**, for a segmented control on a tinted surface, as `nldd-button-bar` has it. The selected segment keeps its fill. For a quiet row without a track, use `nldd-toggle-button-group` with `type="radio"` and a transparent appearance. - **The font files are exported as `@nldd/design-system/fonts/*`.** A site that serves the fonts itself without a bundler, such as a static site that only publishes its own folder, had to copy the woff2 files from `node_modules` into its own repository. A build step can now take them from the package, with `import.meta.resolve('@nldd/design-system/fonts/RijksSansWeb-Regular.woff2')`, so the copies and their separate license notes can go. The terms in `NOTICES.md` do not change: the path is only reachable. - **A card that is one link or button reacts to hover and press.** With `href` or `button`, `nldd-card` steps its surface and its border one shade up on hover and one more while pressed, on `base` and `tinted` alike, as a `neutral-base` button does. A button lifted above the card in its footer does not set it off. - **`loading-text` on `nldd-button` and `nldd-icon-button`** says what the screen reader announces while `loading` is on, for a button that does more than load: "Aan het bewaren". Without it the indicator says its translated "Laden". - **The ribbon in `nldd-top-navigation-bar` stretches when the page is pulled down.** Pulling a page past its top used to open a white gap above the ribbon; the ribbon now carries on into it and only grows longer. A bar above the navigation bar, such as `nldd-status-bar`, stays clear: the ribbon starts at the top of the page, not right above the logo. It works in browsers that support scroll-driven animations; elsewhere the gap stays as it was. ##### Changed - **`nldd-text-editor` checks the spelling, like the other text fields, and `no-spellcheck` turns it off.** It never did: CodeMirror switches spellchecking off. Now it is on for the running text and off for what the editor knows is not: inline code and code blocks, the address of a link and a bare URL (the link text is checked), and mentions. Autocorrect and autocapitalize follow the user's own settings, as in the other fields, also with `no-spellcheck`. Deleting a character or a selected word keeps the underlines on the rest of the line, as it does in a plain text field. Two limits come from the browser: text that was already there is checked once you edit near it, not when the editor opens, and markup that changes how a line is built, such as starting a list item, hides the underlines on that line until you type on. An editor that should not be checked takes `no-spellcheck`. - **The `inherit-tinted` and `inherit-filled` buttons keep one color through hover, press and expanded.** The label on these buttons has only the contrast the colored surface around it gives, and every state color moved the background toward the label: on a surface that just met 4.5:1, a hovered or pressed button fell below it. In a button bar the states did not show at all, since the bar's own surface lay underneath. This applies to `nldd-button`, `nldd-icon-button`, `nldd-button-bar` and `nldd-split-button`; the focus ring stays. The forty `--semantics-buttons-inherit-*-is-*` tokens for those states are gone, as nothing uses them any more. - **One checkbox or radio item in an `nldd-menu` gives every item in that menu the check-mark column.** Only the checkable items had it, so a group of plain actions below a group of options started its text further left, and the menu could no longer be scanned from top to bottom. The text of the whole menu now starts at one line, as in a native menu. A plain item keeps the column empty and is announced as before. An icon gets no column of its own: it starts where the text of an item without an icon starts. A submenu decides for its own items. - **`nldd-button-bar` warns in development about an `nldd-toggle-button` inside it.** The bar is one surface for actions, and it showed a toggle button half: its own size and border, a selected fill under the bar's ring. Use `nldd-toggle-button-group` for a row of toggles, or `nldd-segmented-control` for one choice out of a few options. - **`NOTICES.md` covers the logo and the house style of the Rijksoverheid as well, not only the fonts.** The logo in `nldd-top-navigation-bar`, the favicon and the touch icon, the ribbon and the house style colors fall outside the EUPL: the Staat der Nederlanden reserved copyright on them, and they are for the Rijksoverheid and parties working on its behalf only. The coat of arms may only be used together with the ribbon. The README and the `nldd-design-build` skill point to it. - **Running text wraps with `text-wrap: pretty`, headings in `nldd-rich-text` with `balance`.** `nldd-text`, and the paragraphs, list items, definitions and quotes in `nldd-rich-text`, no longer end on a single word on their last line, as the cells and the status components already did. Headings in `nldd-rich-text` had `pretty` and now break into lines of even length, the way `nldd-title` does. Browsers without support, Firefox for now, break lines as before. - **`nldd-dropdown` fades a long option out instead of ending it with an ellipsis.** The field now shows its choice through the native `<select>`, and WebKit neither keeps that text out of the end padding nor draws an ellipsis there, so every browser fades the text before the icons. Two side effects: desktop Safari draws the options in its popup at the field's text size, 18px at `md` instead of 16px, and an `xs` dropdown shows 16px text on touch devices, because iOS zooms in on a smaller select when you tap it. ##### Breaking - **`variant` is now `appearance` on `nldd-button`, `nldd-button-bar`, `nldd-icon-button`, `nldd-split-button`, `nldd-keyboard-shortcut`, `nldd-code-viewer`, `nldd-code-editor`, `nldd-text-editor` and `nldd-list`.** The values stay the same, so `variant="primary"` becomes `appearance="primary"`, and the property is `appearance` too. `variant` meant two different things across the system: how something is drawn, and what kind of thing it is. On these nine it was always the first, a designed style with its color included, so it now has a name of its own. `variant` stays on the components where it says what kind of thing it is and sets the icon and role with it, such as `nldd-banner`, `nldd-notification`, `nldd-status-bar` and `nldd-inline-dialog`. A `variant` left on one of the nine is ignored without a warning and the component falls back to its default style, so search your markup for it. The exported types follow: `CodeViewerVariant`, `CodeEditorVariant`, `TextEditorVariant`, `ListVariant` and the `Variant` of `nldd-icon-button` are now `CodeViewerAppearance`, `CodeEditorAppearance`, `TextEditorAppearance`, `ListAppearance` and `Appearance`. - **`variant` on `nldd-timeline-track-cell` is now `level`.** `major`, `minor` and `none` say how far down the hierarchy a row sits: `minor` is a row that belongs under the one above it. The values stay the same, so `variant="minor"` becomes `level="minor"`. - **`mode` on `nldd-progress-bar` and `nldd-progress-circle` is now `variant`.** `progress` and `distribution` are two kinds of indicator, progress toward a goal and the parts of a whole, and the screen reader hears something different for each, which is what `variant` stands for in this system. The values stay the same, so `mode="distribution"` becomes `variant="distribution"`. The types `ProgressBarMode` and `ProgressCircleMode` are now `ProgressBarVariant` and `ProgressCircleVariant`. ##### Fixed - **A typeahead query in `nldd-text-editor` takes accents and a `+`.** `@józef` stopped at the `ó` and `:+1:` at the `+`, so the source never saw the rest. What may follow a trigger is now letters in any script and with any accent, digits, `_`, `.`, `+` and `-`, for every list. A space still ends the query, as it ends a mention in most systems. - **`nldd-combo-box` with `allow-custom` keeps a value chosen from the menu.** Leaving the field, or pressing Enter, committed the shown text as the value whenever it differed from the value. That is the normal state after every choice ("Nederland" for `nl`), so in a form the label went to the server instead of the value, usually on the click on the submit button. Only text the user typed is committed now, and typing an option's label in full picks that option. `nldd-token-field` did the same with a typed label: "België" became a token with the value "België" instead of `be`, on Enter, on a comma or when leaving the field. It now adds the option. - **`nldd-combo-box` and `nldd-token-field` open when the options arrive after the keystroke.** A field that queries its server per keystroke slots the matches in a moment later. With `allow-custom`, and on the token field always, the keystroke found nothing to show and kept the menu shut, and nothing looked again when the options came in, so the list only appeared on the next letter. The options that arrive now open it, as long as the user is still in the field and did not press Escape. A menu whose options all go away closes again. - **A component that another component builds can be translated.** The activity indicator in a loading `nldd-button`, `nldd-icon-button` and `nldd-inline-dialog`, the tokens of `nldd-token-field`, the overflow menus of `nldd-toolbar`, `nldd-menu-bar` and `nldd-document-tab-bar`, and the pickers of `nldd-date-field` and `nldd-time-field` sit in a shadow root, so the `translations` you set on the outer element never reached them and they stayed Dutch. They read `setTranslations()` now. - **`nldd-dropdown` shows the value your app sets.** A value set with `select.value`, `selectedIndex` or `option.selected` kept the old label on screen until someone picked an option by hand, so a form that loaded saved data showed a different choice than it held. The label was a copy in the shadow DOM that only updated on `slotchange` and `change`. It is gone: the `<select>` now shows its own choice, so there is nothing left to go stale. - **The changelog no longer repeats its introduction** under 0.8.93. - **The `global` and `utility` slots of `nldd-top-navigation-bar` are documented.** The component has always rendered both, each taking an `nldd-menu-bar`, but neither had an `@slot` line. `custom-elements.json` and the reference in `nldd-design` therefore listed no slots for it, and a check that validates markup against the manifest rejected `<nldd-menu-bar slot="global">`. The default slot of `nldd-progress-circle`, where its segment indicators go, was missing the same way. ### [`v0.8.93`](https://github.com/NederlandseDigitaleDienst/design-system/blob/HEAD/CHANGELOG.md#0893-2026-09-30) [Compare Source](https://github.com/NederlandseDigitaleDienst/design-system/compare/v0.8.92...v0.8.93) ##### Highlights - **The patterns are live in Storybook**, with their examples running and a test on what each one promises. The pages in the skill are generated from that same markup, so what you copy is what you saw. - **The skills are split and renamed, so the name says the task.** `nldd-design` holds the reference, the changelog and the design guidelines, and `nldd-design-build`, `nldd-design-migrate`, `nldd-design-upgrade` and `nldd-design-contribute` each cover one job. A skill named `nldd` stays behind to catch the old name until 1 March 2027. Update the references in your own instruction files first: a skill that is not found warns nobody, it just makes the answer worse. - **Four design guidelines come with this release**, on where work that needs its context belongs, on a filtered list as a mode, on sticky headers, and on the two shapes a heading can take. They are in `nldd-design`, and Storybook has them under Docs. ##### Breaking - **The page sections no longer take `scheme`.** `nldd-simple-section`, `nldd-full-bleed-section`, `nldd-hero`, `nldd-sidebar-section` and the two- and three-column sections could pin `light`, `dark` or `inverted` on a band, which made one section decide the color scheme for everything inside it. A section still draws its surface with `background`, which is what the components inside read; light and dark stay a choice for the page, through `color-scheme` on a root element. `nldd-window` keeps its own `scheme`. - **`nldd-button-group` follows its own width, and that is its default.** `orientation` was `horizontal` or `vertical`, with `vertical` as the default, so every group that did not say otherwise stacked its buttons at every width. It now takes `auto` as well, and that is the new default: a row, and stacked over the full width once the group itself is narrower than the sm breakpoint. The group is its own container query, so the same group is a row in a page and a stack in a sheet beside it, without a media query of yours. A group that wants to keep stacking everywhere says `orientation="vertical"`. A stacked group stretches the buttons through `--context-button-width`, which `nldd-button` now reads, so a button follows the parent that stacks it without anyone setting `width="full"`. The group used to write that attribute onto its children and take it off again; it no longer touches them, so CSS or a test of yours that keys on `[width="full"]` inside a group stops matching. - **The skills are now `nldd-design`, `nldd-design-build`, `nldd-design-migrate`, `nldd-design-upgrade` and `nldd-design-contribute`.** `nldd` meant four things at once: the organization, the npm package, the plugin and the skill inside it, so the name said nothing about what the skill was for and its description had to carry an anti-trigger instead. The names now say the task. What is shared between them, the component reference, the changelog and the design guidelines, moves to `nldd-design`: that is reference material whether you are building something new or converting something old, and a migration needs it as much as a new app does. **Raising the version of an app that already runs on this system is its own skill**, `nldd-design-upgrade`. It sat as a section inside the build skill, which is the wrong place twice over: an upgrade is not building something new, and it is not a migration either, so whichever of the two you reached for, the guidance was in the other one. It matters here more than in most systems because this project releases everything as a patch, including a breaking change, so the version number tells you nothing about whether a jump is safe. That is a deliberate choice in `.releaserc.json`, not how semantic-release behaves by default, which makes it easy to assume the usual semver signal is there when it is not. **A skill named `nldd` stays behind to catch the old name**, and does nothing but point at the ones that replaced it. It is deliberately findable by the model and not just by `/nldd`, because the reference that breaks most quietly is a line in your own `CLAUDE.md` saying "use the nldd skill": nobody types anything there, so a slash command would not catch it. **It is removed after 1 March 2027**, so update your references rather than lean on it. **The plugin is still called `nldd`.** Installing it does not change, and `enabledPlugins` and `extraKnownMarketplaces` point at `nldd@nldd-plugins`, the plugin, so leave those alone. What to check, quietest first, because the first two give you no error at all: 1. **The skill name in your own instruction files**: `CLAUDE.md`, `.claude/rules/*.md`, `AGENTS.md`, or the body of a skill of your own that says "use the nldd skill". Claude reads the instruction, does not find the skill, and carries on without it. Nothing warns; the output is just worse. 2. **The skill name in subagent definitions** (`.claude/agents/*.md`) **and in hooks that match on it.** Equally silent. 3. **`Skill(nldd)` in permission rules.** It stops matching, so you get a permission prompt where you had none. 4. **Scripts or CI that call `claude -p "/nldd ..."`.** Since Claude Code 2.1.273 an unknown slash command is no longer a free deterministic rejection but a model call that answers with a "did you mean" text, so a script checking the exit code still sees 0 and now gets billed, variable output instead of a fixed error. 5. **Typing `/nldd` interactively.** The loudest and least harmful. Invoke a skill either way: `/nldd-design-build` is the short form, and `/nldd:nldd-design-build` always resolves to ours even when a skill of your own carries the same name. - **The `subtitle` slot of `nldd-title` is now `supporting-text`.** That is what the text under a title is called in every other component, including `nldd-top-title-bar`. Rename `slot="subtitle"` to `slot="supporting-text"`, or use the new `supporting-text` attribute for plain text. Content still in `slot="subtitle"` is not shown, and in development the console says once which rename it needs. - **`nldd-form-section` calls its supporting text `supporting-text` throughout.** The span in the legend is now `.form-section__supporting-text` instead of `.form-section__subtitle`, and its token `--semantics-forms-section-supporting-text-font` instead of `--semantics-forms-section-subtitle-font`. The attribute already had that name. Rename the class in your CSS and the token where you override it: the old ones do nothing any more, without a warning. - **`nldd-page` in a split-view pane no longer carries the document's landmarks.** A page carries them: its header is the banner, its content the main landmark, its footer the contentinfo. A document has one of each, so two pages beside each other were two of each, which is invalid HTML that nothing on screen gives away. A page in a pane of a navigation, side-by-side or stacked split view, or inside an overlay, now renders a section and a plain div instead, which drops all three at once: a header inside sectioning content is no longer a banner. **Set `landmarks="page"` on the page in the pane that holds your primary content**, because only the application knows which pane that is. Nothing warns when you do not: the app shell simply has no main landmark, and a screen reader user loses the jump to the content. Give the other panes an `accessible-label` and they are named regions instead, which is a landmark worth having. `landmarks` also takes `region` to step down anywhere else, and a second page that still renders a main says so in development. - **`nldd-icon` takes `icon` instead of `name`.** Every other component that renders an icon already called it `icon`, so you had to remember the one exception. Rename `name="…"` to `icon="…"` on every `nldd-icon`. An icon that still has `name` draws the dashed placeholder circle, and in development the console says once which rename it needs. - **The `--components-title-*` tokens are gone.** `--components-title-{sm,md,lg}-overline-font` and `--components-title-{sm,md,lg}-subtitle-font` stood in `variables.css`, but `nldd-title` never read them, so overriding one changed nothing. The overline and the supporting text take `--primitives-font-body-sm-regular-tight` and `--primitives-font-body-md-regular-tight`. The two names are removed rather than renamed, so a `var()` of your own that points at one resolves to nothing. ##### Added - **`nldd-list-item-segment` can be the button that opens a menu.** It takes `popup-type`, `popovertarget` and the popover-invoker properties the buttons already had, so a row can carry a "more" action that looks like part of the row instead of a button dropped on top of it. An `nldd-menu` anchored to the segment seeds its own type and keeps `aria-expanded` in step, the same as with `nldd-icon-button`. - **`nldd-button` takes a `form` attribute.** A save button in a sticky footer sits outside the form it saves, and pointing it at that form did not work: the platform resolves `form` to a real `<form>` element, while `nldd-form` renders its own form without handing it the id you wrote. So the button found an element that was not a form, ended up with no form owner, and did nothing at all when clicked. It now resolves the id itself and takes the form an `nldd-form` renders, as well as a plain `<form>`. An id that finds nothing, or an `nldd-form` that has not rendered its form yet, says so in development instead of letting the click do nothing. - **A skill for migrating an existing codebase** (`nldd-design-migrate`). What goes wrong when you convert an application that already exists, and how you notice before your users do. The system fails silently, so the skill is built around checks that make the silence audible: what to verify before you convert anything, how to measure what a page still *does* rather than how it looks, and what to do when the fault is ours rather than yours. Separate files cover coming from Tailwind and rendering HTML on the server with fragment swaps (htmx, Turbo, Unpoly, LiveView), where one rule explains most of the trouble: a swap does not run a component's lifecycle the way a page load does. - **A skill for raising the version** (`nldd-design-upgrade`). Reading the changelog as an upgrade path: which entries to read first, what to search your own code for, and why renamed CSS variables are the trap that catches most people. Your own theme overrides then point at a name that no longer exists, with no error and no visible break, just a silent fall back to the default. - **A skill for proposing a change** (`nldd-design-contribute`). Where a report goes first, which depends on who you are: inside NLDD it goes to the design system channel on Mattermost, which is shorter than an issue and where the maintainer reads along, and from outside NLDD it goes to a GitHub issue. Then how to write it so it gets somewhere: describe the problem in your interface rather than only the component you have in mind, because often something existing already does it, and when it does not, your context shapes the design. It also states plainly what to expect, that the maintainer decides and a rejection comes with a reason, and it carries the rule that keeps the pattern set small: a composition used by several teams is a pattern of the system, one that lives in a single app is that app's habit for now. `CONTRIBUTING.md` stays the source for maintainers; this is the consumer's half of it. - **The patterns are live in Storybook.** Every pattern of `nldd-design-build` has a page under "Patronen", with its example running and a test on what the pattern promises: that the sheet closes once, that a confirmation puts the way out first, that a page has one `h1`. The pattern pages in the skill are generated from the same markup, so the example you copy from the skill is the one that is tested. Rules about a single component moved out of the patterns and into that component's documentation, and a design rule is stated once, in the design guidelines. The content page came along as a pattern of its own: it used to travel as a loose example, without a running example and without a test. - **Four design guidelines, and a section that says what it holds.** Work that needs its context belongs in a sheet, not a modal or a page of its own, and a sheet buys you the full height of the screen. A filtered list is a mode as soon as you cannot see which filters are on. Avoid a sticky header: the content matters more than the bar above it, with the title bar that says what you are looking at as the one exception. And a heading is either a short summary written as a sentence or a label kept as short as it goes, which is a choice about what the reader is doing rather than about the kind of page. "Microcopy en toon" is now "Copywriting", because it covers headings as well as the small print. - **`open` on `nldd-sheet`, `nldd-modal-dialog`, `nldd-window` and `nldd-popover`.** Bind it instead of calling `show()` and `hide()` from your own code, for example `<nldd-sheet :open="isOpen" @close="isOpen = false">` in Vue. The overlay clears it when it closes another way, by Escape, the backdrop or its close button. `show()` and `hide()` keep working and set it too. On `nldd-popover` it replaces the read-only `open` property, and opening still needs an anchor. The build skill, its Vue example and the patterns now bind `open` instead of calling `show()` and `hide()` from a watcher, and the migration skill tells a server-rendered app to put `open` in the markup, which needs no JavaScript at all. - **`text`, `supporting-text`, `overline` and `heading-level` on `nldd-title`.** `size` sets how big the title looks, `heading-level` which heading it is, and you now see both side by side on the element. Without `heading-level` the text is a paragraph, for a title that is not a heading. Each text keeps a slot for content that is more than text, such as a link: the default slot, `overline` and `supporting-text`. A filled slot takes the place of its attribute. - **`heading-level` on `nldd-top-title-bar`.** The title was always an `h1`. It still is by default, and you can lower it where the bar is not the top of the page. ##### Changed - **A stacked `nldd-button-group` leaves an icon button at its own size.** Everything in a stack fills the width, which turned an `nldd-icon-button` into a full-width bar with one glyph in the middle: wider, not a bigger target. Only `auto` is a container query now, so only `auto` has to take its width from its parent: a group pinned to `horizontal` or `vertical` sizes itself again, which it could not do in a parent that shrink-wraps (an inline-flex box, a float, a table cell, a flex item at `width: auto`). An `auto` group that ends up in such a parent measures zero and says so in development. - **The edge of a surface is the same grey as a line inside it again.** `--semantics-surfaces-base-border-color` and `--semantics-surfaces-tinted-border-color` go back to `neutral-75` in light mode and `neutral-200` in dark, the values `--semantics-dividers-color` carries, which undoes the lighter edge of 0.8.89. Everything that draws its outline from these tokens is a step more present: `nldd-table`, `nldd-list`, `nldd-code-viewer`, `nldd-rich-text` and the boxes that follow them. Override the two tokens to keep the lighter edge. - **`nldd-sheet` and `nldd-window` take their name from the title bar.** Without `accessible-label`, a screen reader called them "Venster" unless you repeated the title there. They now take the `text` of the `nldd-top-title-bar` inside them, and follow it when it changes. `accessible-label` still wins, for a name that has to differ from the title. The development warning only appears when neither is there. - **`nldd-list-item` warns about anything in a row that is not a cell or a segment.** Bare text or a loose element gets none of the typography, size and alignment a cell brings, and in a clickable row bare text falls back to the browser's button font. The row now says so once in development. Wrap the content in a cell. - **`nldd-list-item` warns about a control inside a row that is its own control.** An icon button or a segment in a row with `href`, `button`, `checkbox` or `radio` nests a control inside a control: invalid HTML, and a second tab stop. The documentation already said the row warned about this, but it did not. A `decorative` checkbox or radio button, which only shows the row's state, is fine. - **`nldd-toolbar-item` warns when it has nothing in `slot="overflow"`.** On a narrow toolbar such an item moves into the overflow menu and its action is gone, which you never see on a wide screen. The item now says so once at load in development. A tab bar is no exception: its alternative is a menu group of `type="radio"` items. - **`nldd-rich-text` looks through a single wrapper `div`.** The rhythm and the width zones apply to the direct children, so content wrapped in one `div` became a single block and its paragraphs sat against each other. A markdown renderer or the root of a framework component produces exactly that wrapper, and you cannot always remove it. A lone `div` without `class`, `style`, `role` or `data-width` is now passed through, and its children are laid out as if they were direct. A wrapper with any of those stays one block, since you gave it something of its own. - **The element that holds the notifications is `nldd-notifications-area`.** It was `nldd-notification-region`, a singular name for the thing that owns every notification at once, and "region" named its ARIA role rather than its job. The id is the only part of it you can see, in the DOM; nothing about the notifications themselves changed. The three overlays that take it in, `nldd-sheet`, `nldd-window` and `nldd-modal-dialog`, now document their `notifications` slot, which the package fills itself. - **The CSS variables are documented as internal.** They are the wiring of the components, not a public API: they get renamed, merged and removed whenever a component asks for it, and the changelog describes such a change from that component, not from your stylesheet. Steer a component through its attributes. Reach for a variable only for something that is not a component at all, and then at your own risk. - **`nldd-token` names its buttons after itself.** The dismiss button was called "Verwijder" on every token, so a row of filters read as a row of identical buttons unless you composed a `dismiss-text` per token. Unset, it is now `Verwijder "{text}"`, and the menu button `Toon opties voor "{text}"`, with the token's own text in the quotes. A `dismiss-text` or `menu-text` you set still replaces the whole label. Both properties now default to an empty string instead of the bare word. The words themselves come from `translations`, like every other user-facing string in the package: `components.token.dismiss-action`, `components.token.open-menu-action` and `components.token.open-token-menu-action`. `nldd-token-field` names its tokens the same way, through its own translations, where `components.token-field.token-menu-action` reads "Toon acties voor" so the token's text can follow it. ##### Fixed - **`nldd-window` opens when `show()` comes before its first render.** Sheet and modal already waited for their dialog. The window did nothing and said nothing, so a window opened in the same tick it was created stayed shut. - **The validation icon of `nldd-token-field` stays in the top corner.** It was centered over the whole field, so the moment the tokens wrapped to a second row it drifted down the side, away from the row it belongs to. It now sits where `nldd-multi-line-text-field` puts its own: at the top, level with the first row. - **A tree row's divider no longer jumps when the branch opens.** The chevron turned by rotating the whole `nldd-icon-cell`, and a rotated element reports a turned box to `getBoundingClientRect()`. That box is what the row measures to place its divider, so the same row drew its line 12px further left while it was expanded. The cell now turns its glyph instead, through the `icon` part it exposes, and keeps its own box where it was. - **`nldd-list-item` documents where a row's divider starts.** `divider-start` and `divider-end` go on a cell in the row and move the line off its default, the first text or title cell. The item has always read them, but only its prose said so, so neither the reference nor the markup validator knew they existed. An indented tree row could not get its line to start at the icon without guessing. - **`nldd-bar-split-view` documents the order attributes of its panels.** The component reads `sm-order`, `md-order` and `lg-order` off its children to place a bar above or below the content per breakpoint, but only its prose said so, so the reference listed neither the attributes nor what they do. A bottom bar on a phone was there all along and nobody could find it. - **`nldd-validation-item` has a description in the reference.** The component reference takes the prose above the first `@element` in a file. Two components that share a file write their own prose under their own `@element`, and that was thrown away, so the item shipped as a bare table of attributes and the rule about giving it an id that names its field reached nobody. `nldd-navigation-split-view` lost a line the same way. Both are back, and `nldd-form` now says when it marks a field as invalid. - **`hidden` now hides every component.** Nine components stayed visible with `hidden` set, because their own `display` beat the browser's rule for the attribute. `nldd-list`, `nldd-sheet`, `nldd-navigation-split-view`, `nldd-menu`, `nldd-progress-bar-segment-indicator` and `nldd-form` never hid. `nldd-number-field` with `width="full"`, `nldd-pagination` with `centered` and an `nldd-activity-indicator` around content did not hide either. </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Amsterdam) - Branch creation - "before 6am on sunday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMTUuMTAiLCJ1cGRhdGVkSW5WZXIiOiI0NC4xMTUuMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Update dependency @nldd/design-system to ^0.8.93
Some checks failed
CI / pre-commit (pull_request) Successful in 2m18s
CI / frontend-test (pull_request) Successful in 5m47s
CI / e2e (pull_request) Failing after 37m7s
CI / backend-test (pull_request) Failing after 45m15s
CI / release-scripts (pull_request) Successful in 16s
security-scan / JS SCA (npm audit) (pull_request) Successful in 25s
security-scan / Python SAST (bandit) (pull_request) Successful in 28s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 23s
security-scan / SBOM (trivy) (pull_request) Successful in 14s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 47s
test-build / build (frontend) (pull_request) Successful in 1m56s
test-build / build (backend) (pull_request) Successful in 2m3s
test-build / build (pull_request) Successful in 0s
77669bb57b
robbertbos force-pushed renovate/nldd from 77669bb57b
Some checks failed
CI / pre-commit (pull_request) Successful in 2m18s
CI / frontend-test (pull_request) Successful in 5m47s
CI / e2e (pull_request) Failing after 37m7s
CI / backend-test (pull_request) Failing after 45m15s
CI / release-scripts (pull_request) Successful in 16s
security-scan / JS SCA (npm audit) (pull_request) Successful in 25s
security-scan / Python SAST (bandit) (pull_request) Successful in 28s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 23s
security-scan / SBOM (trivy) (pull_request) Successful in 14s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 47s
test-build / build (frontend) (pull_request) Successful in 1m56s
test-build / build (backend) (pull_request) Successful in 2m3s
test-build / build (pull_request) Successful in 0s
to 590eec670a
Some checks failed
CI / pre-commit (pull_request) Successful in 2m7s
CI / release-scripts (pull_request) Successful in 17s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 52s
security-scan / Python SAST (bandit) (pull_request) Successful in 31s
CI / frontend-test (pull_request) Successful in 4m17s
security-scan / JS SCA (npm audit) (pull_request) Failing after 33s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 26s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (backend) (pull_request) Successful in 2m23s
test-build / build (frontend) (pull_request) Successful in 2m13s
test-build / build (pull_request) Successful in 0s
CI / e2e (pull_request) Failing after 48m55s
CI / backend-test (pull_request) Failing after 51m3s
2026-10-06 02:02:18 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.93 to Update dependency @nldd/design-system to ^0.8.94 2026-10-06 02:02:21 +00:00
robbertbos force-pushed renovate/nldd from 590eec670a
Some checks failed
CI / pre-commit (pull_request) Successful in 2m7s
CI / release-scripts (pull_request) Successful in 17s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 52s
security-scan / Python SAST (bandit) (pull_request) Successful in 31s
CI / frontend-test (pull_request) Successful in 4m17s
security-scan / JS SCA (npm audit) (pull_request) Failing after 33s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 26s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (backend) (pull_request) Successful in 2m23s
test-build / build (frontend) (pull_request) Successful in 2m13s
test-build / build (pull_request) Successful in 0s
CI / e2e (pull_request) Failing after 48m55s
CI / backend-test (pull_request) Failing after 51m3s
to b696687bde
Some checks failed
CI / pre-commit (pull_request) Successful in 2m29s
CI / frontend-test (pull_request) Successful in 5m35s
CI / release-scripts (pull_request) Successful in 16s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 49s
security-scan / Python SAST (bandit) (pull_request) Successful in 30s
security-scan / JS SCA (npm audit) (pull_request) Failing after 29s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 23s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
test-build / build (backend) (pull_request) Successful in 2m16s
test-build / build (frontend) (pull_request) Successful in 2m11s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Failing after 2h12m7s
CI / e2e (pull_request) Failing after 2h11m52s
2026-10-07 02:02:29 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.94 to Update dependency @nldd/design-system to ^0.8.95 2026-10-07 02:02:32 +00:00
robbertbos force-pushed renovate/nldd from b696687bde
Some checks failed
CI / pre-commit (pull_request) Successful in 2m29s
CI / frontend-test (pull_request) Successful in 5m35s
CI / release-scripts (pull_request) Successful in 16s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 49s
security-scan / Python SAST (bandit) (pull_request) Successful in 30s
security-scan / JS SCA (npm audit) (pull_request) Failing after 29s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 23s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
test-build / build (backend) (pull_request) Successful in 2m16s
test-build / build (frontend) (pull_request) Successful in 2m11s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Failing after 2h12m7s
CI / e2e (pull_request) Failing after 2h11m52s
to 62fd465152
Some checks failed
CI / pre-commit (pull_request) Successful in 2m21s
CI / frontend-test (pull_request) Failing after 5m32s
CI / e2e (pull_request) Failing after 35m58s
CI / release-scripts (pull_request) Successful in 18s
security-scan / Python SAST (bandit) (pull_request) Successful in 29s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 51s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 24s
security-scan / JS SCA (npm audit) (pull_request) Failing after 32s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
test-build / build (backend) (pull_request) Successful in 5m58s
test-build / build (frontend) (pull_request) Successful in 5m50s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 1h10m47s
2026-10-08 02:02:27 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.95 to Update dependency @nldd/design-system to ^0.8.96 2026-10-08 02:02:31 +00:00
robbertbos force-pushed renovate/nldd from 62fd465152
Some checks failed
CI / pre-commit (pull_request) Successful in 2m21s
CI / frontend-test (pull_request) Failing after 5m32s
CI / e2e (pull_request) Failing after 35m58s
CI / release-scripts (pull_request) Successful in 18s
security-scan / Python SAST (bandit) (pull_request) Successful in 29s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 51s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 24s
security-scan / JS SCA (npm audit) (pull_request) Failing after 32s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
test-build / build (backend) (pull_request) Successful in 5m58s
test-build / build (frontend) (pull_request) Successful in 5m50s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 1h10m47s
to f3ef8d8992
Some checks failed
CI / pre-commit (pull_request) Successful in 2m0s
CI / frontend-test (pull_request) Failing after 3m26s
CI / release-scripts (pull_request) Successful in 16s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 50s
security-scan / Python SAST (bandit) (pull_request) Successful in 32s
security-scan / JS SCA (npm audit) (pull_request) Failing after 31s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 25s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (backend) (pull_request) Successful in 2m2s
test-build / build (frontend) (pull_request) Successful in 2m9s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 1h22m49s
CI / e2e (pull_request) Failing after 1h22m23s
2026-10-14 02:02:11 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.96 to Update dependency @nldd/design-system to ^0.8.98 2026-10-14 02:02:15 +00:00
robbertbos force-pushed renovate/nldd from f3ef8d8992
Some checks failed
CI / pre-commit (pull_request) Successful in 2m0s
CI / frontend-test (pull_request) Failing after 3m26s
CI / release-scripts (pull_request) Successful in 16s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 50s
security-scan / Python SAST (bandit) (pull_request) Successful in 32s
security-scan / JS SCA (npm audit) (pull_request) Failing after 31s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 25s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (backend) (pull_request) Successful in 2m2s
test-build / build (frontend) (pull_request) Successful in 2m9s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 1h22m49s
CI / e2e (pull_request) Failing after 1h22m23s
to 2e799e2234
Some checks failed
CI / pre-commit (pull_request) Successful in 2m18s
CI / frontend-test (pull_request) Failing after 5m35s
CI / release-scripts (pull_request) Successful in 18s
security-scan / Python SAST (bandit) (pull_request) Successful in 30s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 51s
security-scan / JS SCA (npm audit) (pull_request) Failing after 36s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 29s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (frontend) (pull_request) Successful in 2m8s
test-build / build (backend) (pull_request) Successful in 2m15s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 29m35s
CI / e2e (pull_request) Failing after 28m25s
2026-10-15 02:02:24 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.98 to Update dependency @nldd/design-system to ^0.8.99 2026-10-15 02:02:28 +00:00
robbertbos force-pushed renovate/nldd from 2e799e2234
Some checks failed
CI / pre-commit (pull_request) Successful in 2m18s
CI / frontend-test (pull_request) Failing after 5m35s
CI / release-scripts (pull_request) Successful in 18s
security-scan / Python SAST (bandit) (pull_request) Successful in 30s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 51s
security-scan / JS SCA (npm audit) (pull_request) Failing after 36s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 29s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (frontend) (pull_request) Successful in 2m8s
test-build / build (backend) (pull_request) Successful in 2m15s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 29m35s
CI / e2e (pull_request) Failing after 28m25s
to 37b0eb6e11
Some checks failed
CI / pre-commit (pull_request) Successful in 2m11s
CI / frontend-test (pull_request) Failing after 3m54s
CI / release-scripts (pull_request) Successful in 18s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 52s
security-scan / Python SAST (bandit) (pull_request) Successful in 32s
security-scan / JS SCA (npm audit) (pull_request) Failing after 35s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 28s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (backend) (pull_request) Successful in 2m17s
test-build / build (frontend) (pull_request) Successful in 4m11s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Failing after 1h35m46s
CI / e2e (pull_request) Has been cancelled
2026-10-17 02:02:27 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.99 to Update dependency @nldd/design-system to ^0.8.100 2026-10-17 02:02:32 +00:00
robbertbos force-pushed renovate/nldd from 37b0eb6e11
Some checks failed
CI / pre-commit (pull_request) Successful in 2m11s
CI / frontend-test (pull_request) Failing after 3m54s
CI / release-scripts (pull_request) Successful in 18s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 52s
security-scan / Python SAST (bandit) (pull_request) Successful in 32s
security-scan / JS SCA (npm audit) (pull_request) Failing after 35s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 28s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
test-build / build (backend) (pull_request) Successful in 2m17s
test-build / build (frontend) (pull_request) Successful in 4m11s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Failing after 1h35m46s
CI / e2e (pull_request) Has been cancelled
to c996e289f4
Some checks failed
CI / pre-commit (pull_request) Successful in 2m24s
CI / frontend-test (pull_request) Failing after 5m36s
CI / release-scripts (pull_request) Failing after 17s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 51s
security-scan / Python SAST (bandit) (pull_request) Successful in 30s
security-scan / JS SCA (npm audit) (pull_request) Failing after 32s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 26s
test-build / build (frontend) (pull_request) Successful in 2m16s
test-build / build (backend) (pull_request) Successful in 2m23s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 26m51s
CI / e2e (pull_request) Failing after 24m7s
2026-10-20 02:10:23 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.8.100 to Update dependency @nldd/design-system to ^0.9.0 2026-10-20 02:10:29 +00:00
robbertbos force-pushed renovate/nldd from c996e289f4
Some checks failed
CI / pre-commit (pull_request) Successful in 2m24s
CI / frontend-test (pull_request) Failing after 5m36s
CI / release-scripts (pull_request) Failing after 17s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 51s
security-scan / Python SAST (bandit) (pull_request) Successful in 30s
security-scan / JS SCA (npm audit) (pull_request) Failing after 32s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 26s
test-build / build (frontend) (pull_request) Successful in 2m16s
test-build / build (backend) (pull_request) Successful in 2m23s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 26m51s
CI / e2e (pull_request) Failing after 24m7s
to 7012667e86
Some checks failed
CI / pre-commit (pull_request) Successful in 4m37s
CI / frontend-test (pull_request) Failing after 11m45s
CI / release-scripts (pull_request) Successful in 16s
security-scan / Python SCA (pip-audit) (pull_request) Failing after 59s
security-scan / Python SAST (bandit) (pull_request) Successful in 42s
security-scan / JS SCA (npm audit) (pull_request) Failing after 29s
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 25s
security-scan / SBOM (trivy) (pull_request) Successful in 17s
test-build / build (frontend) (pull_request) Successful in 2m15s
test-build / build (backend) (pull_request) Failing after 2m44s
test-build / build (pull_request) Failing after 0s
CI / backend-test (pull_request) Successful in 24m14s
CI / e2e (pull_request) Failing after 20m47s
2026-10-22 02:11:46 +00:00
Compare
robbertbos changed title from Update dependency @nldd/design-system to ^0.9.0 to Update dependency @nldd/design-system to ^0.10.0 2026-10-22 02:11:52 +00:00
Some checks failed
CI / pre-commit (pull_request) Successful in 4m37s
Required
Details
CI / frontend-test (pull_request) Failing after 11m45s
Required
Details
CI / release-scripts (pull_request) Successful in 16s
Required
Details
security-scan / Python SCA (pip-audit) (pull_request) Failing after 59s
Required
Details
security-scan / Python SAST (bandit) (pull_request) Successful in 42s
Required
Details
security-scan / JS SCA (npm audit) (pull_request) Failing after 29s
Required
Details
security-scan / Filesystem scan (trivy fs) (pull_request) Failing after 25s
Required
Details
security-scan / SBOM (trivy) (pull_request) Successful in 17s
Required
Details
test-build / build (frontend) (pull_request) Successful in 2m15s
Required
Details
test-build / build (backend) (pull_request) Failing after 2m44s
Required
Details
test-build / build (pull_request) Failing after 0s
Required
Details
CI / backend-test (pull_request) Successful in 24m14s
Required
Details
CI / e2e (pull_request) Failing after 20m47s
Required
Details
Some required checks were not successful.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin renovate/nldd:renovate/nldd
git switch renovate/nldd
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
robbertbos/waggle!471
No description provided.