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
@deprecatedJSDoc 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
*Propstypes (already@deprecated).DockedToolbarScrollBehaviorandFloatingToolbarScrollBehaviornarrow to drop'exitAlways'.utils/deprecated.tsstays for future deprecations. - CSS:
- Files:
bottom-app-bar.css,segmented-button.css,navigation-bar.css,navigation-rail.css, plus theirindex.cssimports. - Rules: the
.m3e-fab--size-smallrules and the.m3e-list-item--baselinerules.
- Files:
- Elements:
- The legacy
.m3e-bottom-app-barbranch indocked-toolbar-layoutand the legacy item branch inlist-layout. - The aliases in §2 and their dispatches: button-group
change, carouselitem-click, the time-picker detail’sselection. - The internal root re-exports.
- The legacy
- Tokens: generated token files used only by the removed components, for example
bottom-app-bar*.css,segmented-button-defaults.css,outlined-segmented-button.cssandfab-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
majorchangeset 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 |