pudl

The PUDL contract

This document lists everything a project may rely on in PUDL. From 1.0 on, nothing listed here changes except in a new major version, and anything not listed is internal and may change in any release. The README explains how to use each part; this document says what is promised.

The menu-bar conventions describe command placement and ownership. The 0.40.0 migration guide explains the identifiers, contribution limits, and generated-menu changes supported by the API below.

The responsive workspace contract and adoption guide defines narrow placement, compact chrome, menu overflow, splitter tracks, and mounted single-pane presentation introduced in 0.41.0.

The shared dock contract defines the opt-in tabs, responsive icon rails and required windows introduced in 0.55.0, and the shared top and bottom docks, collapsed strips and tab order added in 0.57.0.

Promises

Files

Everything is in dist/. pudl.css and its fonts/ are the language; everything else is optional, and each optional script works without the others except where noted.

File Needs Provides
pudl.css, fonts/   Tokens and every component’s appearance
pudl-theme.js loaded in <head> before pudl.css The reader’s theme, applied before the first paint
pudl-windows.css, pudl-windows.js pudl.css Floating windows
pudl-menu.js pudl.css Menu placement, arrow keys, filtering, keys that summon menus
pudl-applets.js   The applet runtime; works with or without windows
pudl-regions.js   Swapping regions on navigation
pudl-md.js pudl.css Resizing the master-detail sidebar
pudl-dialog.js   Dialog command buttons for browsers that lack them
pudl-toast.js pudl.css Toasts and dismissing notices
pudl-tabs.js pudl.css Tabs within a page
pudl-tooltip.js pudl.css Tooltips on glyph-only controls
pudl-tree.js pudl.css Trees
pudl-grid.js pudl.css Tables whose rows are choices
pudl-hljs.css pudl.css highlight.js classes coloured from the syntax tokens
pudl-code.js pudl.css Copy and Download on code blocks
pudl-split.js pudl.css Splitters between two panes
pudl-menubar.js pudl.css, pudl-menu.js; uses pudl-windows.js and pudl-applets.js when present An application’s menu bar in its topbar
pudl-components.json   The components, their templates, the grammar of their parts, variants and states, for tools; described here. It agrees with the component table below. Until 1.0 its fields may change in a minor release.

Tokens

A theme may set these, on :root and on [data-theme="dark"], within the rules in the README’s “What a project may change”:

A project may read these in its own styles but does not set them: the type scale --text-2xs to --text-3xl; the spacing grid --space-1 to --space-6; --radius, --radius-sm, --radius-xs, --radius-pill; the surface treatments --input-bg, --input-border, --raise-top, --raise-grad, --raise-grad-hover, --raise-active-bg, --raise-border, --raise-border-hover, --raise-shadow, --raise-active-shadow, --entry-shadow, --recess-bg, --recess-shadow, --shadow-card, --shadow-dialog, --backdrop, --focus-ring and --focus-ring-danger; and the glyphs --glyph-account, --glyph-app, --glyph-arrow-down, --glyph-arrow-up, --glyph-back, --glyph-board, --glyph-bold, --glyph-branch, --glyph-caret, --glyph-check, --glyph-chevron, --glyph-circle, --glyph-clip, --glyph-close, --glyph-code, --glyph-colour, --glyph-comments, --glyph-copy, --glyph-diamond, --glyph-dock, --glyph-document, --glyph-download, --glyph-empty, --glyph-file, --glyph-flag, --glyph-folder, --glyph-gear, --glyph-grip, --glyph-home, --glyph-image, --glyph-inbox, --glyph-info, --glyph-italic, --glyph-link, --glyph-list, --glyph-list-numbered, --glyph-maximize, --glyph-menu, --glyph-minimize, --glyph-minus, --glyph-new-window, --glyph-open, --glyph-panel, --glyph-paragraph, --glyph-pencil, --glyph-pencil-off, --glyph-pin, --glyph-plus, --glyph-quote, --glyph-reload, --glyph-restore, --glyph-ring, --glyph-script, --glyph-search, --glyph-shield, --glyph-slash, --glyph-sort, --glyph-sort-down, --glyph-sort-up, --glyph-square, --glyph-stop, --glyph-strike, --glyph-table, --glyph-terminal, --glyph-theme, --glyph-tick, --glyph-ticket, --glyph-triangle, --glyph-underline, --glyph-undock and --glyph-warning, which are SVG masks to be filled with a colour. Drawing a project’s own control from these tokens keeps it in the grammar.

