organism · stable · extension · since 2026-09
PageSwitcher
Purpose
The pages of an audit, in a dialog: each one to open, with how far it is, the current one said as such, one to delete when there are several, and the tab’s page to add. The dialog stays mounted and opens on the prop, so a close by the app still returns the focus.
When to use, when not
Use it from the panel’s header, where the current page is named. Not in the app, which lists an audit’s pages in a table with their rates.
Anatomy
- The dialog, named “Pages de l’audit”.
- The list: per page a link with its name, its short address, its progress; a delete button when there are several pages.
- The add button with the tab’s path and the plan’s note, or the sentence when the page is already in the audit.
Props
| Name | Type | Default | What it does |
|---|---|---|---|
open? | boolean | undefined | Shown or not; bindable, set back to false when the dialog closes by any means. | |
pages | AuditPage[] | The audit's pages, in order. | |
currentId? | string | undefined | The id of the page shown in the panel. | |
onswitch | (pageId: string) => void | Called with the id of the page chosen. | |
ondelete? | ((pageId: string) => void) | undefined | Deletes a page; the button shows when there are several pages and this is given. | |
addPath? | string | undefined | The path of the tab's page, offered for adding; absent when the tab's page is already in the audit. | |
addNote? | string | undefined | A mention under the add button: what the plan allows. | |
onadd? | (() => void) | undefined | Adds the tab's page. | |
onclose? | (() => void) | undefined | Called after the dialog closed. | |
title? | string | 'Pages de l’audit' | The dialog's heading. |
States
Several pages with the tab’s page to add, and a lone page already in the audit.
pages
Three pages, the second one current; a click switches and the outcome is announced. The tab is on a page that can be added.
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured
single
One page and nothing to add: no delete button, and the sentence in place of the add button.
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured
Accessibility contract
- Role and name: Dialog’s, named by its heading; the links named by the page’s name with the address and the progress in their text;
aria-current="page"on the current one; the delete buttons named “Supprimer” and the page. - Keyboard, focus: the first link takes the initial focus, since the close button is last in the DOM; Tab walks the links and the delete buttons, then the add button; Escape closes and returns the focus.
- Live regions: none of the dialog’s. The panel announces the page shown.
Content rules
French. The address is shown without its scheme and cut at forty characters; the progress reads “38 %” with “avancement” for a reader; the add button reads “Ajouter cette page” with the path under it.
Do and don’t
- Do close the dialog from
onswitch: the caller setsopenback, and the focus returns to the header’s button. - Do give
addPathonly when the tab’s page is not in the audit; the sentence covers the other case. - Do not offer to delete the last page: an audit without a page is not an audit.
Examples
<PageSwitcher bind:open={dialogs.pages} pages={audit.pages} currentId={page.id} onswitch={switchPage} ondelete={deletePage} addPath={here ? undefined : path} onadd={addPage} /> Surfaces
- Extension: the page switcher of the panel’s header.
Related
Dialog, PanelShell, Button, IconButton.
Decisions
- 2026-09-26: a link per page, intercepted on the plain click, rather than a button: the address is the page’s, and the middle click still opens it in a tab.
- 2026-09-26: the bar’s width is a custom property written from the progress, the one dynamic value the component styles; the figure next to it carries the information.
- 2026-09-27: the heading and the sentence take the typographic apostrophe (“Pages de l’audit”), as every French string of the panel does; the straight one was the only one left on its screen.
Criteria held by construction
- 7.1, Chaque script est-il, si nécessaire, compatible avec les technologies d'assistance ?
A native dialog opened with showModal: the focus is held, Escape closes, the page behind is inert, and the focus returns to the button that opened it. - 6.1, Chaque lien est-il explicite ?
Each page is a link to its address whose text is the page's name; a modified click keeps the link's own meaning. - 3.1, Dans chaque page web, l'information ne doit pas être donnée uniquement par la couleur. Cette règle est-elle respectée ?
The current page is said by aria-current and drawn by its line; the progress is a figure with its word, the bar only draws it. - 11.9, Dans chaque formulaire, l'intitulé de chaque bouton est-il pertinent ?
Each delete button is named for its page: three 'Supprimer' buttons are three names.
Tokens it reads
- Colour:
--rl-action,--rl-hover,--rl-ink,--rl-ink-soft,--rl-line,--rl-line-strong,--rl-sunken - Typography:
--rl-font-mono,--rl-weight-bold,--rl-weight-regular,--rl-text-sm,--rl-text-xs - Spacing:
--rl-space-1,--rl-space-1-5,--rl-space-10,--rl-space-2-5,--rl-space-3,--rl-space-half - Layout:
--rl-radius,--rl-border
And one custom property of its own, not tokens: --rl-page-switcher-progress.