Skip to content
Coastal Healthcare Advocates

Module: prefs

The Site preferences dialog: theme, text size, animations, reader mode and analytics.

How it fits together

  • Any element with data-open-prefs (the gear buttons in the header and footer, on every page) opens the dialog.
  • The dialog's markup is built here, so every page gets the same one without repeating it in the HTML. It only exists with JavaScript on, which is also the only way to open it.
  • The settings themselves live in theme.js, which applies them before first paint. This file reads and changes them through window.chaPrefs, and listens for cha:prefs so the controls stay in step with the header / footer theme toggles.
  • The Analytics switch goes through window.chaConsent (consent.js). Pages without it simply don't show that row.

Every control applies its change at once — the page behind the dialog is the preview — so there is no Save button.

Why showModal() here

Unlike the contact dialog (modal.js, built around the page-level challenge overlay Google's reCAPTCHA once needed), this one has no such constraint, so the native modal dialog is fine: the browser makes the page inert and handles Escape. Focus goes back to the opening button on close.

Loaded as an ES module.

Source:

Members

(inner, constant) CLOSE_ICON :string

Close icon, inlined because the secondary pages' sprite (src/partials/icons.html) doesn't carry #i-close.

Type:
  • string
Source:

(inner, constant) MOTION_HINT

Hint under Animations when the device already asks for reduced motion.

Source:

(inner) dialog

The dialog, built on first open. @type {HTMLDialogElement|null}

Source:

(inner, constant) osReducedMotion

The device's reduced-motion setting. @type {MediaQueryList}

Source:

(inner) trigger

The button that opened the dialog, refocused on close. @type {HTMLElement|null}

Source:

Methods

(inner) build() → {HTMLDialogElement}

Builds the dialog and wires its controls. Runs once.

Source:
Returns:

The dialog.

Type
HTMLDialogElement

(inner) markup() → {string}

The whole dialog. Built when first opened, by which time consent.js has run and window.chaConsent shows whether to offer the Analytics row.

Source:
Returns:

The dialog's HTML.

Type
string

(inner) open(opener) → {void}

Opens the dialog, building it first if needed.

Parameters:
Name Type Description
opener HTMLElement

The element that was clicked.

Source:
Returns:
Type
void

(inner) segmented(name, legend, cls, options) → {string}

Builds one radio group as a row of segmented buttons.

Parameters:
Name Type Description
name string

The preference name (theme or text).

legend string

The group's visible label.

cls string

Class list for the option row, written out in full at the call site so Tailwind's content scan keeps its rules.

options Array.<Array.<string>>

[value, label] pairs.

Source:
Returns:

The fieldset's HTML.

Type
string

(inner) sync() → {void}

Makes every control match the saved preferences.

Source:
Returns:
Type
void

(inner) toggleRow(name, label, hint) → {string}

Builds one on/off row: a label and hint on the left, a switch on the right.

Parameters:
Name Type Description
name string

The preference name (used in the ids).

label string

The visible label.

hint string

The one-line explanation under it.

Source:
Returns:

The row's HTML.

Type
string