Every other custom property is internal.

Components

Each row is a component, the markup it expects and the attributes that carry its state. “Aria-current” means any aria-current value but "false".

Component Markup State
Topbar header.topbar holding a.brand, optionally nav.topbar-tabs of a (with --section-current-bg for what lies below), .topbar-chrome with a.topbar-pill (optionally a .glyph and a .topbar-pill-label, shown as the glyph alone on a phone), button.theme-toggle; a menu button may hold its words in .menu-btn-label, cut short on a phone aria-current on the pill or tab for the current page
Status area nav.status-area, last in .topbar-chrome, of .status-item links or buttons, each holding a .glyph or an img, or .glyph.status-picture with --glyph-account for an account with no picture, then optionally a .badge with its status class and words in a span; beside a menu bar it is drawn as the menu bar’s groups a .badge that is empty or hidden is not shown; the item’s aria-label says what the badge means
Section tabs nav.app-section-bar of a.section-tab aria-current on the current tab: "page" for the section’s page, "true" for a page inside it
Buttons .btn, with .btn-primary, .btn-danger, .btn-sm, .disclosure (with aria-expanded, the chevron after its words); .icon-btn, with .danger; .link and .link-muted on a button or link disabled; aria-pressed="true" latches a .btn
Form fields .form-group holding label.form-label, .form-input, span.form-select-wrap holding .form-select (a .form-select alone keeps the browser’s drawing), or .form-textarea, .form-help, .form-error; .form-fieldset with a legend; .form-options, with .inline; label.check; input.form-file required, aria-invalid="true", aria-describedby, readonly, disabled
Switch button.switch[role="switch"] holding .switch-track holding .switch-thumb, then the label aria-checked
Segmented control .seg, with .pill, .sm, of button or a; with data-seg-menu and an aria-label, a pop-up .seg-menu beside it on a phone aria-pressed, aria-checked or aria-current
Badges and chips .badge, with .warn, .danger, .positive, .accent; .chip; .filter-chip holding .filter-chip-kind and .filter-chip-x  
Card .card holding .card-title, .card-subtitle, .card-desc  
Layout .vstack, .hstack (with .align-center, .align-end, .align-baseline; .push-end on a component), .auto-grid (with --grid-min, default 224px; .span-all on a component); .gap-0 to .gap-6 on any of them  
Settings panel .settings-panel holding .cards, each with its controls, a .settings-actions row of buttons and optionally a p.settings-status[role="status"], which takes no room while empty  
Key/value table table.kv-table of th and td rows  
Data table .data-table-wrap holding table.data-table, with .stack; th[aria-sort] holding a or button; .num; .data-table-check; tr.data-table-empty; td[data-label] aria-sort; aria-selected="true" in a grid, or a checked .data-table-check checkbox
Notices .notice, with .positive, .warn, .danger, holding .notice-content with .notice-title, .notice-body, .notice-actions, and button.notice-close hidden once dismissed
Toasts .toast-region holding .toast, with .positive, .warn, .danger, holding p.toast-text and button.toast-close; a .toast, usually hidden, in a window’s content or in regions swapped in moves into the region, shown and announced data-toast-ms, data-toast-sticky
Tabs within a page .tabs holding .tablist[role=tablist] of [role=tab][aria-controls], then [role=tabpanel] panels aria-selected
Empty and loading .empty-state holding .empty-state-title, .empty-state-body, .empty-state-actions; .loading[role=status] holding .spinner  
Pagination nav.pagination holding .pagination-summary, a.page-link (with rel="prev" or rel="next"), .page-gap aria-current "page"; aria-disabled="true"
Dialog dialog.dialog holding .dialog-title, .dialog-body, .dialog-actions; opened by a button with command="show-modal" and commandfor open
Menu .menu holding .menu-btn[popovertarget] and .menu-panel[popover], whose content is .md-section-label, .md-row with .md-item, .menu-sep, button.menu-action (with .danger), label.check.menu-check holding a checkbox, an .md-filter and a .menu-empty data-menu-key, data-menu-empty; data-filter-menu on a panel with an id makes a filter menu: a box belonging to a form sends it on change, and after the region swap that causes the panel opens again with focus on that box
Master-detail .md-layout holding .md-toolbar (with .md-site-tools), .md-chips, .md-body holding .md-sidebar, .md-resize, .md-detail[tabindex="0"]; toolbar parts .md-filter, .md-filter-group, .md-filter-go, .md-toolbar-spacer, .md-toolbar-cmds, .md-toolbar-sep, .md-chips-clear; list parts .md-section-label, .md-row holding a.md-item with any number of .md-meta lines, which wrap, .md-grip; a.md-back in the detail data-md-pane="detail" or "list"; aria-current on a row’s link
Windows .win-host holding .win-layer[data-win-layer][data-win-src]; section.win[data-win] holding header.win-head with .win-title and .win-chrome of .win-btn[data-win-action], then .win-body; nav.win-dock[data-win-dock]; a list row .md-row-child[data-win-child] data-win-mode, hidden for minimised, the four --win- position properties, .active on the window in front; for a zone --zone-x, --zone-y, --zone-w and --zone-h, with --zone-rule-e and --zone-rule-s for its hairlines; for a docked window data-win-edge and --win-dock-size, and on the layer --dock-top, --dock-bottom, --dock-left and --dock-right
Applets an element with data-applet, and optionally data-applet-page, data-applet-fit, data-applet-param data-applet-state; data-applet-fit
Regions any element with data-region aria-busy while replaced
Grid table.data-table[role="grid"] whose rows each hold a link, the first being the row’s address aria-selected on rows
Tree ul.tree of li holding a, then optionally a nested ul of the same aria-expanded on a node’s link when it has children; aria-current on the current node’s
Path bar nav.path (with .mono) holding ol of li, each an a or, last, the current place with aria-current aria-current
Glyph .glyph with --glyph set to a glyph token, and --glyph-size  
Document tabs .tablist.doc-tabs[role="tablist"] of [role="tab"] links or buttons, each holding its name, an optional .doc-tab-dirty with words for assistive technology, and an optional .doc-tab-close[aria-hidden="true"] aria-selected
Code pre.code for a block to read, with tabindex="0" when it may scroll; .code-surface for an editor’s surface; pre[data-code-actions], with data-code-filename, which pudl-code.js wraps in .code-block with a .code-head holding .code-lang and .code-actions  
Visually hidden .visually-hidden, words for assistive technology alone  
Splitter .split (with .stacked) holding .split-pane, .split-handle, .split-pane; the first pane’s size in --split-a on the split, or the property the handle’s data-split-prop names; data-split-min, data-split-max, data-split-valuetext on the handle  
Drop target .drop-zone holding an optional .drop-hint; any element as a target data-drop-over on a zone, data-drop-target on an item, set by the host while something is dragged over it
Numbers and time .num, time, data in prose take tabular figures  

