Skip to content

merging fork back to main - #49

Closed
goodidea-kp wants to merge 102 commits into
thedodd:masterfrom
goodidea-kp:master
Closed

goodidea-kp wants to merge 102 commits into
thedodd:masterfrom
goodidea-kp:master

Conversation

@goodidea-kp

Copy link
Copy Markdown

No description provided.

goodidea-kp and others added 28 commits May 25, 2026 16:31
…lete` component

- Introduce new accessibility attributes (`aria-*`, `role`, `tabindex`) for `Button` and `Delete` components.
- Replace Font Awesome modal close buttons with `Delete` components for consistency.
…`ybc-catalog`, and example projects (#23)

- Upgrade `yew` to 0.23.0 with CSR feature.
- Update `yew-router` to 0.20.0.
- Adjust exports for `router`-dependent features.
- Bump package versions for `ybc` (0.4.5) and `ybc-catalog` (0.1.1).
* Fix ModalCard title/body overflowing the viewport for long content

.modal-card-title has flex-shrink:0 in Bulma with no min-width override,
so a long unbroken string (a hostname, an ARN) in the title forces
modal-card-head wider than the card instead of wrapping; centering then
pushes the whole dialog off-screen on both sides. Add min-width:0 on the
head/title, overflow-wrap on the title, and overflow-x on the body as a
backstop for wide table content, in the same DIALOG_STYLE block that
already patches other Bulma/<dialog> quirks per instance.

* Bump version from 0.4.5 to 0.4.6
* Fix ModalCard title/body overflowing the viewport for long content

.modal-card-title has flex-shrink:0 in Bulma with no min-width override,
so a long unbroken string (a hostname, an ARN) in the title forces
modal-card-head wider than the card instead of wrapping; centering then
pushes the whole dialog off-screen on both sides. Add min-width:0 on the
head/title, overflow-wrap on the title, and overflow-x on the body as a
backstop for wide table content, in the same DIALOG_STYLE block that
already patches other Bulma/<dialog> quirks per instance.

* Bump version from 0.4.5 to 0.4.6
The first fix (#24) only addressed .modal-card-title's flex-shrink:0 by
adding min-width:0 — which doesn't actually override flex-shrink:0 (an
explicit "never shrink" declaration, not the default min-width:auto floor
that min-width:0 fixes). The title kept clipping instead of wrapping.

Three problems fixed here, verified against a standalone repro of the
actual DOM/CSS at both desktop and mobile widths:

1. .modal-card-title needs flex-shrink:1 (not just min-width:0) to actually
   participate in shrinking so overflow-wrap can wrap it.
2. Bulma centers .modal-card/.modal-content via `margin: 0 auto` (desktop)
   or a fixed side margin (mobile), which fights this component's own
   flexbox centering (align-items/justify-content on the dialog) once
   content can't shrink to fit. Reset margin to 0 so flexbox is the only
   positioning mechanism.
3. A CSS-variable-based per-instance width override only takes effect
   inside Bulma's own min-width:769px media query; below that breakpoint
   it's silently ignored. Cap with max-width (not width) using
   calc(100vw - 2rem) so the card can never exceed the viewport at any
   breakpoint.
Bulma `.panel-tabs` is filter navigation, not a WAI-ARIA tablist widget:
it has no roving tabindex / arrow-key contract and no linked tabpanels, and
its children are plain links rather than role="tab". Emitting role="tablist"
therefore trips axe `aria-required-children` (critical) on every consumer.
Render it as a labelled role="navigation" region instead. The real accessible
tablist widget remains available via Tabs/TabItem/TabPanel in tabs.rs.

Bumps to 0.4.7.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Neither component exposed the HTML maxlength attribute, so a consuming
app had no way to cap input length client-side even when the backend
enforces one (e.g. a DB column's varchar length) -- the only feedback
was a server round-trip after the fact. Optional (#[prop_or_default]),
so existing call sites are unaffected.
* - Add `TabsProvider` component and enhance Tabs functionality
  - Introduce `TabsProvider` for managing tab state context and `Tabs`, `TabItem`, `TabPanel` coordination.
  - Update `Tabs` to support both controlled and uncontrolled modes with inheritance from `TabsProvider`.
- Add example for Tabs component and custom tab styling.
  - Enhance `basic` example with a new section demonstrating `TabsProvider` integration.
  - Add `TabsProvider`-backed `Tabs` example and implement custom SCSS for high-contrast styling.
- Add `repro_example` module and update routes.
  - Integrate `ReproRoute` for example routing.
  - Create minimal reproducible case for desync bug using nested `Switch` and `Tabs`.
- Add development script.
  - Introduce `scripts_dev_serve.sh` for running `trunk serve` at port `8124`.

* Bump version to 0.4.9 in Cargo.toml
…ode (#30)

* fix(calendar): guard bulma-calendar destroy() against a removed DOM node

detach_date_picker called bulma-calendar's destroy(), which internally does
document.getElementById(id).remove(). When a Yew component hosting a Calendar
unmounts, Yew removes the DOM node before this cleanup effect runs, so
getElementById returns null and .remove() throws an uncaught TypeError
(observed navigating away from a page with a date picker). The instance is
being discarded regardless, so wrap destroy() in try/catch and swallow a
teardown-time failure. Bump to 0.4.10.

* chore: cargo fmt (pre-existing drift in tabs.rs, blocks CI fmt check)

* chore: drop unused JsCast import in calendar.rs
* change web-sys version

* feat(form): accessible ids, labels, validation state and RadioGroup

Every form control (Select, MultiSelect, Input, TextArea, Checkbox,
Radio, File) gains an optional `id` rendered on the native element.
Field mints an id, points `<label for>` at it and shares it through the
new FieldContext, so a labelled Field + control pair is bound with no
explicit ids. Grouped/addons fields opt out to avoid duplicate ids.

Also:
- Field help renders as `<p class="help">` with an id, and controls emit
  `aria-describedby`; `help_has_error` now marks the control
  `aria-invalid` + `is-danger`.
- `invalid` and `required` props on all controls.
- `autocomplete` and `inputmode` (new InputMode enum) on Input.
- `placeholder` on Select: a disabled, empty-valued first option so
  `required` rejects an untouched select.
- RadioGroup: fieldset + legend wrapper naming a set of radios.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* added chart

* fix(chart): add the PieChart source file missed by "added chart"

The previous commit registered `pub mod chart` in components/mod.rs and
exported PieChart from lib.rs, but the module file itself was left
untracked, so every checkout other than the author's failed with E0583.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…s look, one test hook

Bulma's .input { display: inline-flex } beat the hidden attribute, so the
native fallback stayed on screen beside the picker. Clicks and tests then
reached the wrong control. The fallback is now hidden with display: none
too, and restored on unmount.

The picker's input now keeps its own class, which leaves room for the
icon, and takes only the fallback's modifiers (is-small, is-danger, ...).
data-testid and data-cy move to it while it is mounted, so a test finds
exactly one control.

Regression test with the real bulma-calendar 7.1.1 bundle; it fails on
the previous adapter. Version 0.4.13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bulma-calendar 7.1.1's own Cancel does not close the picker in a real
browser (Chromium, standalone page), though it does under jsdom. A person
who pressed Cancel stayed stuck with the picker open. The adapter now
closes it on Cancel and leaves the value as it was, and the listener is
removed on unmount. Version 0.4.14.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…kills (#34)

A modal body that scrolls now says so: CSS-only scroll shadows (covers in
the body's colour scroll with the content, shadows stay at the edges), a
dark edge in light mode and a light edge in dark mode, nothing on a body
that fits. macOS hides overlay scrollbars, and a long form looked complete
(Bastion BASTION-108).

The .claude/skills directory is now tracked (rust-code-style,
ui-cognitive-simplicity with its new poka-yoke section,
ui-page-modernization); the rest of .claude stays ignored.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…eachable PaginationItem (#35)

* feat(a11y): Callout, CopyButton, ReasonedButton, IconText; keyboard-reachable PaginationItem

Bastion BASTION-101, step 1 of the UI & accessibility epic:
- Callout: a light notification whose severity picks the role (alert for
  danger, status otherwise) and an icon, so colour is never the only signal
  (WCAG 1.4.1, 4.1.3).
- CopyButton: copies, says "Copied" for two seconds through a polite live
  region, and shows a refused clipboard in words instead of panicking.
- ReasonedButton: aria-disabled (stays focusable), a visible reason and
  aria-describedby, instead of disabled + a title nobody on a keyboard sees.
- IconText: Bulma .icon-text with the icon always aria-hidden.
- PaginationItem renders a <button> (an <a> without href is not reachable by
  keyboard) with aria-current="page"; Notification takes a role.
Rendered-HTML tests per component (tests/a11y_primitives.rs, yew ssr as a
dev-dependency only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(a11y): reason shown elsewhere, quiet callouts, callout ids

Found migrating the Bastion console (BASTION-101):
- ReasonedButton.reason_elsewhere points aria-describedby at a reason
  already on the page (one line for a whole toolbar, or a notice beside the
  button) instead of repeating it; the reason line is a <span> so the button
  can sit in a phrasing-only parent.
- Callout.quiet: inside a persistent aria-live region it takes no role of
  its own, so it is not announced twice; Callout.id for aria-describedby.
Two more rendered-HTML tests (10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Bastion BASTION-145: ui-client keeps ten raw Bulma tables because Table
could not carry a table-level data-testid or accessible name.
- New optional props id, testid, aria_label, aria_labelledby and
  aria_describedby, rendered on the <table> itself, also when scrollable
  wraps it in the one div.table-container; omitted when None, so the
  existing call sites render byte-for-byte as before.
- classes and the Bulma modifiers stay on the <table>; the wrapper carries
  only table-container.
- tests/table.rs renders both shapes on the host and checks attribute
  placement, classes, children and the single scroll container.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
…gle (#38)

Bastion BASTION-102, step 2 of the UI & accessibility epic. Bulma 1.x already
follows prefers-color-scheme and honours data-theme on <html>; ybc had no API
for choosing. This adds:
- ybc::theme: Theme { System, Light, Dark } (non_exhaustive); apply() sets or,
  for System, removes data-theme on <html>; store()/stored() keep the choice in
  localStorage under THEME_STORAGE_KEY ("ybc.theme"); use_theme() applies,
  stores and re-renders. Browser calls compile only for wasm32, so SSR and host
  tests never reach a wasm-bindgen import.
- ThemeToggle: a named role="group" of three buttons with visible text, an
  aria-hidden icon and aria-pressed on the current choice.
- Module docs carry the inline <head> script that applies the stored choice
  before the WASM loads.
Rendered-HTML and round-trip tests in tests/theme.rs.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…re, high contrast, dialog focus return (#39)

Everything the Bastion console needs for BASTION-103, 104 and 105 in one
release:

- SortHeader<C>, Pager and ListToolbar, generalised from the console's
  shared listing markup (real buttons, aria-sort, aria-current, polite
  range live region), every button at least 24x24 CSS px (WCAG 2.5.8).
- StatusTag (never colour alone) and an icon on Tag.
- Remote<T, E> and RemoteView; Bulma 1.x skeletons via a skeleton prop on
  Title, Button and Tag plus SkeletonBlock, all aria-busy.
- Disclosure over native <details>.
- Theme::HighContrast: data-theme="light" plus data-contrast="more" for the
  page's own CSS; a fourth ThemeToggle button with visible text.
- Modal dialogs give focus back to their opener on close, also when the
  page removes them while open.
- ReasonedButton takes a style.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…itle

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3510344 (tab arrow keys, ModalCard name) was pushed to master without a
pull request. The same change comes back in feat/a11y-tabs-dialog-name
for review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…itle (#40)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Yew delegates listeners to the app root, so current_target() was the root
and the arrow keys did nothing inside a real app.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The dialog style is embedded in every page that renders a modal, so its
design notes reached each visitor. They are Rust comments between the
rule groups now; the CSS itself is unchanged apart from the comments.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Bulma's .notification.is-light pins its tint at 90% lightness in both
schemes, so each Callout stayed a light block on a dark page (Bastion UX
review S1-F14, BASTION-519). The callout now takes its tint from Bulma's
--bulma-soft-l and its text from --bulma-bold-l, which swap with the
scheme under prefers-color-scheme and data-theme alike. Text and icon
contrast on the tint: info 8.3, success 8.2, warning 7.5, danger 9.4 to 1
in both schemes. Every callout also carries CALLOUT_CLASS (ybc-callout)
for a page's own rules about what sits inside it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#44)

* Give Calendar a keyboard-operable picker beside the typable date field

A date field stays the browser's own <input type="date">, typed into from
the keyboard. A named calendar button beside it opens a picker for the
mouse: a Yew grid of day buttons in a native modal <dialog>, one tab stop
moved by the arrow keys, Home/End and PageUp/PageDown, Enter or a click to
pick. Esc, Close, a click outside or a pick closes it and focus returns to
the field. Inside a ModalCard it sits in the top layer and Esc closes only
the picker. It is drawn with Bulma's scheme variables (light, dark, strong
borders under high contrast) and needs no script, stylesheet or CSP change.

The bulma-calendar adapter and its jsdom test are removed; tests/browser
drives the new picker in Chromium (Bastion BASTION-539).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Size the Calendar's picker button like its input

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Start the Calendar picker's weeks on Sunday

Kostya chose the US week (2026-10-24): the columns run Sunday to Saturday,
Home goes back to Sunday and End forward to Saturday.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Join the Calendar's input and button as Bulma addons and give the days borders

The field is a Bulma field has-addons: the input's control is-expanded, then
the button's, replacing the custom flex wrapper. Day buttons draw Bulma's
border colour, so their edges show in the dark scheme; the selected day
(is-link) and today (link border) stay distinct, and high contrast stays
stronger. The backdrop takes Bulma's modal shade (scheme-invert-l).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@goodidea-kp

Copy link
Copy Markdown
Author

Closing: this was opened against the wrong repository. The work lives in the fork, goodidea-kp/ybc.

@goodidea-kp goodidea-kp closed this Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants