PUDL is a control grammar modelled on the conventions of desktop toolkits such as GTK: raised buttons, sunken inputs, segmented controls, a master-detail layout, filter chips, key/value tables, switches and server-rendered dialogs. Elevation signals interactivity, so raised means pressable, sunken means input and flat means display. Colour is never the only signal, and every meaningful state carries a glyph.
A theme sets the tokens below for light and dark, and PUDL derives every other token from them. The default palette shown here is a neutral graphite. A topbar containing a menu bar uses a light surface in the light theme and dark graphite in the dark theme. Each menu group forms one slightly raised surface. A project may replace the palette. A change to the accent reaches links, primary buttons, focus rings, filter chips, accent badges, the current list row, selected table rows, a switch that is on and the active window.
The eight category colours tell things apart without saying anything about their state, such as a chart's series, tags or the lanes of a history graph. They are assigned in this order. Each reaches 3:1 on the page, a card and a field, and stays apart from the status colours and the accent. A category colour is never the only way to identify something, so a series has a legend and a tag has its words. A theme that changes the surfaces sets all eight, and in forced colours they all become the reader's text colour.
Every button is raised, because a button can be pressed, and there is no flat button. A disabled button is dimmed but stays raised, since it is still a button, only one that does nothing yet. A disabled button of any kind, primary and danger included, looks like a disabled plain button, whether it carries disabled itself, is disabled by its <fieldset disabled>, or is a link marked aria-disabled="true". A visible context has at most one .btn-primary; a view that seems to need two has a secondary or destructive action hiding in one of them.
A disclosure button shows or hides content in place, like this line. Its chevron points down while the content is hidden and up while it is shown, and it does not latch.
A toggle button latches. With aria-pressed="true" it stays pressed in until pressed again, and the same attribute tells assistive technology that it is on. A primary button may latch too, such as a flash card's Reveal: it keeps its accent and its text, and loses its lift. Press these three.
A field that takes input is sunken. A read-only value is flat, with no field around it, so it never pretends to be editable. A switch is a raised thumb in a sunken track, and when it is on, the track fills with the accent and the thumb sits at the far end, so its position says so as well as its colour. A select is sunken like any field, drawn by PUDL in a .form-select-wrap with the caret glyph as its opener, so it looks the same in every browser. An error leads with its warning glyph.
A form the server has refused comes back with each wrong field marked aria-invalid="true", drawn with a danger border and tied by aria-describedby to the error beneath it, which carries its glyph. A required field's label carries an asterisk drawn from the field's own required attribute. Help text sits under a field in muted type. Related choices, such as radio buttons, sit in a fieldset with a legend, and a file field's button is raised like any other.
In the currency of the receipt.
The amount must be a number greater than zero.
A combo box is a field with a list of suggestions: the reader may type anything, or open the list with the raised button at its end and choose. It is an input with a list and a datalist in a .combo, which works without a script, and pudl-combo.js draws PUDL's list in place of the browser's. An option's data-combo-keys are words to find it by that are not its value, so typing PHP finds the peso and puts its sign in the field. A select marked data-combo becomes a searchable select, which filters as the reader types and keeps a select's value.
Type a code or a name, or choose from the list.
A segmented control offers two to four choices side by side, one of which is chosen: a small scale, kg or lbs, Read or Edit. Its choices are raised keys joined in a row, because they are pressed, and the chosen one is pressed in, as a pressed toolbar button is. Its choices are buttons marked with aria-pressed, or links to views marked with aria-current.
This one is live. It is a theme setting built on pudl-theme.js, which remembers light, dark or system, and follows the operating system's setting while System is chosen, even when it changes with the page open.
Section tabs are a notebook, after the widget of the same name in desktop toolkits. The bar is a recessed band. Each tab the reader can go to is a raised tab standing on the band, because it can be pressed. The tab for where the reader is, marked with aria-current, is flat, a little taller, and open at the bottom into the content below, so the page visibly hangs from it. A page inside a section marks that section's tab with aria-current="true", and the section's own page with aria-current="page". The current tab takes --section-current-bg, which a page whose content sits on the page background sets to var(--bg).
Three small labels each look like what they are. A badge states an entity's state, done or overdue, and always leads with its glyph as well as its colour. A chip names an attribute the thing carries, such as a tag or a trip, and is a plain neutral label. A filter chip, shown with the master–detail layout below, is a filter in force: it is outlined, and its × is a small raised button that removes it.
A badge also counts what is waiting in the topbar's status area, the last thing in the topbar's chrome: one raised group of flat items, each a glyph or a picture, for what runs in the background of an application, with the reader's account last. The badge takes its colours from the topbar, and a badge with nothing to say is not shown.
A card groups what belongs to one thing on a surface lifted slightly off the page.
Receipt attached; charged to the customer's billing account.
A disclosure card opens and closes by one raised toggle at the start of its head, the same toggle a tree's row has, because a card is read and not pressed: nothing else in the head responds to a press. Its summary shows while it is closed, and its body and a foot of actions while it is open. The server writes aria-expanded on the toggle, and pudl-disclose.js does the rest. Move Up and Move Down carry the arrow-up and arrow-down glyphs; an arrow with a stem says movement, where a chevron says direction.
This one opens from the start. A command on a field's label line, such as the menu above, is a small raised control in the label row's end slot; it is never a select, which would be an input holding no value.
Layout arranges components without a surface of its own. A .vstack places them one above another, an .hstack side by side, wrapping rather than widening the page, and an .auto-grid in as many 224px columns as fit, one on a phone. Each keeps document order, with a gap from the spacing grid. Narrow the window to see these cards fall into one column and the buttons wrap.
Three this quarter.
Two waiting for receipts.
One sent.
A record's read-only fields render as a table of labels and values, not as input boxes that cannot be typed into. Flat means display, and the table says so honestly.
| Expense | Hotel, Makati, three nights |
|---|---|
| Created | 2026-10-19 07:00 UTC |
| Amount | PHP 21,600.00 |
| Account | Plan billable |
A data table lists many records, one per row. A column the reader can sort by has a raised header, because pressing it re-sorts, with a glyph showing the column's direction, or two small arrows while it is not the sort. The header is an ordinary link such as ?sort=amount&dir=desc, so sorting needs no script and a sorted list can be shared. Numbers align to the end. A selected row shows a checked box, a tint and an accent edge at its start. When the table is narrow, as on a phone, a table marked .stack shows each row as a small card of labelled values; make this window narrow to see it.
| Expense | Date | Account | State | Amount | |
|---|---|---|---|---|---|
| Hotel, Makati, three nights | Plan billable | done | 21,600.00 | ||
| Airport transfer | Plan billable | receipt due | 1,200.00 | ||
| Team dinner | Non-billable | ready | 6,800.00 |
A table with nothing in it says so in its own row, rather than showing an empty frame.
| Expense | Date | Amount |
|---|---|---|
| No expenses match these filters. | ||
A notice is a message that stays on the page until it is dealt with, and a toast is a passing confirmation that leaves by itself after a few seconds, waiting while the pointer or focus is on it. Both lead with the glyph of their kind and carry a coloured edge, so neither rests on colour alone, and screen readers announce a toast as it appears. An error the reader has to act on is always a notice, because a toast goes away. With pudl-toast.js, a script raises a toast with pudlToast(), and a server can render one into the page after a form redirects.
Receipts are due by Friday
Two expenses on this trip are still waiting for a receipt.
The October report was sent to accounts.
This expense is over the nightly hotel limit for Manila.
Tabs within a page switch between panels of one record in place, where section tabs go to other addresses. They look alike, because to the reader both are tabs. With pudl-tabs.js, a tab is chosen by pressing it or with the arrow keys once the tab list has focus, the tab list is a single stop in the Tab order, and the chosen panel's id becomes the address's fragment, so a link can open a particular panel and a reload keeps it. Without the script, every panel shows one after another.
| Merchant | Makati Garden Hotel |
|---|---|
| Amount | PHP 21,600.00 |
receipt-city-hotel.pdf, 212 KB, attached 19 October.
Submitted 19 October by Ana Reyes; approved 21 October by accounts.
An empty state tells the reader there is nothing here yet and what to do about it. A loading state pairs a spinner with words, in an element with role="status", so it is announced and never rests on the animation alone. The icon buttons on this page, the window buttons and the filter's apply button show a tooltip with their name on hover or keyboard focus, through pudl-tooltip.js.
No expenses on this trip yet
Add one as you spend, and attach its receipt, so the report builds itself.
A long list comes in pages, each an address such as ?page=3, so paging works without script and a page can be shared. The page links are raised; the current page is pressed in, because the reader is already there; and previous and next carry their glyphs and are disabled at either end.
A dialog is a native <dialog class="dialog"> that the server renders into the page, never the browser's own confirm(). A button opens it with command="show-modal", and the browser keeps focus inside it, closes it on Escape and draws the backdrop, which dims the page gently while the panel's shadow does the lifting. The panel is one step brighter than the page. It offers two actions, the safe one first and the committing one last, and a destructive commit carries its warning glyph. The optional pudl-dialog.js provides the command buttons in browsers that do not have them yet.
When a dialog's content is taller than the window, the title and the actions stay in view and only the content between them scrolls, so the way out is never scrolled away. A .dialog-head keeps a filter or another control with the title. A line separates the head or the actions from the content only while something is hidden beneath it, which pudl-dialog.js works out; without it the bands still stay in view, with no lines. The markup is the same as for a short dialog, and the actions may sit in a form that wraps the fields.
A dialog with tabs keeps the size of its largest panel, so choosing a tab never resizes or moves it, and its tab bar runs from edge to edge under the title. The .tabs goes straight inside the dialog, or inside a form that is, and needs nothing else. A dialog that has grown many tabs, or settings the reader comes back to, belongs in a window, whose tabs fill it in the same way. Building screens covers both.
The master–detail layout serves any list beside one of its records. A toolbar runs across the top, the filters in force sit below it as filter chips, and under them the list and the record share the width. The record in view has its row marked, by aria-current on the row's link, with an accent edge on the side facing the record. The list is 260px wide to begin with; with pudl-md.js the reader can drag the divider, or focus it and use the arrow keys.
Opt-in layouts keep a raised handle available after collapse and on narrow screens. Desktop dragging resizes the list; narrow gestures request URL navigation from the host. The persistent article reader demonstrates both modes, click/tap resize controls, and Back/Forward navigation. The persistent sidebar guide defines the state and request contract.
When the layout is 640 px wide or less, on a phone or in a narrow window or panel, it shows either the list or one record, never both. Each is its own URL. The server marks the layout with data-md-pane="detail" when the URL names a record, and the record's pane then opens with a back link to the list, which keeps the filters and names the record's row as its fragment so that the list scrolls back to where the reader left it. The list's toolbar and filter chips belong to the list and step aside while a record is showing. The back link returns to the list the record lives in, and is not a breadcrumb trail. The two layouts below are the same markup at phone width, one on each pane.
Receipt attached; charged to the customer's billing account.
| Created | 2026-10-19 07:00 UTC |
|---|---|
| Amount | PHP 21,600.00 |
| Account | Plan billable |
A menu button opens a panel of choices. The button is raised and carries a caret, so it reads as opening something rather than doing something, and it looks pressed while its panel is open. The panel is lifted like a dialog but has no backdrop, because it is not modal: Escape, a click outside it or a choice closes it. Places in a panel are list rows grouped under section labels, and actions are rows of their own below a rule, each with a glyph. The panel is an HTML popover, so all of that works without script. The optional pudl-menu.js opens the panel against its button, as a full-width sheet on a phone, lets the arrow keys move between rows, and makes a filter at the top of a panel narrow its rows as you type. An open menu is not part of the URL, because it is momentary; everything in it has an address of its own. The Trip and Account buttons in the master–detail toolbar above are menus too.
A launcher is a menu button at the start of the row that holds a window dock, with a panel that reaches everything a site offers, grouped by category, with a filter at the top. The windows demo below has one, and so does the article reader sample.
A menu can also be summoned from the keyboard. A panel carrying data-menu-key="/" opens when / is pressed anywhere outside a text field, with focus in its filter, so the reader can type part of a name and press Enter to go there. On this page, / opens the expenses launcher. If nothing matches and the filter sits in a form, Enter submits the form, so a server can take the typed text to a page of its own, which makes the menu a "go to" palette that still ends in an ordinary address. A panel with no button of its own opens near the top of the window, as a palette.
The menu-bar conventions define the site bar and applet bar. Standard site menus appear in the order Site name, Go, Applets, View, Window, Help, with unused menus omitted. Applets is a direct launcher beside Go. Each group begins with an identity menu; working commands have their own menus. A site may add a pins group between the two, a Pins menu, its title marked by the pin glyph, followed by a button for each pinned item, which give way together to an Items menu when they do not fit. The adoption guide applies these rules to a tools workspace and to a reader application.
Since 0.61.0 every title and row has a letter, declared with data-mnemonic or assigned from its label, underlined while it can be typed: with focus on a title, a letter opens the title that has it, and in a panel a letter runs the row that has it. Press Alt+M to reach this page's bar and try it. An application with no browser around it marks its bar data-menubar-host="desktop", which also gives it Alt alone and F10 to reach the bar, Alt with a title's letter (Ctrl+Option on a Mac) from anywhere, and the browser's Ctrl+N, T and W; a page in a browser leaves those to the browser. A markup row may also be dangerous, carry a glyph, show a detail line, or say why it is disabled, and pudlMenubar.shortcuts() lists every key bound.
The menu bar at the top of this page is a working example. A bar holds at most two menu groups. The host menu belongs to the application and stays in place. The front menu belongs to the applet or article in front and appears to its right. Each menu is one raised group with a menu glyph at its start. Its titles share that raised surface, and the open title looks pressed. A title opens a panel of commands, which can include links, actions, checked or disabled commands, headings, separators and submenus.
Try View to change the theme or open the Components submenu. Choose Window, then Open hotel expense to see a front menu appear for the hotel window. Its Receipt title opens the receipt through the same link used inside the window. Bringing another expense forward removes the hotel's menu, while the host menu stays available. Resize the page to see the bar become one menu button when it runs out of room. In that form, choosing a title or submenu replaces the panel's rows and adds a Back row.
Load pudl-menubar.js after pudl-menu.js, and after pudl-windows.js and pudl-applets.js when those are used. The host supplies a hidden nested list inside nav.menubar[data-menubar]. Each top-level item supplies a title and its commands. Links keep their addresses, and choosing a button command clicks the source button so the application's handler runs. Keep ordinary navigation beside the source list for readers without script; PUDL hides that fallback when it builds the bar.
<nav class="menubar" data-menubar aria-label="My application">
<ul data-menubar-source hidden>
<li>My application
<ul><li><a href="/">Home</a></li></ul>
</li>
<li>Help
<ul><li><a href="/help">User guide</a></li></ul>
</li>
</ul>
<a class="brand" href="/">My application</a>
<a href="/help">User guide</a>
</nav>
An applet supplies its front menu through menus(), returning { titles, into }. Each title has a label and an items list. Commands have a label and run, with optional checked, radio, disabled, danger and shortcut fields, or an items list for a submenu. A string '-' supplies a separator, and { heading } labels a group. PUDL asks for the menu again whenever a panel opens, so its state stays current. An applet that supplies only commands() gets one title containing those commands.
Host titles declare data-menubar-id independently of their displayed labels. The first title is the site identity. A front menu cannot reuse a reserved site ID or host title. Its into entries add commands only to go, view, and help, below the site commands under a heading naming the applet. Exact host labels remain a compatibility fallback. Empty shared slots appear when populated. A Window title with data-menubar-windows generates standard window management. See the 0.40.0 migration guide for the API and generated identity-menu changes. Command labels must be unique within a panel. PUDL omits clashes and reports them in the console. With a menu bar present, applet commands live there; the window menu retains the window's own controls.
An article supplies a hidden nav[data-page-menu] containing the same nested lists, with links for its commands. PUDL adds a first title named after the article, with Open as a page, Copy link to this content and, in a window, Close window. Print joins them, after Copy link, only where the host marks its menu data-page-print, since printing a page of windows prints the desktop rather than the article. The hotel example uses this form for its Receipt title. A heading link scrolls inside the article's window; a link carrying data-win-open opens its target window.
| Tab | Enter the bar at its single tab stop, or leave an open menu. |
|---|---|
| Left / Right | Move between titles across both menus; inside a panel, open or close a submenu or move to the adjacent title. |
| Down / Enter / Space | Open the focused title's panel. |
| Up / Down | Move between commands in a panel. |
| Letter | Move to the next command beginning with that letter. |
| Escape | Close the menu. |
The first title has accesskey="m"; the browser determines its modifier keys. Set data-menubar-key on the bar to change it, or use an empty value to disable it. A command's data-shortcut, or an applet command's shortcut, uses Mod for Ctrl on Windows and Linux or Command on a Mac. This page uses Mod+Shift+L to change the theme. Site-owned shortcuts work anywhere; applet shortcuts, including contributions to the site bar, work only while focus is in their content. Removing or replacing the active source closes its menu. Browser window and tab shortcuts, and the standard select, copy, cut and paste shortcuts, are reserved. See the integration guide for the complete markup and command contract.
Previews in 0.79.0 let a menu bar unfold into a ribbon, give its titles glyphs that it folds to before it collapses, share the topbar's room in order with a command bar beside it, and keep a resident applet's menu in place whatever is in front. The menus that unfold into a ribbon sample puts them together, with its pins in a command bar at the topbar's right and a taskbar at the foot of its windows. Press Show as ribbon at the far right, bring different windows forward, and narrow the page to watch each part give way in turn.
The shared docks sample shows windows in tabs on every edge, a required Workspace window, icon rails at the sides on narrow screens, and a bottom dock that collapses to its strip on short ones. Drag a tab, or press Alt+Shift with an arrow key, to change its place. The shared dock contract describes this opt-in extension, which began in 0.55.0 at the sides and reached the top and bottom in 0.57.0.
Records can open as windows floating above a list, from the optional pudl-windows.css and pudl-windows.js. Open a few of the expenses below, then drag a window by its title bar, resize it from any edge or corner, drag it against the left, right or top edge to snap it, and double-click its title bar to maximise it. The dock above the list has one tab per open window. Everything you do is written into this page's URL, so reloading puts every window back where it was, and Back undoes the last window you opened.
The frame around a window is a band of the raised tint between two hairlines, and the whole band is the resize border. The window's buttons are glyph buttons sized from its title's text, and its menu button shows the window glyph and a caret. A maximised window draws its title bar as a docked one does, short, so the page keeps the room. Right-click a window's tab in the dock to open its window menu there. The active window's title bar takes the accent. With the title bar focused, the arrow keys move the window, Shift with the arrow keys resizes it, and Enter maximises or restores it. Without script, each link opens the record's own page, and the server renders whichever windows the URL names where the URL puts them.
A window can have children, for content that belongs to a record, such as a receipt, a source listing or an image. Open the hotel expense and follow its receipt link. The receipt opens maximised above the expense, a row for it appears under the expense in the list, and Escape or the close button puts it away. A child has no tab in the dock, travels with its parent when the parent is minimised or brought forward, and closes when its parent closes. The list also marks the row of the window in front. The article reader sample puts all of this together as a reading site, with the article list in a sidebar and each article opening maximised.
The sample also shows three things for moving around and for interactive content. A "Next" link at the foot of an article opens the next one in its place, as a link does in a browser tab, and Back returns to the one before. One article holds an applet, a colour mixer, which runs from the same script in the window and in a page of its own, keeping its state in the address only when it owns the page. And scripts can drive the windows through pudlWindows, and hear each window close through the pudl:window-close event, instead of clicking PUDL's buttons.
A link followed from inside a window opens its window in the same state, so following links never overturns the arrangement: from a floating window, the new one floats a step down and to the right. And the sample's category tabs above the list change only the list. The optional pudl-regions.js swaps the parts of the page a navigation changes, marked with data-region, and leaves the windows as they were, scroll positions and running applets included.
Receipt attached; charged to the customer's billing account. View the receipt.
| Created | 2026-10-19 07:00 UTC |
|---|---|
| Amount | PHP 21,600.00 |
| Account | Plan billable |
| Merchant | Makati Garden Hotel |
|---|---|
| Nights | 3, from 2026-10-16 |
| Room | PHP 7,200.00 per night |
| Total | PHP 21,600.00 |
A child window. Press Escape or the close button to return to the expense.
The receipt is due by Friday.
| Amount | PHP 6,800.00 |
|---|---|
| Account | non-billable |
A tree is a hierarchy of places, such as folders, as nested lists of links. Without script it is an indented list; pudl-tree.js makes it one stop in the Tab order, where the arrow keys move, open and close, and typing a name moves to it. Each node with children has a small raised toggle. A path bar says where the reader is inside a hierarchy they are browsing, and only there: a site's sections are its tabs.
A data table whose rows are choices is a grid. The selected row is tinted with an accent edge; with pudl-grid.js the arrow keys move the selection, and Enter or a double-click opens the row by its first link. The glyphs are tokens drawn by .glyph, and a folder's row ringed in the accent is a drop target, as it looks while a file is dragged over it.
| Name | Kind | Size |
|---|---|---|
| coincidences.md | Article | 6 KB |
| drafts | Folder | |
| build.sh | Script | 1 KB |
| feed | Link |
Drop text files here to upload them
Document tabs come and go, one per open file, and look like every other tab. An unsaved document's tab carries a dot, whose word is heard rather than seen, and each tab has a small raised close button; Delete closes the focused tab. The host decides, through pudl:tab-close. A code block is flat, because it is for reading, and an editor's surface is sunken, because it takes input; highlighted code in both takes the theme's --syntax colours. Both show every character as written, with the monospace face's ligatures turned off. A block marked data-code-actions gains a strip naming its language, with raised buttons to copy the code and to download it as a file.
// Keep the window in front across a reload.
function restoreAll(state) {
const top = state.top ?? null;
return { ...state, min: {}, top, note: "restored", count: 2 };
}
A diff shows what changed between two texts, inline as here or side by side, and needs no script. Each changed line shows a plus or minus sign as well as its tint, since the tint alone is too faint to rely on. Changed words are underlined, the gutters are left out when the text is copied, and each hunk has a heading with its range and its actions. The application computes the diff and decides what its actions do.
1 hunk, 1 line added, 1 removed
@@ -2,3 +2,3 @@ Hunk 1 of 1
function restoreAll(state) { const top = state.top || undefined; const top = state.top ?? null; return { ...state, top };A searchable catalog can contain destinations and commands. Categories stay in a list, and the divider resizes with pointer or keyboard input. Try categories on the right or on the left.
A Start catalog can switch between a popup and a pinned sidebar without replacing its content. The standard site menu can use its identity title as the opener. Read the API contract or try the interactive host demos.
Set --split-target-size: 18px for a wider track that occupies its own space. --split-rule-size controls the visible line. Set data-split-pane="first" or "second" to show one pane while keeping both mounted and preserving the split value; remove the attribute to restore both panes. The host owns the URL state and focus transfer. The responsive workspace guide also covers narrow window policies, compact chrome, menu overflow, and menu-group theme tokens.
Two panes inside a component, with a handle between them that resizes the first, drawn as the master-detail divider is. Drag it, or focus it and use the arrow keys, Home and End; Enter or a double-click returns the stylesheet's size. The second pair is stacked.
A row editor edits a list of like things as rows of fields: a table with flat headings, a danger glyph button at each row's end to remove it, and an Add button beneath, led by the plus glyph. When the editor itself is 480px wide or less, each row stacks its fields under their headings as labels; narrow this window to see it. pudl-rows.js keeps focus where a reader expects it after Add and Remove.
| Name | Type | Optional | Remove |
|---|---|---|---|
A zoom group scales a picture larger than its viewport: Zoom Out and Zoom In are glyph buttons with minus and plus, never the characters, the scale is a flat live readout, and Fit fills the viewport's width. Zooming keeps the viewport's middle in place, and while the viewport has focus Ctrl with Plus, Minus and 0 zoom, and Ctrl with the wheel zooms about the pointer. pudl-zoom.js does the scaling and tells the page each new scale.
The flow editor sample puts all of these together in a flow editor's window: steps as disclosure cards with row editors inside, a chart in a zoom viewport docked at the side, and the flow's runs as a row list docked at the foot, each run a link to its address.
A row list is the master-detail list's rows standing on their own, wherever a page lists things to open: the same flat rows, the same current mark, and each row a link to its thing's address, so it can be shared and restored. The rows are one tab stop, and Up, Down, Home and End move among them without going anywhere.
A toolbar is a row of groups of raised controls, as a page editor's formatting toolbar is: glyph buttons, menu buttons and small buttons, each group set apart by a hairline, wrapping with groups whole when the row is narrow. It is one tab stop: Left and Right move along its enabled controls, Home and End to its ends. A control in the state the cursor is in carries aria-pressed and is drawn pressed in, and a menu button whose every row is disabled is disabled with them. pudl-toolbar.js keeps the tab stop and watches the rows. The twelve editing glyphs came with it.
A toolbar marked data-toolbar-fold keeps to one row and folds its groups as the room runs out, instead of wrapping (0.78.0). Each group may carry a name, data-toolbar-group, shown before its controls; a glyph, data-toolbar-glyph; a priority, data-toolbar-priority, higher kept open longer; and data-toolbar-end, which keeps it at the end of the row. A group marked data-toolbar-keep, such as the Find field below, stays on the row as it is and never folds, and the others fold around it. A group passes through five stages: its name and each control's glyph and words; its name and the glyphs alone; one menu button with its glyph and name; that button with its glyph alone; and a section of the More menu. Every group reaches the second stage before any becomes a menu, and the lower priorities fold first. Nothing is lost by folding: a folded group's menu holds each command, a switching one ticked, a segmented control's choices as radio rows, a select as a submenu of its options, a field in a popover and a menu as a submenu. Narrow the box below, with the slider or by its corner. The commands sample builds the same kind of toolbar from an applet's declared commands, with the keys and an agent's view of them.
A ribbon holds a long set of tools as folding toolbars of which one shows at a time, each under a tab. Show as ribbon, beside the tabs, folds the whole ribbon into a menu bar of the same names, each menu holding its tab's groups under their names, and back; the choice is remembered. The tab band and the menu bar are one height, so folding takes away only the row of tools.
A right-click, Shift+F10 or the Menu key opens a context menu where the page offers one, at the pointer or the focused element, with rows as a menu bar's are; Shift with a right-click always gives the browser's own. A split button's main key does the usual thing and its caret key offers the alternatives. A popover is a panel of any content anchored to its control, not a menu and not modal: Escape or a press outside closes it.
The amount is in the currency of the receipt.
Three nights, paid on 22 October.
Both are flat bars, since they are read, and both always have words. A progress bar fills with the accent, and one with no value slides a block and says it is working. A meter's own low, high and optimum say which end is bad, so a low fuel level and a high pollution level are both marked bad, by colour and by the glyph in its words; a meter with marks keeps the accent and marks its thresholds.
Each takes input, so each is sunken, and each joins raised keys to its end where it has any. A number field reads and writes the page's language. A list box carries check boxes, since it sets state, and needs no Ctrl to choose several. A token field gathers its values below the field. A date or time field says back in words what it understood, and its calendar and time list are PUDL's.
A rich list box holds rows the page writes, each with a title, a second line and a badge, under group headings. It takes the same keys and presses as the list box above. Rows hidden by a filter are out of every key and keep their choice.
A list marked data-reorder can be put in order by the reader while its mode is on. Each item that may move gains a flat grip, the handle it is dragged by, and with a grip focused Up and Down move it, Home and End to the ends; each move is announced, and focus stays on the grip. A fixed item keeps its place. A line marks where a dragged item will land. The page saves the order from pudl:reorder.
A figure's frame keeps its picture's proportion before it loads, and a picture that fails shows its words. An avatar is neutral, or tinted by name, and its status mark has a shape as well as a colour. A stepper tells done, current and to come by shape as well as colour, and each done step is a link back.
These hold everywhere PUDL is used, and a page that breaks one is not using PUDL as intended.
aria-current, aria-pressed, aria-checked or aria-selected, so the eye and assistive technology are told the same thing.confirm().--accent reaches links, primary buttons, focus rings, filter chips, the dots on the dock's tabs and the active window.