The hidden attribute always hides, on any component, except hidden="until-found".

Attributes that scripts read

Attribute On Read by Meaning
data-theme, data-theme-pref <html> the stylesheet, a settings control The theme in force, and the reader’s preference
data-win-layer, data-win-src the window layer pudl-windows.js The layer, and where window markup comes from ({key}, or # for a template); fetched markup must be text/html from the page’s origin; a numbered key name-2 to name-9 with no template of its own takes name’s, numbered
data-win-default the window layer pudl-windows.js The keys of the windows an address naming no windows opens
data-win-required the window layer pudl-windows.js Keys separated by spaces or commas; always opened, protected against closing, replacement and re-keying, and ordered first in shared docks
data-win-dock-tabs, data-win-dock-rail-width the window layer pudl-windows.js Opt into shared side docks, with automatic icon rails at or below the given width, default 960 CSS pixels
data-win-glyph, data-win-attention, data-win-running, data-win-progress a window pudl-windows.js Glyph token suffix, positive integer attention count, boolean running mark, and percentage from 0 to 100; reflected in side tabs, rails and taskbar
data-win-params the window layer pudl-windows.js, pudl-regions.js Prefixes, space- or comma-separated, of the page’s window-scoped parameters: <prefix>.<key> belongs to window <key>, travels with the windows through region swaps and history, follows the window when it is re-keyed, and is dropped when it closes; p is PUDL’s and is ignored
data-win-pane="off" the window layer pudl-windows.js Leave the master-detail layout’s data-md-pane to the server
data-win, data-win-parent, data-win-mode a window pudl-windows.js Its key, its parent’s key, its starting mode
data-win-href a window pudl-windows.js, pudl-menubar.js The host’s crafted share URL; without it, Copy the link uses the title bar’s page link; an empty or invalid value disables sharing
data-win-open, data-win-replace a link pudl-windows.js Open that key’s window, in place of this one
data-win-menu the window layer pudl-windows.js Give every window a window menu
data-win-size a window pudl-windows.js, pudl-windows.css, pudl-applets.js content for a window sized by its content, or user, the default
data-win-narrow, data-win-narrow-width a window, the layer pudl-windows.js maximized opts a window into restricted presentation at or below the layer width in CSS pixels, default 640; the URL placement is preserved; content-sized windows ignore the option
data-win-chrome a window pudl-windows.js, pudl-windows.css compact retains the title and menu and hides secondary chrome; --win-button-size and --win-glyph-size set independent sizes
data-split-pane a .split pudl-split.js, pudl.css first or second shows one mounted pane and preserves the split value; removal restores split presentation; --split-target-size and --split-rule-size set track and line sizes
data-win-min, data-win-max a window pudl-windows.js Its smallest and largest width and height, w,h in pixels
data-win-action a window button pudl-windows.js menu, page, minimize, maximize, dock or close
data-menubar, data-menubar-source, data-menubar-if, data-menubar-key, data-menubar-text-* the menu bar, its hidden source list, a title, the bar, the bar pudl-menubar.js The menu bar; the host menu as nested lists; windows to show a title only on a page of windows; the jump key, m unless set, none if empty; the bar’s own words (menu, back, page, copy-link, print, close, actions, active-window, minimize-all, restore-all, close-all, open-windows)
data-menubar-id a source-list title pudl-menubar.js Stable site menu ID; standard IDs are site, go, applets, view, window, and help. The first title is always the identity; standard menus are ordered, and duplicate IDs are rejected. Empty slots appear when populated.
data-menubar-windows a title with ID window pudl-menubar.js Append generated active-window layout commands, bulk actions, and the open-window list, using the window module’s capabilities.
data-shortcut a link or button in a menu bar’s list pudl-menubar.js Its command’s shortcut, as Mod+Shift+L
data-page-menu a hidden nav in an article pudl-menubar.js The article’s front menu, as nested lists of links
data-page-print the article’s nav[data-page-menu] pudl-menubar.js Offer Print in the article’s own menu, which a host does once its printed article is worth having
data-menubar-pins a hidden list in the menu bar pudl-menubar.js The pins group, between the host menu and the front menu: its first item the Pins menu of the host’s commands, each later item a pin, a link whose content is its icon and title. The bar redraws when the list changes. Adds pins and items to the bar’s own words.
data-applet-text-commands, -no-commands an applet mount outside a window pudl-applets.js The label of its Commands button, and the text of an empty menu
data-win-dock, data-win-tab, data-win-back, data-win-restore the dock, a dock tab or row, a minimise-all or back link, a restore-all link pudl-windows.js The script keeps the last two’s href current and marks them aria-disabled when they would change nothing
data-win-text-maximize, -restore, -minimized, -head, -dock, -undock, -dock-menu, -dock-top, -dock-bottom, -dock-left, -dock-right, -collapse, -expand, -menu, -page, -minimize, -reset, -reset-position, -close, -snap, -layout-<name>, -zone-<name> the window layer pudl-windows.js The page’s own words, with {title}
data-win-text-copy-link, data-win-text-copy-link-manual the window layer pudl-windows.js The share command label and manual-copy prompt
data-win-edge a docked window the stylesheet, pudl-windows.js The edge it shows on, top, bottom, left or right, which the server renders and the script keeps
data-menu-key, data-menu-empty a menu panel pudl-menu.js Its summoning key, its “nothing matches” text
data-menu-anchor a menu panel with no button pudl-menu.js The id of the element a script opens it from, which it is placed against
data-menu-placement a menu panel pudl-menu.js beside places a submenu beside its anchor, using the same visible viewport bounds and overflow cues
data-md-pane .md-layout the stylesheet, pudl-windows.js Which pane a narrow layout shows
data-md-side .md-layout the stylesheet, pudl-md.js end puts the sidebar at the end edge of the writing direction, mirrored; start, the default, at the start
data-md-peek a persistent .md-layout pudl-md.js, the stylesheet Let the reader peek at the collapsed sidebar by resting the pointer on, or keyboard-focusing, its handle; PUDL marks an open peek with data-md-peek-open and --md-peek-shift, which are its own
data-md-valuetext .md-resize pudl-md.js The divider’s spoken width, with {n}
data-region any element pudl-regions.js A region’s name
data-region-link a link, or an element holding links pudl-regions.js Links outside every region that swap regions as if inside one
data-applet, data-applet-page an applet mount pudl-applets.js The applet’s name, and a page on this origin overriding the registry’s; only pudlApplets.define() names the script and stylesheet
data-applet-fit an applet mount pudl-applets.js, the applet’s stylesheet fill or flow; the runtime sets it when absent
data-applet-param an applet mount outside a window pudl-applets.js, pudl-regions.js The page query parameter that keeps the applet’s state
data-applet-preset a link pudl-applets.js The applet whose running instance the link’s state is handed to
data-toast-ms, data-toast-sticky, data-toast-close-label a toast, the region pudl-toast.js How long, whether to stay, the dismiss label
data-tooltip any element pudl-tooltip.js A tooltip’s text
data-label a data table cell the stylesheet The label shown when rows stack

Events

Each is a CustomEvent. The ones marked “bubbles” can be heard on the document.

Event Fired on Detail When
pudl:theme-change the document preference, theme After the theme changes, in this tab or another
pudl:window-place the window layer key, parent, opener, and placement for a listener to set Before a window opens with no placement in the URL
pudl:window-open the window, bubbles   When a window’s content is in the page
pudl:window-closing the window, and each child closing with it, bubbles, cancelable key, reason: button, key, script or parent Before a reader’s or a script’s close; cancelling it keeps the window
pudl:window-close the window, bubbles key, reason: button, key, script, parent, replace or address Just before a window leaves the page, by any route
pudl:window-rekey the window, bubbles oldKey, key After pudlWindows.rekey() has given the window its new key
pudl:pins-menu the menu bar’s pins list, bubbles none As the Pins menu, or the collapsed bar’s menu, opens, before the list is read, so the host can set its pinning commands for what is in front
pudl:window-menu the window, bubbles key, and add(label, run, { checked, disabled }) As the window menu opens, for content to add its commands
pudl:window-link-copy the window, bubbles key, href, ok After a share URL copy attempt; ok is true only for a successful automatic clipboard write; no event when no URL is usable
pudl:windows-change the window layer, bubbles the whole state: open, top, min, place After every change to the windows
pudl:windows-policy the window layer, bubbles none After responsive presentation changes; the URL state is unchanged
pudl:regions-swap the document url, regions After regions are swapped
pudl:tree-toggle a tree node’s link, bubbles open After a node opens or closes
pudl:split a splitter’s handle, bubbles size in pixels, or null after a reset When a change to the split ends
pudl:code-copy, pudl:code-download the code block’s pre, bubbles ok for a copy, name for a download After each action
pudl:tab-close a document tab, bubbles   When its close button is pressed, or Delete on it; the host closes it or not
pudl:row-select a grid’s row, bubbles   After the selection moves to the row
pudl:row-open a grid’s row, bubbles   When a row with no link is opened, by Enter or a double-click
pudl:md-resize the .md-layout, bubbles width, reset When a sidebar resize ends
pudl:md-peek the .md-layout, bubbles open As a peek at a collapsed sidebar opens and closes
pudl:applet-state the applet’s mount, bubbles name, instance, host, fit, param, and state for a listener to set; a request’s state wins over it Just before init; what state holds then is opts.state
pudl:applet-change the applet’s mount, bubbles state, a string or null When the applet calls opts.changed()

Script functions

Function From Does
pudlSetTheme(p), pudlThemePreference(), pudlToggleTheme() pudl-theme.js Set, read and toggle the reader’s theme
pudlWindows.open(key), .replace(oldKey, key), .raise(key), .minimize(key), .minimizeAll(), .restoreAll(), .dock(key, edge or null), .snap(key, zone or null), .retitle(key, title), .close(key), .state() pudl-windows.js What the matching link or button does, URL and history included
pudlWindows.shareURL(key) pudl-windows.js The window’s absolute HTTP(S) share URL, or null; omitted key means the visible front window; resolves against the document base and preserves the host’s query and fragment
pudlWindows.effectivePlacement(key) pudl-windows.js Detached derived placement after responsive policy, or null for an unknown key; state() retains canonical URL placement
pudlWindows.dockMode(edge, mode) pudl-windows.js Set a shared side dock’s mode: edge is left or right, mode is auto, open or rail; updates the URL and emits pudl:windows-change
pudlWindows.copyLink(key) pudl-windows.js Copies the share URL without changing workspace state; returns a promise of automatic-copy success; offers a manual-copy prompt on clipboard failure and returns false
pudlWindows.rekey(oldKey, key, push) pudl-windows.js Give an open window a new key and keep its element, placement, place in the stack, focus and running content, with its window-scoped parameters; a new history entry unless push is false; returns false, changing nothing, onto a key that is open or loading, and to its own key brings the window forward. Use it where the window stays and only its key changes, such as a reader turning to another story; use replace() where another window takes its place
pudlApplets.define(name, { src, css, page, ver, handles, instances }) pudl-applets.js Name an applet’s files once, for mounts that carry only the name, and the requests it serves: handles: { verb: { param, kinds, extra, reuse } }, with up to instances windows of it, at most 9
pudlApplets.request(verb, { path, kind, … }, from), .can(verb, kind) pudl-applets.js Ask for a request without naming an applet; request returns false when nothing serves it
pudlApplets.menuSourceIn(scope, outside) pudl-applets.js The first running applet in scope offering menus() or commands(), for a menu bar
pudlApplets.commandsIn(scope) pudl-applets.js The commands of the applets running inside scope, as the window menu shows them
pudlApplets.register(name, { init }), .boot(scope), .destroy(scope) pudl-applets.js The applet contract: init(root, opts) returns { destroy } and optionally state(), setState(s), commands(), which returns [{ label, run, checked, disabled }], and menus(), which returns { titles, into } for a menu bar, with opts.host, opts.fit, opts.instance, opts.ownsUrl, opts.pageUrl, opts.state, opts.changed(s)
pudlToast(message, { kind, ms, sticky }) pudl-toast.js Raise a toast
pudlTabs.enhance() pudl-tabs.js Enhance tabs added to the page by other means
pudlTree.enhance(tree) pudl-tree.js Take in nodes added to a tree by other means
pudlGrid.enhance(table) pudl-grid.js Take in rows added to a grid by other means
pudlWindows.menuCommands(key) pudl-windows.js Fresh standard command descriptors for a window, or the visible front window when omitted; missing windows return []. Each has id, label, and run or nested items, with optional checked, disabled, or danger. Callbacks bind to the original element and recheck capabilities; applet commands and extension hooks are excluded. IDs and generated-menu rules are listed in the migration guide.
pudlMenubar.refresh() pudl-menubar.js Rebuild the menu bar after a change the script did not see
pudlMenu.place(panel) pudl-menu.js Place an open panel at once and show it, for a script that moves focus into it in the same moment
pudlMenu.refresh() pudl-menu.js Build the pop-up button for segmented controls with data-seg-menu added by other means
pudlSplit.refresh() pudl-split.js Bring the handles’ values and limits up to date after a change the script did not see
pudlCode.enhance(scope or pre), .names, .extensions, .words pudl-code.js Take in code blocks added by other means; the maps and words a project extends
pudlRegions.refresh() pudl-regions.js Carry the live windows into region links a script has rendered
pudlRegions.reload() pudl-regions.js Fetch the current address again, past any cache, and swap its regions in place with no new history entry; resolves true once swapped, or false if a navigation started meanwhile superseded it; rejects, leaving the regions as they were and never navigating, if the request fails or the page has other regions

Addresses

Windows. The parameters open (keys, comma-separated, in opening order), top (one key, which may name a minimised window after minimise-all, when no window is active), min (keys) and p.<key>=<mode>:<x>,<y>,<w>,<h> describe the windows, alongside the page’s own parameters. A key is letters, digits, - and _. The mode is floating, maximized, left, right, zone, dock-top, dock-bottom, dock-left or dock-right. A docked placement adds a fifth number, its strip’s size as a fraction of the layer, and a zone adds four, its rectangle’s x, y, w and h as fractions of the inner area, which a reader moves to the nearest sixths and reads as left, right or maximized when it is a half or the whole; the four numbers are fractions of the inner area the docks leave, from 0 to 1, with at most three decimal places, and are the floating geometry to restore to. A server renders the windows these name, and ignores what it cannot parse. An address with no open parameter opens the layer’s default windows, if it names any; an address with open, empty or not, opens exactly what it names.

Regions. A soft navigation fetches the same address a bookmark would. It is made by a link inside a region or marked with data-region-link, a collapsed segmented control’s .seg-choice standing for such a link, or a GET form inside a region. It swaps when the answering page is text/html from the page’s own origin, with no redirect to another, and has a region of every name the current page has and the same window layer source; otherwise the browser navigates. A region that is sometimes empty must still be rendered.

Applets. A mount outside a window with data-applet-param="name" has its applet’s state under name in the page’s query, replaced rather than pushed as it changes. Regions carry that parameter from address to address like the windows’ parameters, and a change in it alone fetches nothing. The applet owns the address itself only on its own page: ownsUrl is true when the mount is outside a window, has no data-applet-param, and its page, from data-applet-page or the registry, is this page’s path, ignoring an index file, an .html extension and a trailing slash.

A link with data-applet-preset whose click an instance takes is handled as the link: its state goes to setState(), and a mount that keeps its state in the address gets it there as a new history entry.

Everything else. Sorting, filtering, paging, the record in view and the panel chosen in a set of tabs are addresses: query parameters for the first four, the fragment for the last. What is momentary, such as an open menu or a tooltip, is not.

Internal

These are how PUDL works today and may change in any release: the classes scripts add for their own use (.placing, .sheet, .dragging, .tabs-ready, .leaving, .minimized, .win-rh, .win-ghost, .win-moving, .win-inner, .win-collapsed, .tooltip, .tree-ready, .tree-toggle, .tree-spacer), data-toast-armed, data-edge, the custom properties not listed above (among them --ctl-h, --notice-color, --badge-color, --glyph and --glyph-size), the popover used for tooltips, the order of rules in the stylesheets, and anything a script does that no event, function or attribute above describes.

Names already replaced

These work until 2.0: --pr (now --positive), .badge.pr (.badge.positive), .fc-kind (.filter-chip-kind), .active on section tabs, segments and list rows (the ARIA attributes above), and .dialog-backdrop shown by a project’s script (dialog.dialog).

One name was removed outright before 1.0, for security rather than replaced: data-applet-src and data-applet-css on an applet mount, removed in 0.23.0, whose files pudlApplets.define() now names.

Applet menus() title descriptors accept id. The first title is the identity; file and edit identify standard working menus and order them before domain menus. Reserved site IDs cannot be used by applet working menus. Duplicate working-menu IDs are diagnosed and omitted. Explicit menu definitions remain responsible for semantic command placement.

into keys resolve by stable site ID first and exact displayed label second. Only go, view, and help accept applet contributions, under their owner’s heading. Missing or disallowed destinations are diagnosed and omitted. English standard labels are recognized when an ID is absent. Contributed commands retain applet shortcut scope, including inside submenus. An invalidated active source closes its open menu; stale commands cannot execute against a removed or substituted source.

Legacy commands() results appear under Actions beside a generated identity menu. Generated article menus have no File menu since 0.49.0; their identity menu uses Copy link to this content and Close window, and holds Print, after Copy link, only when the page menu carries data-page-print. Existing translation overrides continue to apply. See the migration guide for all changed defaults and stable window command IDs.

The persistent sidebar contract defines data-md-persistent, sizing and translation attributes, data-md-action commands, pudlMd, and the pudl:md-request and pudl:md-change events introduced in 0.43.0. Its derived attributes and CSS properties belong to PUDL.