Components & interactions
DevSikt's examples demonstrate interaction patterns as well as appearance. They are not backend implementations.
Find component examples
The component overview (components.html) is a directory only. Open a focused reference to use its specimens:
- UI foundations (
components-foundations.html): buttons, identities, statuses, feedback and progress. - Navigation and overlays (
components-navigation.html): tabs, disclosures, dropdown navigation, modal dialogs, drawers and cookie consent. - Operational patterns (
components-operations.html): timelines, checks, logs, integration states and diffs. - Charts and data states (
components-analytics.html): throughput, duration, success rate and model usage, with equivalent tables. - Forms and validation (
components-forms.html): native fields, validation, confirmations, searchable selection and simulated file-input states. - Tables and selection (
components-tables.html): two independent tables with sorting, filtering, pagination, selection, column visibility and CSV export. - AI chat (
components-chat.html): floating, compact project and full-page examples with a shared response controller. - Header mega menu (
components-mega-menu.html): grouped navigation and disclosure behaviour.
Workflow pages also demonstrate tables, confirmations and lists in context. A catalog specimen is not automatically a reusable core API; follow each example's source and instance requirements. The catalog remains in progress.
Copy code examples
The shared theme initializes Copy controls for pre > code blocks, including documentation examples. Copying uses the code's text, never executes it, and announces success or clipboard failure. If browser clipboard access is unavailable or denied, select and copy the text manually.
src/theme/ts/code-copy.ts exports initCodeCopy(root: ParentNode = document) for content inserted after initialization. Repeating initialization does not add duplicate controls. Add data-no-copy to a pre element to opt that block out. Keep untrusted code escaped or assign it using textContent; copy controls do not sanitize HTML or make arbitrary code safe to execute.
Reuse foundations and operational specimens
Foundations uses existing dd-button, dd-primary and dd-status styling. Its opening reference documents the working type scale, semantic colour tokens, spacing/radius rules and icon contract; these are usage specimens, not a second token source. Copy semantic markup from the example disclosures; its src/project/ts/foundations-reference.ts controller uses page-specific IDs and is for one reference page, not a general alert or upload service. Repeated interactive instances need unique IDs and scoped controllers. Static badges and buttons do not require this controller.
The photo-avatar specimen wraps the image in a relatively positioned container and places a small status dot at its bottom-right corner. The dot has a surface-coloured border to separate it from the photo. It is decorative (aria-hidden="true"); adjacent visible text says Online, so presence does not rely on colour. Pair any away/offline colours with equivalent text. This is static markup, not a presence service or new avatar controller.
Operational examples use ordered timeline markup, labelled native details, escaped pre/code output and textual integration states. src/project/ts/operations-reference.ts copies the one log specimen using textContent and reports clipboard failure; that block opts out of shared copy controls with data-no-copy so it has only one copy action. Copying never executes a command. The diff is authored HTML, not a parser or patch application API. Read each section's reuse note before supplying real data; never insert logs or diffs as untrusted HTML.
Loading buttons
src/theme/ts/button-loading.ts exports createButtonLoading(button: HTMLButtonElement). Use a real button with a data-button-label child and an initially hidden data-button-spinner child. Set data-loading-label on the button to override the default Loading… label. Do not apply this to navigation links or disclosure/toggle controls; connect it to an actual asynchronous action.
The returned controller exposes busy, run(task) and reset(). run passes an AbortSignal to the task, disables the button, sets aria-busy, shows its spinner/label and restores the prior presentation on completion. It resolves true on completion or false for duplicate, disabled or cancelled work; real failures are rethrown for the caller to handle. The caller must provide an appropriate live-region result or error message.
reset() aborts the signal and restores the button. Tasks must honour cancellation themselves; resetting UI cannot undo a request or save that already happened. The foundations reference uses a cancellable one-second simulation, not persistence. Reduced-motion styling keeps the state visible without relying on animation.
Reuse navigation and overlays
src/theme/ts/component-navigation.ts initializes each data-navigation-example root and exports initComponentNavigation(root) for roots inserted later. Keep IDs document-unique. Tabs live inside data-tabs, using role="tab", aria-controls, aria-selected, one tab stop and labelled tab panels. This example supports horizontal automatic-activation tabs, not vertical or asynchronously loaded tabs.
Use data-navigation-dropdown on a native details with a summary and ordinary navigation links. Escape, focus leaving the disclosure and outside clicks dismiss it. It is not an ARIA action menu. Dialog triggers use data-dialog-open="dialog-id"; their native dialog must be inside the same root. Native dialog establishes modal background blocking; the controller restores focus to the opener and wraps keyboard focus. Copy the labelled close control and method="dialog" form from the specimen. Drawer presentation changes placement, not modal semantics. See the reference page for full markup and state coverage.
Choose the interaction by consequence, not appearance. Use a disclosure for optional context or navigation that can remain in the page flow, such as chat context/model choices or a short link menu. Use a dialog when the task interrupts the page, requires a decision, changes configuration or must block background interaction. Do not make a disclosure look modal or use a modal for information that users should compare with the page. In either case, support Escape, outside-click dismissal where appropriate, visible focus and predictable focus return.
Use cookie consent
The navigation reference includes a compact banner, native preferences dialog and persistent reopen control. Reusable files are src/theme/ts/consent.ts and src/theme/css/consent.css; the specimen markup is src/project/partials/cookie-consent.html. Read docs/content/cookie-consent.md for initialization, storage, emitted events and the integration boundary.
The example loads no trackers. The UI alone does not block or revoke scripts and is not a compliance certification. Customers must connect it to their own script loader and privacy policy, default optional services off, and obtain appropriate compliance review.
Use the mega menu
Include src/project/partials/mega-menu.html in a header with dd-page-header. Import src/project/ts/mega-menu.ts once. The controller expects one instance per page.
The menu uses ordinary navigation links, current-page state and a labelled close icon. Inside clicks keep it open; outside clicks, Escape and leaving it by keyboard dismiss it.
Use floating chat
Include the floating-chat partial once and import its controller:
{{> floating-chat}}
import "./floating-chat";
The controller lives in src/project/ts/floating-chat.ts. It requires the shared theme and project CSS. The sample uses a native modal dialog: background controls become inert while it is open, Escape dismisses it and focus returns to the launcher. The transparent backdrop preserves the floating appearance without pretending it is non-modal.
Responses are scripted. Closing the panel cancels a pending response. Messages remain in memory while the page is open. No model, network call or storage is involved.
Use full-page chat
chat.html demonstrates conversation history, drafts, context/model labels, a composer and explicit approval UI. Rich sample content is authored markup; arbitrary Markdown is not rendered from chat input.
Use the demo controls to exercise failure and retry. Attachment previews retain names only; they do not read or upload file contents. Real applications need server-side authentication, upload validation, model access and authorization.
Shared chat session
src/theme/ts/chat-session.ts exports createChatSession({ respond, onState, onReply, onError }). The floating, compact project and full-page demos all use it. It is a response-lifecycle primitive, not a complete chat widget, transcript store, Markdown renderer or model client.
respond(text, signal)returns a promise of plain response text. Honour theAbortSignalto stop your own work. Cancellation cannot undo an already-completed server action.onState(state)receivesthinking,idle,stoppedorerror. Successful completion reportsidlebeforeonReply(text); failure reportserrorbefore optionalonError(error).send(text)trims the prompt and returns whether it was accepted. Blank prompts, sends while busy and calls after destruction are rejected.busyexposes whether a response is pending.stop()cancels it;reset()returns to idle;destroy()permanently disposes the session. Late results from cancelled requests are ignored even when the responder ignores cancellation.- Each caller owns its transcript, retry prompt, activity presentation and accessible status region. Full-page and project typing previews are presentation states, not token streaming.
Use one session per independent conversation surface. Render user and response text with textContent, not innerHTML. chatTimestamp(date) supplies ISO dateTime and a readable UTC date/time label for semantic time elements. Theme core has no project branding or scripted replies.
project.html#project-chat includes src/project/partials/project-chat.html and its page-specific controller. It is an inline, local-only Atlas Commerce conversation. Closing a floating chat cancels its pending reply; page navigation cancels pending demo work. None of the three examples calls a model or persists conversations across reloads.
Run recovery previews
run.html includes an optional recovery-state specimen in src/project/ts/run-recovery.ts. It demonstrates retry, cancellation and recovery feedback without changing historical run evidence or executing a command. The failed-run and unavailable-evidence scenarios are independent. These controls do not implement job scheduling, authorization, file retrieval or real retries. Wire your own service only after defining the underlying workflow semantics.
Searchable selection and upload examples
components-forms.html includes src/project/partials/advanced-forms.html and loads src/project/ts/advanced-forms.ts once. Keep their IDs unique. The searchable picker combines a labelled search field with a native select list and explicit apply button; it is not a custom ARIA combobox. Search preserves the applied value until the user applies another choice.
The file specimen inspects only filename and size (one non-empty PDF/TXT/Markdown file, up to 5 MiB). It never reads contents or uploads anything. A timer simulates progress, cancellation, failure and retry; removing the file resets the native input. Filename extensions are only client-side guidance, not trusted content validation. Real applications need server-side authorization, size/type checks, safe storage and scanning appropriate to their threat model.
Reusable table controller
components-tables.html shows two independent, authored-HTML instances. Import createDataTable from src/theme/ts/data-table.ts and pass each table's containing root separately. Repeated initialization of the same root returns its existing instance. Keep element IDs document-unique and author a stable, non-empty, unique row ID for every record; the controller validates row IDs rather than treating a displayed row number as identity. It requires a tbody[data-table-body]. Copy the reference's full root, labelled controls and semantic table markup, not just its rows.
The controller reads data from authored HTML. It scopes listeners, filters, sorting, pagination, selection and column preferences to its root. Text and numeric sorting are stable. Selection is limited to the visible page; changing filters, sorting or pagination clears it. The select-page checkbox reflects partial selection. The root emits a bubbling dd:table-selection event with a copied row-ID array in event.detail.ids. Bulk-action handlers belong to the caller: read getSelectedIds(), confirm the intended action and announce its result. The theme does not perform a server mutation.
Initialize explicitly after the markup exists; importing the module does not initialize tables automatically:
import { createDataTable } from "../../theme/ts/data-table";
const runs = document.querySelector<HTMLElement>("#run-table");
const projects = document.querySelector<HTMLElement>("#project-table");
if (runs) createDataTable(runs);
if (projects) createDataTable(projects);
That import path is relative to a customer entry module in src/project/ts/. Use your own root IDs and follow the complete markup example in the table reference's reuse section.
The returned controller provides:
getSelectedIds(): the selected authored row IDs.clearSelection(): clear the current checkbox selection.reset(): return the instance to its initial presentation.setState("ready" | "loading" | "error" | "denied"): set a local presentation state.destroy(): remove listeners and restore authored row order, visible rows and initial filter/column settings. The root can then be initialized again.
Loading, error and denied previews are not network requests, retries or access control. An empty filtered result is distinct from an unavailable table. Author visible explanations and keep their status announcements with the controls. CSV export includes all filtered rows across pages, including hidden columns, and neutralizes formula-like prefixes. It is a local download, not an upload. Hiding a column is not a privacy boundary: review sensitive fields before offering exports in a real application.
This is a client-side HTML table controller, not a framework data grid. It does not fetch remote rows, provide server-side pagination, virtualize large datasets, or support nested sorting. Do not replace the authored rows behind a live instance; dispose and recreate it when rebuilding its source markup. The reference's two instances demonstrate isolation, not a requirement to show two tables in every workflow.
Export uses data-export-label on column headers and data-export on cells when provided. Otherwise it uses displayed cell text with layout whitespace collapsed. Explicit export values are useful for numeric values without unit suffixes; CSV quoting preserves commas, quotes and intentional newlines in those explicit values.
Work queue controls
The shared workspace partial and src/project/ts/queue-table.ts demonstrate native table selection, bulk assignment confirmation, pagination, optional status/source display and filtered CSV export. The Overview and Work queue pages reuse the same specimen. They have not been migrated to the scoped core table controller above. Selecting an item for the inspector is distinct from checkbox selection for bulk actions.
Selection is limited to the visible page and clears when filters, sorting or pagination change. Export includes all filtered rows across pages and the four fixed columns even when a column is hidden. Assignment only changes local display badges. The controller expects one queue per page; it is not a generic data-grid API.
Board and support workflows
work-board.html uses the existing queue's authored fixture records to present the same items in status columns. Native movement controls provide a keyboard and touch alternative to dragging. Search, counts and reset are part of the page specimen. Status changes stay in the current board session: they do not update the list view, persist after reload or execute work. Keep this limitation visible when using the demo unchanged. The page controller is customer/demo code, not a generic core Kanban API.
help-article.html demonstrates readable application help with section links and troubleshooting. support.html demonstrates a labelled request form with validation, cancellable loading, failure/retry and completion previews. It uses the shared loading-button helper but performs no support submission, file upload or storage of request content. Production use needs your own submission service, privacy handling and server-side validation.
These are application-facing examples. The separate theme documentation remains the source for installation, customization and deployment guidance.
Billing and invoice specimens
billing.html demonstrates local plan/seat changes and billing-contact validation. Its invoice link opens invoice.html, a fixed, printable specimen. Workspace subscription charges are separate from the model-usage estimates in usage.html. No payment method, charge, subscription or financial record is created.
The fixed invoice fixture is DD-2026-0901: five Team seats at USD 12 each, USD 60 total, dated 1 September 2026 for that calendar month. It is explicitly marked as a specimen, not a tax document. Browser print can be used to produce a PDF; print output retains the specimen label.
Chart and system-state examples
Include src/project/partials/analytics-patterns.html once and load src/project/ts/analytics-patterns.ts. components-analytics.html shows the combined reference; the directory links to it without duplicating the specimen. The chart uses fictional data and supplies a semantic table with equivalent values. Loading, empty, unavailable and access-denied previews are local states, not network or authorization checks. Keep chart labels, tabular data and status announcements together when adapting the example.
The standalone chart reference shares the same partial/controller. Success rate is successful completed runs divided by all completed runs: 183/190 = 96.3% over the fixture period. Cancelled and in-progress runs are excluded. Model usage totals 2.48 million input plus output tokens across three fictional models; it does not estimate cost. Rates and shares are rounded, so displayed shares may not sum to exactly 100%. The table changes with the metric. Each page supports one chart specimen, not arbitrary multiple chart instances.
Accessibility checks for adapted examples
Keep visible keyboard focus, input labels, status announcements and sensible heading levels. Test cancellation and focus restoration, not just opening a dialog. Never use colour alone for approval or error state.