Page sections, danger zone, callouts and form controls #618

Closed
opened 2026-10-24 15:00:18 +02:00 by simon · 0 comments
Owner

Motivation

Pages frame their content in five different ways (one with a heavy shadow), ~12 Danger zones are copy-pasted, and some forms have none. Help appears in about nine visual styles, from solid alerts below AA contrast to palette boxes and explanations below tables. Save sits in four different places. Some settings save immediately through checkboxes next to fields that wait for “Save”. DESIGN_GUIDELINES §16 (sections), §17 (help ladder), §18 (form controls), §5.4 (Save placement) and §11 (detail layout) define the target.

Visible improvement

Calm, uniform pages: each section has its title, description and action together; hints are readable and look the same everywhere; it is obvious when a change takes effect.

Scope (ordered steps, just ci-dev green after each)

If /plan finds this too large for one run, split after step 4 into a sequence of two issues.

  1. <.section> (card header pattern: title, description, actions, toolbar, footer) and <.danger_zone>; replace <.form_section> and the private section_box copies.
  2. Detail layout: decide whether <.list> (today a <ul class="list">) is rebuilt as the two-column <dl> layout or a new component replaces the four detail layouts; migrate detail pages and the interim <dl> markup (DESIGN_GUIDELINES §11).
    ENV-managed settings (#540) show their values as readonly inputs styled like disabled (greyed surface, muted value still >= 4.5:1, no placeholder) with a source line below ("Environment variable VAR", "Missing – …"), by human decision instead of §22.1's read-only text: add this as an explicit exception to DESIGN_GUIDELINES §22.1 (values set in the server environment, shown inside an otherwise editable settings form) and keep the #540 component as the one implementation.
    Security fix carried along (open on main, checked 2026-10-19): the member show page's mail links (lib/mv_web/live/member_live/show.ex, the header link href={"mailto:#{MemberHelpers.email_recipient(@member)}"} and mailto_link/1) put the recipient into mailto: without URL encoding. email_recipient/1 quotes RFC 5322 specials only, not ? or &, so a member name such as Max?bcc=x@example.org adds headers (bcc=, subject=) to the mail the viewer composes. The #535 fix covers only the overview's bulk mail and copy. Fix while migrating the detail layout: percent-encode the mailto: address part (as the overview's BCC already does); regression test with ?, &, # and % in first and last name.
  3. Migrate forms to sections and the Save rule: form pages Save only in the header; section forms Save in the section footer; Danger zone last (add it to the role and fee type forms; move it after the footer in the user and data field forms).
    Global settings after #540: each section is its own LiveComponent (lib/mv_web/live/global_settings_live/*_section.ex); wrap each one in <.section> without merging them back. A section can mix ENV-managed (read-only) and editable fields — SMTP in ENV mode keeps the sender fields (MAIL_FROM_*, per field) editable: the footer Save appears only when the section has editable fields; a fully ENV-managed group has no Save.
  4. Width rule per page type (§16.3); remove fixed widths (w-xl) and shadows in page content.
  5. <.callout>, <.collapsible>, help on <.input>; migrate hints by the help ladder:
    • fee settings: explanations into section descriptions and field help, examples into a collapsible;
    • user form: password hint and member-linking hints as callouts / field help;
    • import: instructions into a collapsed “How the import works”, two sections (“Prepare file”, “Upload and check”). Keep this minimal: the dialog-guided import will replace the page;
    • fees tab empty state: no longer an alert.
    • the ENV status callout #540 added to the global settings groups (info when complete, warning when incomplete) becomes a <.callout> kind; remove the interim component so there is one callout;
    • example values move out of placeholders into field help below the field, with example.com hosts (SMTP, Vereinfacht API/app URL; NN/g: placeholders read as real values).
  6. <.input type="toggle"> with a hook that resets checked when the handler pushes the stored value after an error (push_event; a re-render of an unchanged assign sends no diff, DESIGN_GUIDELINES §8.1); global settings checkboxes that save immediately become switches (toast + rollback; the flash #540 adds to "Allow direct registration" becomes this toast). The switch needs the two states #540 already has: set via environment variable (OIDC_ONLY: shown in its state, not toggleable, lock line below) and not switchable until OIDC is fully configured; the “Change password” checkbox becomes a disclosure through <.collapsible> (decide whether it renders <details> or a button with aria-expanded/aria-controls inside forms; DESIGN_GUIDELINES §18.2).
  7. Checkbox size and color fixed by the component (fee settings uses a raw checkbox-primary today).
  8. Labels on touched forms per §5.7 (“Save”, “New ‹entity›”).
  9. Showcase sections: section, danger zone, callout (all kinds), collapsible, input with help, switch.

Out of scope

  • Edit routes and switches in tables for small entities (U9).
  • Content of help texts, documentation links and onboarding.
  • The dialog-guided import itself.

Acceptance criteria

  • DESIGN_GUIDELINES §5.4, §11, §14 (Danger zone), §16, §17, §18.1, §18.2 are met on every migrated page.
  • No solid alert-* for hints, no palette colors, no shadow-* in page content (guard exceptions removed accordingly).
  • Before/after screenshots: fee settings, import, user form, global settings, one detail page; light and dark. Global settings also in ENV mode (one group complete, one incomplete, ASSOCIATION_NAME set), German locale.
  • The ENV callout's warning text reaches 4.5:1 in the dark theme too.
  • Accessibility: help texts linked via aria-describedby; callouts reach 4.5:1 (text) and 3:1 (icon); switches have role="switch" and a toast on change; Danger zone only for authorized users.
  • Showcase sections added.
  • The member show page's mailto: links are percent-encoded; a name containing ?/& adds no header (regression test).
  • just ci-dev green after every step.

Dependencies

  • Consider #255 (consistent Enter behaviour in forms): make it an acceptance point for the migrated forms and close #255 with a reference to this issue.
  • U3 (tokens, button API). #540 (split global settings / fees component) must be merged first: it moves the global settings and fees-tab markup into new components.
  • U9 builds on <.section>, <.danger_zone> and the switch input.

Anchors (verified against main @ d9093a1f, re-check before filing)

  • Fee settings card with shadow: lib/mv_web/live/membership_fee_settings_live.ex:114; raw primary checkbox: :167
  • Import instructions (solid alert, fixed width): lib/mv_web/live/import_live/components.ex:23
  • User form hint boxes: lib/mv_web/live/user_live/form.ex:113,166,174,192,213; “Change password” checkbox: :101
  • Global settings checkboxes saving immediately (after #540): lib/mv_web/live/global_settings_live/join_form_section.ex:48, auth_section.ex:51 (registration), auth_section.ex:92 (OIDC only)
  • Fees tab empty state as alert (after #540): lib/mv_web/live/member_live/show/cycles_component.ex:223
  • Anchors above changed with #540 and its acceptance fixes; re-check after #540 is merged.
  • <.form_section>: lib/mv_web/components/core_components.ex:686

Caution

  • #536 (merged) changed the import/export paths; re-check the import anchors.
  • Switching save timing (checkbox → switch) changes behavior; test toast and rollback on error, including a ui-tagged browser test that the switch shows the stored value again after a failed save.
## Motivation Pages frame their content in five different ways (one with a heavy shadow), ~12 Danger zones are copy-pasted, and some forms have none. Help appears in about nine visual styles, from solid alerts below AA contrast to palette boxes and explanations below tables. Save sits in four different places. Some settings save immediately through checkboxes next to fields that wait for “Save”. DESIGN_GUIDELINES §16 (sections), §17 (help ladder), §18 (form controls), §5.4 (Save placement) and §11 (detail layout) define the target. ## Visible improvement Calm, uniform pages: each section has its title, description and action together; hints are readable and look the same everywhere; it is obvious when a change takes effect. ## Scope (ordered steps, `just ci-dev` green after each) If `/plan` finds this too large for one run, split after step 4 into a sequence of two issues. 1. `<.section>` (card header pattern: title, description, `actions`, `toolbar`, `footer`) and `<.danger_zone>`; replace `<.form_section>` and the private `section_box` copies. 2. Detail layout: decide whether `<.list>` (today a `<ul class="list">`) is rebuilt as the two-column `<dl>` layout or a new component replaces the four detail layouts; migrate detail pages and the interim `<dl>` markup (DESIGN_GUIDELINES §11). ENV-managed settings (#540) show their values as `readonly` inputs styled like disabled (greyed surface, muted value still >= 4.5:1, no placeholder) with a source line below ("Environment variable `VAR`", "Missing – …"), by human decision instead of §22.1's read-only text: add this as an explicit exception to DESIGN_GUIDELINES §22.1 (values set in the server environment, shown inside an otherwise editable settings form) and keep the #540 component as the one implementation. Security fix carried along (open on `main`, checked 2026-10-19): the member show page's mail links (`lib/mv_web/live/member_live/show.ex`, the header link `href={"mailto:#{MemberHelpers.email_recipient(@member)}"}` and `mailto_link/1`) put the recipient into `mailto:` without URL encoding. `email_recipient/1` quotes RFC 5322 specials only, not `?` or `&`, so a member name such as `Max?bcc=x@example.org` adds headers (`bcc=`, `subject=`) to the mail the viewer composes. The #535 fix covers only the overview's bulk mail and copy. Fix while migrating the detail layout: percent-encode the `mailto:` address part (as the overview's BCC already does); regression test with `?`, `&`, `#` and `%` in first and last name. 3. Migrate forms to sections and the Save rule: form pages Save only in the header; section forms Save in the section footer; Danger zone last (add it to the role and fee type forms; move it after the footer in the user and data field forms). Global settings after #540: each section is its own LiveComponent (`lib/mv_web/live/global_settings_live/*_section.ex`); wrap each one in `<.section>` without merging them back. A section can mix ENV-managed (read-only) and editable fields — SMTP in ENV mode keeps the sender fields (`MAIL_FROM_*`, per field) editable: the footer Save appears only when the section has editable fields; a fully ENV-managed group has no Save. 4. Width rule per page type (§16.3); remove fixed widths (`w-xl`) and shadows in page content. 5. `<.callout>`, `<.collapsible>`, `help` on `<.input>`; migrate hints by the help ladder: - fee settings: explanations into section descriptions and field help, examples into a collapsible; - user form: password hint and member-linking hints as callouts / field help; - import: instructions into a collapsed “How the import works”, two sections (“Prepare file”, “Upload and check”). Keep this minimal: the dialog-guided import will replace the page; - fees tab empty state: no longer an alert. - the ENV status callout #540 added to the global settings groups (info when complete, warning when incomplete) becomes a `<.callout>` kind; remove the interim component so there is one callout; - example values move out of placeholders into field help below the field, with `example.com` hosts (SMTP, Vereinfacht API/app URL; NN/g: placeholders read as real values). 6. `<.input type="toggle">` with a hook that resets `checked` when the handler pushes the stored value after an error (`push_event`; a re-render of an unchanged assign sends no diff, DESIGN_GUIDELINES §8.1); global settings checkboxes that save immediately become switches (toast + rollback; the flash #540 adds to "Allow direct registration" becomes this toast). The switch needs the two states #540 already has: set via environment variable (`OIDC_ONLY`: shown in its state, not toggleable, lock line below) and not switchable until OIDC is fully configured; the “Change password” checkbox becomes a disclosure through `<.collapsible>` (decide whether it renders `<details>` or a button with `aria-expanded`/`aria-controls` inside forms; DESIGN_GUIDELINES §18.2). 7. Checkbox size and color fixed by the component (fee settings uses a raw `checkbox-primary` today). 8. Labels on touched forms per §5.7 (“Save”, “New ‹entity›”). 9. Showcase sections: section, danger zone, callout (all kinds), collapsible, input with help, switch. ## Out of scope - Edit routes and switches in tables for small entities (U9). - Content of help texts, documentation links and onboarding. - The dialog-guided import itself. ## Acceptance criteria - DESIGN_GUIDELINES §5.4, §11, §14 (Danger zone), §16, §17, §18.1, §18.2 are met on every migrated page. - No solid `alert-*` for hints, no palette colors, no `shadow-*` in page content (guard exceptions removed accordingly). - Before/after screenshots: fee settings, import, user form, global settings, one detail page; light and dark. Global settings also in ENV mode (one group complete, one incomplete, `ASSOCIATION_NAME` set), German locale. - The ENV callout's warning text reaches 4.5:1 in the dark theme too. - Accessibility: help texts linked via `aria-describedby`; callouts reach 4.5:1 (text) and 3:1 (icon); switches have `role="switch"` and a toast on change; Danger zone only for authorized users. - Showcase sections added. - The member show page's `mailto:` links are percent-encoded; a name containing `?`/`&` adds no header (regression test). - `just ci-dev` green after every step. ## Dependencies - Consider #255 (consistent Enter behaviour in forms): make it an acceptance point for the migrated forms and close #255 with a reference to this issue. - U3 (tokens, button API). #540 (split global settings / fees component) must be merged first: it moves the global settings and fees-tab markup into new components. - U9 builds on `<.section>`, `<.danger_zone>` and the switch input. ## Anchors (verified against `main` @ `d9093a1f`, re-check before filing) - Fee settings card with shadow: `lib/mv_web/live/membership_fee_settings_live.ex:114`; raw primary checkbox: `:167` - Import instructions (solid alert, fixed width): `lib/mv_web/live/import_live/components.ex:23` - User form hint boxes: `lib/mv_web/live/user_live/form.ex:113,166,174,192,213`; “Change password” checkbox: `:101` - Global settings checkboxes saving immediately (after #540): `lib/mv_web/live/global_settings_live/join_form_section.ex:48`, `auth_section.ex:51` (registration), `auth_section.ex:92` (OIDC only) - Fees tab empty state as alert (after #540): `lib/mv_web/live/member_live/show/cycles_component.ex:223` - Anchors above changed with #540 and its acceptance fixes; re-check after #540 is merged. - `<.form_section>`: `lib/mv_web/components/core_components.ex:686` ## Caution - #536 (merged) changed the import/export paths; re-check the import anchors. - Switching save timing (checkbox → switch) changes behavior; test toast and rollback on error, including a `ui`-tagged browser test that the switch shows the stored value again after a failed save.
simon closed this issue 2026-10-26 11:15:08 +01:00
Sign in to join this conversation.
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
local-it/mitgliederverwaltung#618
No description provided.