Skip to content

Merge develop into main - #101

Merged
Arthurk12 merged 19 commits into
mainfrom
develop
Oct 7, 2026
Merged

Arthurk12 merged 19 commits into
mainfrom
develop

Conversation

@Arthurk12

Copy link
Copy Markdown
Member

What does this PR do?

⚠️ Breaking
  • BBBCheckbox: ariaLabel is now applied to the <input> element.
  • BBBToggle: exposes the correct accessible name, description and role.

The library is pre-1.0, so these changes bump the minor version (0.8.0 → 0.9.0).

Features
  • BBButton: add type (defaults to "button") and fullWidth props; forward className.
Fixes
  • BBButton: theme colors for the secondary border and neutral hover; disabled border and background fixed.
  • BBBModal: long titles wrap; background follows the BBB dark theme.

Arthurk12 and others added 19 commits September 30, 2026 10:47
chore: sync v0.8.0 from main into develop
BBButton renders its underlying <button> without a type attribute, and
per the HTML spec such a button defaults to type="submit". Any BBButton
placed inside a <form> therefore submits it on click, on top of running
its own onClick handler. With no onSubmit handler this is a GET to the
current URL, i.e. a full page navigation; inside the BBB client that
hits the beforeunload handler and can drop the user out of the meeting.

Set type="button" on the <button> in every layout branch (circle/squared,
stacked and default), matching what other component libraries (MUI,
Chakra, Radix) do: a button inside a form must not submit it unless the
consumer explicitly asks for that.

Closes #82
BBButton always renders type="button", so a consumer that genuinely
wants a submit or reset button has no way to get one: ButtonProps does
not accept a type prop, so passing it is rejected by TypeScript and
would not reach the DOM node anyway.

Expose type?: 'button' | 'submit' | 'reset', defaulting to 'button' so
the safe behavior stays the default and submitting a form remains an
explicit opt-in. The allowed values live in constants.ts (TYPES,
TYPE_VALUES, DEFAULT_TYPE) like the other Button enums, and are
documented in the Storybook argTypes and the component README.
The modal title is a flex item sharing the header row with the close
button, and a flex item does not shrink below its longest word. A title
made of one long unbroken word therefore overflows the header, and the
modal clips both the title and the close button. Since
shouldCloseOnEsc and shouldCloseOnOverlayClick default to false, a
modal rendered with noFooter is left with no way to be closed.

Let the title take the remaining space, shrink below its content width
and break anywhere when needed, so it wraps and the close button stays
inside the modal at any width. Add a gap so the wrapped title never
touches the button.

Closes #83
Add a LongTitle story to exercise the header layout with a title made
of a single long word, which is the case that used to push the close
button out of the modal.
BBBModal and its sticky footer take their background from colorWhite,
which resolves to --color-neutral-white. The BBB client does not know
that variable: its own palette and its dark theme are built on
--color-white, so in dark mode the modal keeps a white background, or
at best gets darkreader's generic inversion, which does not match the
client's native modals.

The background is also set through react-modal's inline `style`, so
consumers can only override it with `!important` on the modal id.

Map colorWhite to --color-white, falling back to
--color-neutral-white, following the same "mapped to core css vars"
pattern used by colorBrand1 and colorError. This makes every library
use of colorWhite follow the client's --color-white, which is what
BBB's own components already do.

Move the modal background out of the inline style into a
styled(ReactModal) class. Passing a className makes react-modal drop
its default content styles, including a 1px #ccc border; that border
is not restated, matching BBB's native BaseModal, which has none.

A dedicated token used only by the modal was considered, but it would
leave the rest of the library out of sync with the client theme.
The border of the secondary (outlined) BBButton stays blue even when
the client overrides --color-primary, while the button's text and
outline already follow it. The border comes from colorBorderSelected,
which falls back straight to the library's base brand color
(--color-brand-1, #0F70D7), skipping --color-primary.

Fall back to colorBrand1 instead, so the chain becomes
--color-border-selected -> --color-primary -> --color-brand-1 ->
#0F70D7. The border-specific variable still wins when set, and
otherwise the border follows the client's primary color.

colorBorderSelected is also used for the focus/selected borders of
BBBSelect, BBBSearch, BBBInput and BBBTextInput, which now follow
--color-primary the same way.
The aria-label prop is passed to the MUI Checkbox root, which forwards
it to the ButtonBase span instead of the <input>, so a BBBCheckbox
without a visible label has no accessible name. dataTest and the
consumer's inputProps reach the <input>, but through inputProps, which
is deprecated in MUI and removed in v7.

Pass aria-label and data-test through slotProps.input so they land on
the <input>, merging any slotProps.input supplied by the consumer
(object or function form).

MUI does not merge inputProps and slotProps.input (a slotProps.input
replaces inputProps entirely), so a consumer's inputProps would be
silently dropped; remove it from CheckboxProps instead, turning that
into a compile error. Keeping a library-owned inputProps and
forwarding it to slotProps.input was discarded to avoid maintaining a
second API for the same purpose.

BREAKING CHANGE: BBBCheckbox no longer accepts inputProps; use
slotProps.input to set attributes on the underlying <input>.
The aria-label/aria-labelledby/aria-describedby props are passed to
the MUI Switch root, which forwards them to the ButtonBase span
instead of the <input>. The input is then named by the <label htmlFor>
that wraps both the title and the helper text, so its accessible name
contains both texts and it has no description. MUI's Switch also
renders a plain checkbox, so screen readers announce "checkbox"
instead of "switch".

Pass the aria attributes and role="switch" through slotProps.input so
they land on the <input>, merging any slotProps.input supplied by the
consumer (object or function form). Since aria-labelledby takes
precedence over the native <label> in the accessible name
computation, the name becomes the title only and the helper text
becomes the description. The <label htmlFor> keeps wrapping both
texts, so clicking the helper text still toggles the switch; moving
the helper text out of the label was discarded because it drops that
behavior.

slotProps.input is used instead of inputProps because inputProps is
deprecated in MUI and removed in v7. MUI does not merge the two (a
slotProps.input replaces inputProps entirely), so a consumer's
inputProps would be silently dropped; remove it from ToggleProps
instead, turning that into a compile error. Merging the legacy prop
was discarded because reading it keeps the deprecated API in use.

When only helperText is given, nothing provides aria-labelledby, so
the <label htmlFor> names the input from the helper text; linking it
as aria-describedby too would announce it twice. Link the helper as
the description only when ariaLabel, ariaLabelledBy or label provides
the name.

Switch only forwards slotProps.input to the <input> since MUI 6.4.9
(earlier 6.x releases ignore it, or lack its types and
SwitchOwnerState), so raise the @mui/material and @mui/icons-material
peer floor to 6.4.9.

BREAKING CHANGE: BBBToggle no longer accepts inputProps; use
slotProps.input to set attributes on the underlying <input>. The
@mui/material and @mui/icons-material peer range is raised to
^6.4.9 || ^7.0.0.
fix(BBBModal): wrap long titles instead of pushing the close button out
fix(BBButton): render type="button" by default  and add type prop
fix(BBBModal, BBButton): follow the BBB client dark theme and border color when colors are overridden
fix(BBBToggle)!: expose correct accessible name, description and role
A disabled BBButton renders 2px narrower and 2px shorter than the same
button enabled. The enabled style reserves a 1px transparent border when
the color has no visible border, but the disabled style sets
`border: none`. The disabled palette has no border color, so every
disabled button drops its border, and toggling `disabled` resizes the
button and moves the layout around it (e.g. the Share button in the BBB
media-sharing modal shifts its anchored modal by 2px).

Fall back to `1px solid transparent` in the disabled branch, matching
the enabled style, so the box is the same in both states.
The disabled style falls back to `background-color: none`, which is not
valid CSS and is dropped by the browser. Use `transparent`, which is
what the fallback means. The branch is unreachable with the current
disabled palette, but it should stay correct if the palette changes.
BBButton sizes itself to its label and gives consumers no way to change
that: it has no width prop and does not forward `className`, so
`styled(BBButton)` has no effect. Consumers that need a button to fill
a footer, popover or dialog row wrap it in a div and reach into it with
a `> *` child selector, which depends on the component's markup and
targets the wrong element in the stacked layout, where the root is a
wrapper div rather than the <button>.

Add a `fullWidth` prop to the default layout that makes the button fill
its container with the content still centered. It switches the button
to `display: flex` so it does not leave the inline-flex baseline gap
below it. The circle, squared and stacked layouts are fixed-size boxes,
so the prop is not offered there.

Forward `className` to the root element of every layout, so one-off
needs such as a minimum width for short labels, margins or letting a
long label wrap work through `styled(BBButton)`. It is documented as an
escape hatch while the component is being adopted: overrides stay
greppable as `styled(BBButton)`, so the recurring ones can later be
turned into native props.

`style` is deliberately not forwarded. Inline overrides add nothing that
`styled()` does not already cover, they are harder to audit, and they
would widen the public API that has to be narrowed again later.
…ound

Buttons with the neutral color take their hover background from
colorBrandAux, which falls back from --color-brand-aux straight to the
library's light brand blue (#E5EFFB). Neither the BBB client nor its
custom styles define --color-brand-aux, so a client that rebrands
through --color-primary and --color-hover-light still gets a blue hover
on every neutral button, in every variant.

Fall back to --color-hover-light before the base light blue, so the
chain becomes --color-brand-aux -> --color-hover-light ->
--color-brand-light -> #E5EFFB. The aux variable still wins when set,
clients that rebrand the hover tint get it on neutral buttons too, and
clients that set neither keep the current #E5EFFB.
fix(BBBCheckbox)!: apply ariaLabel to the input element
fix(BBButton): keep box size when disabled, add fullWidth and className, follow client hover tint
@Arthurk12
Arthurk12 merged commit 30ae81c into main Oct 7, 2026
2 checks passed
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