Skip to content

feat(BBBToast): add notification card component - #103

Open
Arthurk12 wants to merge 1 commit into
bigbluebutton:developfrom
Arthurk12:issue/72
Open

Arthurk12 wants to merge 1 commit into
bigbluebutton:developfrom
Arthurk12:issue/72

Conversation

@Arthurk12

Copy link
Copy Markdown
Member

What does this PR do?

Add BBBToast, the presentational card for transient notifications: an icon badge matched to variant, a title row it shares with the close button, and a content area below, both aligned to the same edge.

The card never hides itself. The close button and the autoClose timer both call onRequestClose, leaving removal to whoever owns the toast stack, so the card can sit inside an external engine without leaving an empty slot behind. maxHeight caps it and scrolls its body past that point, since those engines clip their own containers with no scrollbar. The card fills the width of the slot it is given, since engines wrap each toast in a flex container that would otherwise shrink it to its content and leave a stack of mismatched widths, and its body keeps room for the close button's focus ring, which the scroll container would otherwise clip.

The autoClose countdown pauses while the card is hovered or has focus inside it, and resumes with the time left, so the toast does not vanish under someone reading it or about to press one of its buttons (WCAG 2.2.1, Timing Adjustable). A bar along the bottom of the card counts the delay down and pauses with it, showing how long the toast has left; hideProgressBar drops it. paused holds both from outside, for engines that pause a whole stack while it is hovered, since the card only sees the pointer over itself.

Every badge carries a white glyph. White fails the 3:1 non-text contrast (WCAG 1.4.11) on the palette's success and warning fills (1.97:1 and 2.32:1), so those badges use new darker shades, colorSuccessDark and colorWarningDark (about 3.6:1), exposed as --color-success-dark and --color-warning-dark so themes can override them. A dark glyph passes too, but it set those two variants apart from the rest.

The card is a live region, which rules out role="button" on it, and it holds buttons of its own, so a clickable container would nest interactive elements and swallow their Enter/Space presses. With onClick, the click is exposed through a real button wrapping message instead: it is announced as a button, reachable with Tab and activated natively, and its focus ring outlines the whole card. clickAriaLabel names it when the message does not describe the action, and clicks on interactive elements passed in message or content stay with those elements. The pointer cursor follows onClick by default, with disablePointer as an override.

The close button takes closeButtonAriaLabel, since a hardcoded English name is what screen readers announce in every locale. The live-region attributes stay overridable through the rest props, for engines whose wrapper is already a live region, while the card's own handlers and test id are applied after them.

Prop names follow the library rather than react-toastify or BBB's notify(): variant as in BBButton and BBBTypography, and hideCloseButton as in BBBHint, so opting out of the close button reads the same across components. DOM-driven handlers (onClick, onActionClick) receive the event, as in BBButton; onRequestClose does not, as in BBBHint, since the timer fires it too. small keeps its name to match the field already in BBB's notify() and in the plugin SDK.

message is optional, for cards whose content reads on its own, and typed as a node rather than a string because four call sites pass a <FormattedMessage> that cannot be flattened without losing inline markup.

example

Closes Issue(s)

Closes #72

Add BBBToast, the presentational card for transient notifications: an
icon badge matched to `variant`, a title row it shares with the close
button, and a content area below, both aligned to the same edge.

The card never hides itself. The close button and the `autoClose` timer
both call `onRequestClose`, leaving removal to whoever owns the toast
stack, so the card can sit inside an external engine without leaving an
empty slot behind. `maxHeight` caps it and scrolls its body past that
point, since those engines clip their own containers with no scrollbar.
The card fills the width of the slot it is given, since engines wrap
each toast in a flex container that would otherwise shrink it to its
content and leave a stack of mismatched widths, and its body keeps room
for the close button's focus ring, which the scroll container would
otherwise clip.

The `autoClose` countdown pauses while the card is hovered or has focus
inside it, and resumes with the time left, so the toast does not vanish
under someone reading it or about to press one of its buttons (WCAG
2.2.1, Timing Adjustable). A bar along the bottom of the card counts the
delay down and pauses with it, showing how long the toast has left;
`hideProgressBar` drops it. `paused` holds both from outside, for
engines that pause a whole stack while it is hovered, since the card
only sees the pointer over itself.

Every badge carries a white glyph. White fails the 3:1 non-text
contrast (WCAG 1.4.11) on the palette's success and warning fills
(1.97:1 and 2.32:1), so those badges use new darker shades,
`colorSuccessDark` and `colorWarningDark` (about 3.6:1), exposed as
`--color-success-dark` and `--color-warning-dark` so themes can
override them. A dark glyph passes too, but it set those two variants
apart from the rest.

The card is a live region, which rules out `role="button"` on it, and
it holds buttons of its own, so a clickable container would nest
interactive elements and swallow their Enter/Space presses. With
`onClick`, the click is exposed through a real button wrapping
`message` instead: it is announced as a button, reachable with Tab and
activated natively, and its focus ring outlines the whole card.
`clickAriaLabel` names it when the message does not describe the
action, and clicks on interactive elements passed in `message` or
`content` stay with those elements. The pointer cursor follows
`onClick` by default, with `disablePointer` as an override.

The close button takes `closeButtonAriaLabel`, since a hardcoded
English name is what screen readers announce in every locale. The
live-region attributes stay overridable through the rest props, for
engines whose wrapper is already a live region, while the card's own
handlers and test id are applied after them.

Prop names follow the library rather than react-toastify or BBB's
notify(): `variant` as in BBButton and BBBTypography, and
`hideCloseButton` as in BBBHint, so opting out of the close button
reads the same across components. DOM-driven handlers (`onClick`,
`onActionClick`) receive the event, as in BBButton; `onRequestClose`
does not, as in BBBHint, since the timer fires it too. `small` keeps
its name to match the field already in BBB's notify() and in the
plugin SDK.

`message` is optional, for cards whose content reads on its own, and
typed as a node rather than a string because four call sites pass a
`<FormattedMessage>` that cannot be flattened without losing inline
markup.

This branch has not been deployed

No deployments
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.

1 participant