Color mode

UX

Client-side progressive enhancements for reading. The plugin leaves the built article HTML untouched and adds a reading progress bar, a back-to-top button, table-of-contents scroll-spy, and code copy buttons at runtime.

日本語

Features

  • Reading progress bar — a thin fixed bar (.rb-ux__progress) that follows the scroll position through the article.
  • Back-to-top button — a real button (.rb-ux__back-to-top) with an aria-label that appears after scrolling and smooth-scrolls to the top.
  • TOC scroll-spy — observes a[href^="#"] links inside the article table of contents with IntersectionObserver and marks the active link with .rb-ux__toc-active.
  • Code copy buttons — wraps each pre > code in .rb-ux__code and adds a copy button (.rb-ux__copy) with a transient "copied" state.

Every feature is a no-op when the relevant DOM is absent, and initUx() is idempotent.

Usage

ts
import { defineConfig } from "@riebeckite/core";
import { uxPlugin } from "@riebeckite/plugin-ux";
 
export default defineConfig({
  // ...
  plugins: [
    uxPlugin({
      progress: true,
      backToTop: true,
      tocScrollSpy: true,
      codeCopy: true,
      backToTopLabel: "Back to top",
      copyLabel: "Copy",
      copiedLabel: "Copied",
    }),
  ],
});

The factory is also exported as ux.

Options

Option Type Default Description
progress boolean true Show the reading progress bar
backToTop boolean true Show the back-to-top button
tocScrollSpy boolean true Highlight the active table-of-contents link
codeCopy boolean true Add a copy button to each code block
backToTopLabel string "Back to top" aria-label for the back-to-top button
copyLabel string "Copy" Label of the copy button
copiedLabel string "Copied" Transient label shown after copying

How configuration reaches the client

Client initializers are bundled statically and cannot receive plugin options. At build time the plugin prepends an inert JSON element to each article HTML:

html
<script type="application/json" id="rb-ux-config" data-rb-ux-config>{...}</script>

initUx() reads that element to restore the options; when it is missing, every feature falls back to its enabled default. Injection happens in onPostProcessed (the object getProcessedContent() caches and renders) and is mirrored onto remaining manifest entries in onManifestCreated. The data-rb-ux-config attribute doubles as the marker that keeps the element from being inserted twice per page.

Emitted HTML / CSS hooks

Class Target
rb-ux__progress Progress bar track (role="progressbar")
rb-ux__progress-bar Bar scaled with scaleX
rb-ux__back-to-top Back-to-top button
rb-ux__back-to-top--visible Added while the button is visible
rb-ux__toc-active Active table-of-contents link
rb-ux__code Code block wrapper
rb-ux__copy Copy button
rb-ux__copy--copied Transient copied state

Styles ship as @riebeckite/plugin-ux/style.css and use the theme's --rb-color-* tokens so they do not fight the existing theme.

Accessibility

  • The back-to-top control is a button with an aria-label.
  • The progress bar exposes role="progressbar" with aria-valuemin, aria-valuemax, and aria-valuenow.
  • The active table-of-contents link receives aria-current="true".
  • Under prefers-reduced-motion: reduce, progress and back-to-top transitions are disabled and the back-to-top jump becomes an immediate scroll.
  • Progress bar, buttons, and copy buttons are hidden when printing.

Limitations

  • Client-only: without JavaScript nothing is added.
  • No SPA support; a full page load re-initializes the enhancements.
  • The TOC scroll-spy looks for .rr-table-of-contents, .table-of-contents, or [data-rb-toc] as the table-of-contents container.
  • Copy buttons are skipped inside .rr-code blocks (managed by the code-enhance plugin) to avoid duplicate copy UI.

Exports

  • uxPlugin(options?) / ux(options?) — plugin factory
  • initUx — browser initializer
  • Types: UxOptions, UxResolvedConfig

See also

History

1 changesCollapseExpand
1 + <!-- Generated from packages/plugins/ux/README.md. Do not edit this page directly; edit the package README and run `pnpm docs:sync`. -->
2 +
3 + # UX
4 +
5 + Client-side progressive enhancements for reading. The plugin leaves the built
6 + article HTML untouched and adds a reading progress bar, a back-to-top button,
7 + table-of-contents scroll-spy, and code copy buttons at runtime.
8 +
9 + [日本語](./ux.md)
10 +
11 + ## Features
12 +
13 + - **Reading progress bar** — a thin fixed bar (`.rb-ux__progress`) that follows
14 + the scroll position through the article.
15 + - **Back-to-top button** — a real `button` (`.rb-ux__back-to-top`) with an
16 + `aria-label` that appears after scrolling and smooth-scrolls to the top.
17 + - **TOC scroll-spy** — observes `a[href^="#"]` links inside the article table of
18 + contents with `IntersectionObserver` and marks the active link with
19 + `.rb-ux__toc-active`.
20 + - **Code copy buttons** — wraps each `pre > code` in `.rb-ux__code` and adds a
21 + copy button (`.rb-ux__copy`) with a transient "copied" state.
22 +
23 + Every feature is a no-op when the relevant DOM is absent, and `initUx()` is
24 + idempotent.
25 +
26 + ## Usage
27 +
28 + ```ts
29 + import { defineConfig } from "@riebeckite/core";
30 + import { uxPlugin } from "@riebeckite/plugin-ux";
31 +
32 + export default defineConfig({
33 + // ...
34 + plugins: [
35 + uxPlugin({
36 + progress: true,
37 + backToTop: true,
38 + tocScrollSpy: true,
39 + codeCopy: true,
40 + backToTopLabel: "Back to top",
41 + copyLabel: "Copy",
42 + copiedLabel: "Copied",
43 + }),
44 + ],
45 + });
46 + ```
47 +
48 + The factory is also exported as `ux`.
49 +
50 + ## Options
51 +
52 + | Option | Type | Default | Description |
53 + | --- | --- | --- | --- |
54 + | `progress` | `boolean` | `true` | Show the reading progress bar |
55 + | `backToTop` | `boolean` | `true` | Show the back-to-top button |
56 + | `tocScrollSpy` | `boolean` | `true` | Highlight the active table-of-contents link |
57 + | `codeCopy` | `boolean` | `true` | Add a copy button to each code block |
58 + | `backToTopLabel` | `string` | `"Back to top"` | `aria-label` for the back-to-top button |
59 + | `copyLabel` | `string` | `"Copy"` | Label of the copy button |
60 + | `copiedLabel` | `string` | `"Copied"` | Transient label shown after copying |
61 +
62 + ## How configuration reaches the client
63 +
64 + Client initializers are bundled statically and cannot receive plugin options.
65 + At build time the plugin prepends an inert JSON element to each article HTML:
66 +
67 + ```html
68 + <script type="application/json" id="rb-ux-config" data-rb-ux-config>{...}</script>
69 + ```
70 +
71 + `initUx()` reads that element to restore the options; when it is missing, every
72 + feature falls back to its enabled default. Injection happens in
73 + `onPostProcessed` (the object `getProcessedContent()` caches and renders) and is
74 + mirrored onto remaining manifest entries in `onManifestCreated`. The
75 + `data-rb-ux-config` attribute doubles as the marker that keeps the element from
76 + being inserted twice per page.
77 +
78 + ## Emitted HTML / CSS hooks
79 +
80 + | Class | Target |
81 + | --- | --- |
82 + | `rb-ux__progress` | Progress bar track (`role="progressbar"`) |
83 + | `rb-ux__progress-bar` | Bar scaled with `scaleX` |
84 + | `rb-ux__back-to-top` | Back-to-top button |
85 + | `rb-ux__back-to-top--visible` | Added while the button is visible |
86 + | `rb-ux__toc-active` | Active table-of-contents link |
87 + | `rb-ux__code` | Code block wrapper |
88 + | `rb-ux__copy` | Copy button |
89 + | `rb-ux__copy--copied` | Transient copied state |
90 +
91 + Styles ship as `@riebeckite/plugin-ux/style.css` and use the theme's
92 + `--rb-color-*` tokens so they do not fight the existing theme.
93 +
94 + ## Accessibility
95 +
96 + - The back-to-top control is a `button` with an `aria-label`.
97 + - The progress bar exposes `role="progressbar"` with `aria-valuemin`,
98 + `aria-valuemax`, and `aria-valuenow`.
99 + - The active table-of-contents link receives `aria-current="true"`.
100 + - Under `prefers-reduced-motion: reduce`, progress and back-to-top transitions
101 + are disabled and the back-to-top jump becomes an immediate scroll.
102 + - Progress bar, buttons, and copy buttons are hidden when printing.
103 +
104 + ## Limitations
105 +
106 + - Client-only: without JavaScript nothing is added.
107 + - No SPA support; a full page load re-initializes the enhancements.
108 + - The TOC scroll-spy looks for `.rr-table-of-contents`, `.table-of-contents`,
109 + or `[data-rb-toc]` as the table-of-contents container.
110 + - Copy buttons are skipped inside `.rr-code` blocks (managed by the
111 + code-enhance plugin) to avoid duplicate copy UI.
112 +
113 + ## Exports
114 +
115 + - `uxPlugin(options?)` / `ux(options?)` — plugin factory
116 + - `initUx` — browser initializer
117 + - Types: `UxOptions`, `UxResolvedConfig`
118 +
119 + ## See also
120 +
121 + - [Plugin guide](../reference/plugin-api.en.md)
122 +