Skip to content

Migrating to 2.0

Nothing breaks in 1.x (DECISIONS D16): every name 2.0 removes still works, marked @deprecated, and React warns once in development. Move to the replacements below at your own pace. This page is the repository's 2.0 removal plan, rendered from the same file.

Everything @kyralabs/* 2.0 removes, its replacement, how to migrate, and the warning 1.x prints today.

  • Why 1.x keeps them: DECISIONS D16 rules out breaking changes in 1.x. A fix to the API adds a new name, and the old one keeps working, marked @deprecated, until 2.0.
  • D4: the deprecated Material 3 components ship through 1.x for migration, get no new features, and are removed in 2.0.
  • React warnings: React warns once per page load, in development only, through packages/m3e-react/src/utils/deprecated.ts.
  • Elements: the elements layer has no dev mode (D7), so its deprecations are @deprecated JSDoc and docs notes only.

When both an old and a new name are set in 1.x, the new one wins.

1. Deprecated components (D4)

Deprecated (1.x) Layers Replacement 1.x dev warning
BottomAppBar / .m3e-bottom-app-bar React, CSS, docked-toolbar-layout legacy branch DockedToolbar / .m3e-docked-toolbar [m3exp-web] <BottomAppBar> is deprecated (DECISIONS D4) and will be removed in 2.0. Use <DockedToolbar>.
SingleChoiceSegmentedButtonRow, MultiChoiceSegmentedButtonRow, SegmentedButton / .m3e-segmented-button-row, .m3e-segmented-button React, CSS ButtonGroup variant="connected" with ButtonGroupItem toggles / .m3e-button-group--connected … <SingleChoiceSegmentedButtonRow> … Use <ButtonGroup variant="connected" selectionMode="single">. and … <MultiChoiceSegmentedButtonRow> … Use <ButtonGroup variant="connected" selectionMode="multiple">. (SegmentedButton itself is silent: its row warns.)
Fab size="small", fabClassName({ size: 'small' }) / .m3e-fab--size-small React, CSS size="baseline" (56dp) [m3exp-web] <Fab size="small"> is deprecated (DECISIONS D4) and will be removed in 2.0. Use <Fab size="baseline">.
NavigationBar / .m3e-navigation-bar React, CSS ShortNavigationBar / .m3e-short-navigation-bar … <NavigationBar> … Use <ShortNavigationBar>.
NavigationRail / .m3e-navigation-rail React, CSS WideNavigationRail / .m3e-wide-navigation-rail … <NavigationRail> … Use <WideNavigationRail>.
ListItem headlineContent=… (BaselineListItemProps) / .m3e-list-item--baseline React, CSS, list-layout legacy branch <ListItem>{headline}</ListItem>, the expressive item … <ListItem headlineContent> … Use <ListItem>{headline}</ListItem>.

The extended FAB’s small size (its default) is not deprecated and stays.

Migration

// BottomAppBar → DockedToolbar. The docked toolbar has no FAB slot (nor does Compose's
// FlexibleBottomAppBar): place the FAB yourself, or use FloatingToolbar's `fab`.
<BottomAppBar actions={actions} floatingActionButton={fab} />
<DockedToolbar>{actions}</DockedToolbar>

// Segmented buttons → connected button group
<SingleChoiceSegmentedButtonRow value={v} onChange={setV}>
  <SegmentedButton value="day">Day</SegmentedButton>
</SingleChoiceSegmentedButtonRow>
<ButtonGroup variant="connected" selectionMode="single" selectedKeys={[v]}
  onSelectionChange={(keys) => setV([...keys][0])}>
  <ButtonGroupItem id="day">Day</ButtonGroupItem>
</ButtonGroup>

// Small FAB → baseline FAB
<Fab size="small" icon="add" aria-label="Add" />
<Fab size="baseline" icon="add" aria-label="Add" />

// NavigationBar / NavigationRail → ShortNavigationBar / WideNavigationRail
<NavigationBar items={items} selectedKey={k} onSelectionChange={setK} />
<ShortNavigationBar items={items} selectedKey={k} onSelectionChange={setK} />
<NavigationRail items={items} selectedKey={k} onSelectionChange={setK} />
<WideNavigationRail items={items} selectedKey={k} onSelectionChange={setK} />

// Baseline list item → expressive list item
<ListItem headlineContent="Inbox" />
<ListItem>Inbox</ListItem>
<!-- CSS / elements: swap the block class; the parts follow the new component's DOM contract
     (COMPONENT_SPEC). -->
<div class="m3e-bottom-app-bar">…</div>          →  <div class="m3e-docked-toolbar">…</div>
<div class="m3e-segmented-button-row">…</div>    →  <m3e-button-group variant="connected" selection-mode="single">…</m3e-button-group>
<button class="m3e-fab m3e-fab--size-small">     →  <button class="m3e-fab">
<nav class="m3e-navigation-bar">…</nav>          →  <nav class="m3e-short-navigation-bar">…</nav>
<nav class="m3e-navigation-rail">…</nav>         →  <nav class="m3e-wide-navigation-rail">…</nav>
<li class="m3e-list-item m3e-list-item--baseline">  →  <li class="m3e-list-item">

The props each replacement takes are on its docs page. For the navigation bar and rail, the migration only changes the component name: items, selectedKey and onSelectionChange carry over.

2. Deprecated names (M11 API review, since 1.8)

React (@kyralabs/m3e-react), each warns once in development

Deprecated Use Warning
FabMenu open isOpen [m3exp-web] <FabMenu open> is deprecated since 1.8 and will be removed in 2.0. Use <FabMenu isOpen>.
FloatingToolbar expanded isExpanded … <FloatingToolbar expanded> … Use <FloatingToolbar isExpanded>.
SearchBar expanded isExpanded … <SearchBar expanded> … Use <SearchBar isExpanded>.
ExtendedFab expanded isExpanded … <ExtendedFab expanded> … Use <ExtendedFab isExpanded>.
DockedToolbar scrollBehavior="exitAlways" "exit-always" … <DockedToolbar scrollBehavior="exitAlways"> … Use <DockedToolbar scrollBehavior="exit-always">.
FloatingToolbar scrollBehavior="exitAlways" "exit-always" … <FloatingToolbar scrollBehavior="exitAlways"> … Use <FloatingToolbar scrollBehavior="exit-always">.
DatePicker headline / DateRangePicker headline (boolean) showHeadline … <DatePicker headline> … Use <DatePicker showHeadline>.

BottomAppBar also accepts 'exit-always', but it goes in 2.0 with the component, so this is not advertised.

<FabMenu open={o} />                        →  <FabMenu isOpen={o} />
<FloatingToolbar expanded={e} />            →  <FloatingToolbar isExpanded={e} />
<DockedToolbar scrollBehavior="exitAlways" />  →  <DockedToolbar scrollBehavior="exit-always" />
<DatePicker headline={false} />             →  <DatePicker showHeadline={false} />

Elements (@kyralabs/m3e-elements): JSDoc and docs only

Element Deprecated Use
<m3e-button-group> event change event selection-change (same detail; it fires first)
<m3e-button-group> attribute selection-required disallow-empty-selection
<m3e-time-picker>, <m3e-time-input>, <m3e-time-scroll> selection-change detail key selection detail key value
<m3e-list> attribute selection selection-mode
<m3e-carousel> event item-click action on the <m3e-carousel-item> (bubbles; same { index })
<m3e-slider> boolean centered variant="centered"
<m3e-slider> boolean vertical orientation="vertical"
<m3e-side-sheet> attribute back (the back event stays) back-button
<m3e-slider centered vertical>              →  <m3e-slider variant="centered" orientation="vertical">
<m3e-list selection="single">               →  <m3e-list selection-mode="single">
<m3e-button-group selection-required>       →  <m3e-button-group disallow-empty-selection>
<m3e-side-sheet back>                       →  <m3e-side-sheet back-button>
group.addEventListener('change', …)         →  group.addEventListener('selection-change', …)
carousel.addEventListener('item-click', …)  →  carousel.addEventListener('action', …)

CSS (@kyralabs/m3e-css)

Setting the private --_m3e-top-app-bar-collapsed-height / --_m3e-top-app-bar-expanded-height by hand is replaced by the public --m3e-comp-top-app-bar-container-collapsed-height / --m3e-comp-top-app-bar-container-expanded-height. The private variables stay internal: React TopAppBar still writes them inline. 2.0 stops documenting them.

Internal helpers on the elements root

71 helper functions and constants re-exported from the @kyralabs/m3e-elements root are tagged @internal (for example sliderInputBounds, textFieldSizesFromCss, listOptionId and rippleStyle). m3e-react imports them from their subpath entries. 2.0 removes them from the root index.ts; the subpath entries keep them. The full list is in the M11 API PR (kyra-labs/m3exp-web#94).

3. What 2.0 deletes

  • React: the components and props in §1 and §2, and their *Props types (already @deprecated). DockedToolbarScrollBehavior and FloatingToolbarScrollBehavior narrow to drop 'exitAlways'. utils/deprecated.ts stays for future deprecations.
  • CSS:
    • Files: bottom-app-bar.css, segmented-button.css, navigation-bar.css, navigation-rail.css, plus their index.css imports.
    • Rules: the .m3e-fab--size-small rules and the .m3e-list-item--baseline rules.
  • Elements:
    • The legacy .m3e-bottom-app-bar branch in docked-toolbar-layout and the legacy item branch in list-layout.
    • The aliases in §2 and their dispatches: button-group change, carousel item-click, the time-picker detail’s selection.
    • The internal root re-exports.
  • Tokens: generated token files used only by the removed components, for example bottom-app-bar*.css, segmented-button-defaults.css, outlined-segmented-button.css and fab-small.css. Each is checked for remaining references first: the navigation bar and rail item tokens are partly shared with the expressive bars and rails.
  • Docs and tests: the docs pages and sections for the removed components, their visual specs and baselines, and their size-limit entries.
  • Changesets: a major changeset for every affected package.

4. Other 2.0 candidates (breaking, not in 1.x)

Each needs its own DECISIONS row before 2.0. They are listed here so the 2.0 batch sees them.

Candidate Today (1.x) Why it waits
Menu, FAB menu and tooltip announce user-initiated open-change before the change, cancelable, as dialog, side sheet and drawer do open-change fires after the state change and is not cancelable Moving it before the change makes a 1.x listener that reads menu.open see the old value. It was implemented in M11 and reverted for this reason.
State events (open-change, expanded-change, selection-change, value-change, navigation-*-change) stop bubbling; item events (action, remove) keep bubbling (M11 plan N5) All bubble and are composed, so nested components cross-talk; 1.x docs guard with e.target === host Changes what listeners on ancestors receive
The umbrella root stops registering every custom element (M11 plan N3, option D) import … from '@kyralabs/m3exp-web' registers all elements Pages that rely on the side-effect registration would lose their elements
Low-severity naming cleanups from the M11 API review: FilterChip / InputChip isExpressive → expressive, Surface variant (boolean) → a string union, positional *ClassName helpers → options objects Inconsistent but working Renames; low value in 1.x