Migrate from v5 to v6
There were a lot of breaking changes between v5 and v6 of react-md, but a good
amount can be automated using the codemod. The migrations will be listed on
this page and prefixed with an icon:
- 🎉 - no breaking changes
- ✅ - can be fully migrated
- 🎨 - can be migrated but might need additional styling
- 🔧 - can be migrated but will probably require a few manual changes
- ❌ - must be manually updated
Make sure to have committed or stashed any working changes before running the codemod to make reviewing changes easier and having a fallback if everything goes wrong. If you use a formatter, make sure to run it against all files afterwards to reduce the diffs as well.
Before getting started, remove all the @react-md/* packages and upgrade to
the latest react-md version.
npm uninstall \
react-md \
@react-md/alert \
@react-md/app-bar \
@react-md/autocomplete \
@react-md/avatar \
@react-md/badge \
@react-md/button \
@react-md/card \
@react-md/chip \
@react-md/dialog \
@react-md/divider \
@react-md/elevation \
@react-md/expansion-panel \
@react-md/form \
@react-md/icon \
@react-md/layout \
@react-md/link \
@react-md/list \
@react-md/material-icons \
@react-md/media \
@react-md/menu \
@react-md/overlay \
@react-md/portal \
@react-md/progress \
@react-md/sheet \
@react-md/states \
@react-md/table \
@react-md/tabs \
@react-md/theme \
@react-md/tooltip \
@react-md/transition \
@react-md/tree \
@react-md/typography \
@react-md/utilspnpm remove \
react-md \
@react-md/alert \
@react-md/app-bar \
@react-md/autocomplete \
@react-md/avatar \
@react-md/badge \
@react-md/button \
@react-md/card \
@react-md/chip \
@react-md/dialog \
@react-md/divider \
@react-md/elevation \
@react-md/expansion-panel \
@react-md/form \
@react-md/icon \
@react-md/layout \
@react-md/link \
@react-md/list \
@react-md/material-icons \
@react-md/media \
@react-md/menu \
@react-md/overlay \
@react-md/portal \
@react-md/progress \
@react-md/sheet \
@react-md/states \
@react-md/table \
@react-md/tabs \
@react-md/theme \
@react-md/tooltip \
@react-md/transition \
@react-md/tree \
@react-md/typography \
@react-md/utilsyarn remove \
react-md \
@react-md/alert \
@react-md/app-bar \
@react-md/autocomplete \
@react-md/avatar \
@react-md/badge \
@react-md/button \
@react-md/card \
@react-md/chip \
@react-md/dialog \
@react-md/divider \
@react-md/elevation \
@react-md/expansion-panel \
@react-md/form \
@react-md/icon \
@react-md/layout \
@react-md/link \
@react-md/list \
@react-md/material-icons \
@react-md/media \
@react-md/menu \
@react-md/overlay \
@react-md/portal \
@react-md/progress \
@react-md/sheet \
@react-md/states \
@react-md/table \
@react-md/tabs \
@react-md/theme \
@react-md/tooltip \
@react-md/transition \
@react-md/tree \
@react-md/typography \
@react-md/utilsnpm install react-md @react-md/material-iconspnpm add react-md @react-md/material-iconsyarn add react-md @react-md/material-iconsCodemods
If you just want to try auto-migrating everything through the codemods and
handling the TODOs/manual steps afterwards, you can run the following commands:
npx @react-md/codemod migrate/v5-to-v6
You will be prompted to provide the Javascript parser, which files/folder to run the codemod on, and if everything should be auto-confirmed.
Javascript/Typescript Migration
✅ Update all imports to react-md
This step is required for any other codemods to work. The codemods
only look for the react-md package name.
npx @react-md/codemod v5-to-v6/to-react-md-imports
To make the migration easier, the codemod will begin by converting all scoped
package imports (@react-md/*) into the react-md package import.
+import {
+ AppBar,
+ AppBarNav,
+ ArrowBackSVGIcon,
+ Button,
+ Dialog,
+ DialogContent,
+ MediaContainer,
+} from "react-md";
+
import type { ReactElement } from "react";
import { useState } from "react";
-import { AppBar, AppBarNav } from "@react-md/app-bar";
-import { Button } from "@react-md/button";
-import { Dialog, DialogContent } from "@react-md/dialog";
-import { ArrowBackSVGIcon } from "@react-md/material-icons";
-import { MediaContainer } from "@react-md/media";
import AppBarTitle from "./AppBarTitle";
import styles from "./FullPageExample.module.scss";
🔧 Hardcode any scssVariables usage
npx @react-md/codemod v5-to-v6/hardcode-scss-variables
This codemod converts any @react-md/*/dist/scssVariables into hard coded constants since
it no longer exists.
-import alertVariables from "@react-md/alert/dist/scssVariables";
-import appBarVariables from "@react-md/app-bar/dist/scssVariables";
-import mediaVariables from "@react-md/media/dist/scssVariables";
import shouldNotChange from "another/scssVariables";
-const color = alertVariables["rmd-alert-theme-values"].color;
-const backgroundColor =
- alertVariables["rmd-alert-theme-values"]["background-color"];
+const color = "#fff";
+const backgroundColor = "#323232";
-const margin = alertVariables["rmd-snackbar-margin"];
-const zIndex = alertVariables["rmd-snackbar-z-index"];
+const margin = "1rem";
+const zIndex = 40;
-const titleKeyline = appBarVariables["rmd-app-bar-title-keyline"];
+const titleKeyline = "4.5rem";
-const mediaOverlayPositions = mediaVariables["rmd-media-overlay-positions"];
-const mediaOverlayPosition = mediaVariables["rmd-media-overlay-positions"][2];
-const aspectRatio = mediaVariables["rmd-media-default-aspect-ratios"]['"16-9"'];
+const mediaOverlayPositions = [
+ "top",
+ "right",
+ "bottom",
+ "left",
+ "middle",
+ "center",
+ "absolute-center",
+];
+const mediaOverlayPosition = "bottom";
+const aspectRatio = "16 9";
function Example() {
return (
<div
style={{
- backgroundColor:
- appBarVariables["rmd-app-bar-primary-background-color"],
+ backgroundColor: "var(--rmd-theme-primary, #9c27b0)",
}}
/>
);
✅ Remove deprecated FontIcon props
npx @react-md/codemod v5-to-v6/icon/remove-deprecated-font-icon-props
The forceSize and forceFontSize props were removed from the FontIcon component.
<>
<FontIcon>material_unchanged</FontIcon>
<FontIcon iconClassName="fa fa-star" />
- <FontIcon iconClassName="fa fa-star" className={styles.icon} forceSize />
- <FontIcon iconClassName={styles.fontIcon} forceFontSize />
- <FontIcon
- iconClassName={styles.fontIcon}
- className={styles.icon}
- forceSize
- forceFontSize
- />
+ <FontIcon iconClassName="fa fa-star" className={styles.icon} />
+ <FontIcon iconClassName={styles.fontIcon} />
+ <FontIcon iconClassName={styles.fontIcon} className={styles.icon} />
</>
);
}
✅ Update Material Icons
The @react-md/material-icons package was updated to support all the new icons
and material symbols but only exports SVG icon component versions. Choose one of
the following migrations:
✅ to-svg
npx @react-md/codemod v5-to-v6/material-icons/to-svg
Converts all material icons into the SVG components in v6.0.0.
+import ArrowDropDownIcon from "@react-md/material-icons/ArrowDropDownIcon";
+import ArrowUpwardIcon from "@react-md/material-icons/ArrowUpwardIcon";
+import CheckBoxIcon from "@react-md/material-icons/CheckBoxIcon";
+import CheckIcon from "@react-md/material-icons/CheckIcon";
+import ErrorOutlineIcon from "@react-md/material-icons/ErrorOutlineIcon";
+import FileUploadIcon from "@react-md/material-icons/FileUploadIcon";
+import KeyboardArrowDownIcon from "@react-md/material-icons/KeyboardArrowDownIcon";
+import KeyboardArrowLeftIcon from "@react-md/material-icons/KeyboardArrowLeftIcon";
+import KeyboardArrowRightIcon from "@react-md/material-icons/KeyboardArrowRightIcon";
+import MenuIcon from "@react-md/material-icons/MenuIcon";
+import NotificationsIcon from "@react-md/material-icons/NotificationsIcon";
+import RadioButtonCheckedIcon from "@react-md/material-icons/RadioButtonCheckedIcon";
+import RemoveRedEyeIcon from "@react-md/material-icons/RemoveRedEyeIcon";
import type { ReactElement, ReactNode } from "react";
import { Link, useLocation } from "react-router-dom";
import {
- ArrowDropDownSVGIcon,
- ArrowUpwardSVGIcon,
- CheckBoxSVGIcon,
- CheckSVGIcon,
ConfiguredIcons,
Configuration,
- ErrorOutlineSVGIcon,
- FileUploadSVGIcon,
- KeyboardArrowDownSVGIcon,
- KeyboardArrowLeftSVGIcon,
- KeyboardArrowRightFontIcon,
Layout as RMDLayout,
- MenuSVGIcon,
- NotificationsSVGIcon,
- RadioButtonCheckedSVGIcon,
- RemoveRedEyeSVGIcon as MyTestIcon,
useLayoutNavigation,
} from "react-md";
import navItems from "./navItems";
const icons: ConfiguredIcons = {
- back: <KeyboardArrowLeftSVGIcon />,
- checkbox: <CheckBoxSVGIcon />,
- dropdown: <ArrowDropDownSVGIcon />,
- error: <ErrorOutlineSVGIcon />,
- expander: <KeyboardArrowDownSVGIcon />,
- forward: <KeyboardArrowRightFontIcon />,
- menu: <MenuSVGIcon />,
- notification: <NotificationsSVGIcon />,
- password: <MyTestIcon />,
- radio: <RadioButtonCheckedSVGIcon />,
- selected: <CheckSVGIcon />,
- sort: <ArrowUpwardSVGIcon />,
- upload: <FileUploadSVGIcon></FileUploadSVGIcon>,
+ back: <KeyboardArrowLeftIcon />,
+ checkbox: <CheckBoxIcon />,
+ dropdown: <ArrowDropDownIcon />,
+ error: <ErrorOutlineIcon />,
+ expander: <KeyboardArrowDownIcon />,
+ forward: <KeyboardArrowRightIcon />,
+ menu: <MenuIcon />,
+ notification: <NotificationsIcon />,
+ password: <RemoveRedEyeIcon />,
+ radio: <RadioButtonCheckedIcon />,
+ selected: <CheckIcon />,
+ sort: <ArrowUpwardIcon />,
+ upload: <FileUploadIcon></FileUploadIcon>,
};
✅ to-font
npx @react-md/codemod v5-to-v6/material-icons/to-font
Converts all material icons into the new MaterialIcon component.
@@ -1,39 +1,27 @@
import type { ReactElement, ReactNode } from "react";
import { Link, useLocation } from "react-router-dom";
import {
- ArrowDropDownFontIcon,
- ArrowUpwardFontIcon,
- CheckBoxFontIcon,
- CheckFontIcon,
- ConfiguredIcons,
Configuration,
- ErrorOutlineFontIcon,
- FileUploadFontIcon,
- KeyboardArrowDownFontIcon,
- KeyboardArrowLeftFontIcon,
- KeyboardArrowRightFontIcon,
+ ConfiguredIcons,
Layout as RMDLayout,
- MenuFontIcon,
- NotificationsFontIcon,
- RadioButtonCheckedFontIcon,
- RemoveRedEyeFontIcon as MyTestIcon,
+ MaterialIcon,
useLayoutNavigation,
} from "react-md";
import navItems from "./navItems";
const icons: ConfiguredIcons = {
- back: <KeyboardArrowLeftFontIcon />,
- checkbox: <CheckBoxFontIcon />,
- dropdown: <ArrowDropDownFontIcon />,
- error: <ErrorOutlineFontIcon />,
- expander: <KeyboardArrowDownFontIcon />,
- forward: <KeyboardArrowRightFontIcon />,
- menu: <MenuFontIcon />,
- notification: <NotificationsFontIcon />,
- password: <MyTestIcon />,
- radio: <RadioButtonCheckedFontIcon />,
- selected: <CheckFontIcon />,
- sort: <ArrowUpwardFontIcon />,
- upload: <FileUploadFontIcon></FileUploadFontIcon>,
+ back: <MaterialIcon name="keyboard_arrow_left" />,
+ checkbox: <MaterialIcon name="check_box" />,
+ dropdown: <MaterialIcon name="arrow_drop_down" />,
+ error: <MaterialIcon name="error_outline" />,
+ expander: <MaterialIcon name="keyboard_arrow_down" />,
+ forward: <MaterialIcon name="keyboard_arrow_right" />,
+ menu: <MaterialIcon name="menu" />,
+ notification: <MaterialIcon name="notifications" />,
+ password: <MaterialIcon name="remove_red_eye" />,
+ radio: <MaterialIcon name="radio_button_checked" />,
+ selected: <MaterialIcon name="check" />,
+ sort: <MaterialIcon name="arrow_upward" />,
+ upload: <MaterialIcon name="file_upload" />,
};
✅ to-symbol
npx @react-md/codemod v5-to-v6/material-icons/to-symbol
Converts all material icons into the new MaterialSymbol component.
import type { ReactElement, ReactNode } from "react";
import { Link, useLocation } from "react-router-dom";
import {
- ArrowDropDownFontIcon,
- ArrowUpwardFontIcon,
- CheckBoxFontIcon,
- CheckFontIcon,
- ConfiguredIcons,
Configuration,
- ErrorOutlineFontIcon,
- FileUploadFontIcon,
- KeyboardArrowDownFontIcon,
- KeyboardArrowLeftFontIcon,
- KeyboardArrowRightFontIcon,
+ ConfiguredIcons,
Layout as RMDLayout,
- MenuFontIcon,
- NotificationsFontIcon,
- RadioButtonCheckedFontIcon,
- RemoveRedEyeFontIcon as MyTestIcon,
+ MaterialSymbol,
useLayoutNavigation,
} from "react-md";
import navItems from "./navItems";
const icons: ConfiguredIcons = {
- back: <KeyboardArrowLeftFontIcon />,
- checkbox: <CheckBoxFontIcon />,
- dropdown: <ArrowDropDownFontIcon />,
- error: <ErrorOutlineFontIcon />,
- expander: <KeyboardArrowDownFontIcon />,
- forward: <KeyboardArrowRightFontIcon />,
- menu: <MenuFontIcon />,
- notification: <NotificationsFontIcon />,
- password: <MyTestIcon />,
- radio: <RadioButtonCheckedFontIcon />,
- selected: <CheckFontIcon />,
- sort: <ArrowUpwardFontIcon />,
- upload: <FileUploadFontIcon></FileUploadFontIcon>,
+ back: <MaterialSymbol name="keyboard_arrow_left" />,
+ checkbox: <MaterialSymbol name="check_box" />,
+ dropdown: <MaterialSymbol name="arrow_drop_down" />,
+ error: <MaterialSymbol name="error_outline" />,
+ expander: <MaterialSymbol name="keyboard_arrow_down" />,
+ forward: <MaterialSymbol name="keyboard_arrow_right" />,
+ menu: <MaterialSymbol name="menu" />,
+ notification: <MaterialSymbol name="notifications" />,
+ password: <MaterialSymbol name="remove_red_eye" />,
+ radio: <MaterialSymbol name="radio_button_checked" />,
+ selected: <MaterialSymbol name="check" />,
+ sort: <MaterialSymbol name="arrow_upward" />,
+ upload: <MaterialSymbol name="file_upload" />,
};
Update the scoped packages
Alert ❌
There are a lot of breaking changes for the alert components and API. There are some auto-migrations available, but it is recommended to change a few things manually to adapt to the new API. The best way to understand the changes is to check out the new Snackbar Examples, but here's a summary of the changes:
- Add a
Snackbarnear the root of the app and display toasts with theaddToastexport - The
MessageQueueis no longer required and replaced by an optionalToastManagerProvider - The
useAddMessagehook is no longer required and replaced byuseAddToast- Use the
addToastexport instead for most cases
- Use the
- The
messageIdhas been renamed totoastId - The
messagePriorityhas been renamed topriority - The toast duplicates behavior renamed
"prevent"to"update" - The
disableAutohidemessage option has been removed in favor of just settingvisibleTimetonull - The
twoLinesoption is no longer required since a resize observer automatically determines multiple lines of text. If the number of lines are always known, themultilineprop can be set to a boolean instead. - The
useMessageQueueActionshas been removed in favor ofuseToastManager/useCurrentToastActions
Here's an example diff for converting the "Simple Message Queue" demo in v5 to the v6 implementation:
+import { Snackbar } from "@react-md/core/snackbar/Snackbar";
+import { addToast, type CreateToastOptions } from "@react-md/core/snackbar/ToastManager";
import type { ReactElement } from "react";
-import type { ToastMessage } from "@react-md/alert";
-import { MessageQueue, useAddMessage } from "@react-md/alert";
import { Button } from "@react-md/button";
import { Form, Radio, useChoice } from "@react-md/form";
const SINGLE_LINE = "SINGLE_LINE";
const SINGLE_LINE_ACTION = "SINGLE_LINE_ACTION";
const TWO_LINES = "TWO_LINES";
const TWO_LINES_ACTION = "TWO_LINES_ACTION";
const TWO_LINES_STACKED = "TWO_LINES_STACKED";
type MessageKeys =
| typeof SINGLE_LINE
| typeof SINGLE_LINE_ACTION
| typeof TWO_LINES
| typeof TWO_LINES_ACTION
| typeof TWO_LINES_STACKED;
-type MessageRecord = Record<MessageKeys, ToastMessage>;
+type MessageRecord = Record<MessageKeys, CreateToastOptions>;
const messages: MessageRecord = {
[SINGLE_LINE]: {
children: "This is an example message",
},
[SINGLE_LINE_ACTION]: {
action: "Action",
children: "This is an example message",
},
[TWO_LINES]: {
- twoLines: true,
+ // this is optional
+ multiline: true,
children: (
<>
<p>This is an example message</p>
<p>With a second line of text.</p>
</>
),
},
[TWO_LINES_ACTION]: {
action: "Action",
- twoLines: true,
+ // this is optional
+ multiline: true,
children: (
<>
<p>This is an example message</p>
<p>With a second line of text.</p>
</>
),
},
[TWO_LINES_STACKED]: {
action: "Action",
stacked: true,
- twoLines: true,
+ // this is optional
+ multiline: true,
children: (
<>
<p>This is an example message</p>
<p>With a second line of text.</p>
</>
),
},
};
function SimpleMessageQueue(): ReactElement {
- const addMessage = useAddMessage();
const [key, handleKeyChange] = useChoice<MessageKeys>(SINGLE_LINE);
return (
- <Form onSubmit={() => addMessage(messages[key])}>
+ <Form onSubmit={() => addToast(messages[key])}>
<Radio
id="mqr-1"
name="message"
value={SINGLE_LINE}
checked={key === SINGLE_LINE}
onChange={handleKeyChange}
label="Single Line Message"
/>
<Radio
id="mqr-2"
name="message"
value={SINGLE_LINE_ACTION}
checked={key === SINGLE_LINE_ACTION}
onChange={handleKeyChange}
label="Single Line Message with Action"
/>
<Radio
id="mqr-3"
name="message"
value={TWO_LINES}
checked={key === TWO_LINES}
onChange={handleKeyChange}
label="Two Line Message"
/>
<Radio
id="mqr-4"
name="message"
value={TWO_LINES_ACTION}
checked={key === TWO_LINES_ACTION}
onChange={handleKeyChange}
label="Two Line Message with Action"
/>
<Radio
id="mqr-5"
name="message"
value={TWO_LINES_STACKED}
checked={key === TWO_LINES_STACKED}
onChange={handleKeyChange}
label="Two Line Message with Stacked Action"
/>
<Button id="mqr-submit" type="submit" theme="primary">
Add Message
</Button>
</Form>
);
}
export default function SimpleMessageQueueContainer(): ReactElement {
return (
+ <>
- <MessageQueue id="simple-message-queue">
<SimpleMessageQueue />
+ <Snackbar />
+ <>
- </MessageQueue>
);
}
App Bar
🔧 remove-class-name-constants
npx @react-md/codemod v5-to-v6/app-bar/remove-class-name-constants
The APP_BAR_OFFSET_* constants were removed and custom styles are required to
add any offset going forward. The codemod will apply the following diff:
+// TODO: Add styles for app bar offset
import cn from "classnames";
import { useState } from "react";
-import {
- APP_BAR_OFFSET_CLASSNAME,
- APP_BAR_OFFSET_DENSE_CLASSNAME,
- APP_BAR_OFFSET_PROMINENT_CLASSNAME,
- APP_BAR_OFFSET_PROMINENT_DENSE_CLASSNAME,
-} from "react-md";
import styles from "./styles.module.scss";
export default function Example() {
const [dense, setDense] = useState(false);
const [prominent, setProminent] = useState(false);
- return (
- <div
- className={cn(
- styles.content,
- {
- [APP_BAR_OFFSET_CLASSNAME]: !dense && !prominent,
- [APP_BAR_OFFSET_DENSE_CLASSNAME]: dense && !prominent,
- [APP_BAR_OFFSET_PROMINENT_CLASSNAME]: !dense && prominent,
- [APP_BAR_OFFSET_PROMINENT_DENSE_CLASSNAME]: dense && prominent,
- },
- !dense && !prominent && APP_BAR_OFFSET_CLASSNAME,
- dense && !prominent && APP_BAR_OFFSET_DENSE_CLASSNAME,
- !dense && prominent && APP_BAR_OFFSET_PROMINENT_CLASSNAME,
- dense && prominent && APP_BAR_OFFSET_PROMINENT_DENSE_CLASSNAME
- )}
- >
- content
- </div>
- );
+ return <div className={cn(styles.content, {})}>content</div>;
}
If the content should still be offset by the app bar's height, apply the following styles:
@use "react-md";
.container {
// use the current var(--rmd-app-bar-height) as the padding top
@include react-md.app-bar-use-var(padding-top, height);
// or choose one of the static values:
padding-top: react-md.$app-bar-height;
padding-top: react-md.$dense-height;
padding-top: react-md.$prominent-height;
padding-top: react-md.$prominent-dense-height;
}
✅ remove-use-action-class-name
npx @react-md/codemod v5-to-v6/app-bar/remove-use-action-class-name
The useActionClassName hook was removed since it is no longer needed for
spacing within an AppBar.
-import { useActionClassName } from "react-md";
import SomeComponent from "./SomeComponent";
import styles from "./styles.module.scss";
export function Example() {
- const className1 = useActionClassName();
- const className2 = useActionClassName({ first: true });
- const className3 = useActionClassName({ last: true });
- const className4 = useActionClassName({ className: styles.example });
+ const className4 = styles.example;
return (
<>
- <div className={className1} />
- <div className={className2} />
- <div className={className3} />
+ <div />
+ <div />
+ <div />
<div className={className4} />
<SomeComponent
- className1={useActionClassName()}
- className2={useActionClassName({ first: true })}
- className3={useActionClassName({ last: true })}
- className4={useActionClassName({ className: styles.example })}
+ className4={styles.example}
objectExample={{
- className1: useActionClassName(),
- className2: useActionClassName({ first: true }),
- className3: useActionClassName({ last: true }),
- className4: useActionClassName({ className: styles.example }),
+ className4: styles.example,
}}
/>
</>
✅ replace-nav-and-action-with-button
npx @react-md/codemod v5-to-v6/app-bar/replace-nav-and-action-with-button
The AppBarAction and AppBarNav components were removed and can be replaced
with a Button.
import type { ReactElement } from "react";
import {
AppBar,
- AppBarAction,
- AppBarNav,
AppBarTitle,
+ Button,
MenuSVGIcon,
MoreVertSVGIcon,
SearchSVGIcon,
@@ -19,33 +18,21 @@ export default function Demo(): ReactElement {
<Container>
{themes.map((theme, i) => (
<AppBar id={`simple-usage-app-bar-${i}`} theme={theme} key={theme}>
- <AppBarNav
- id={`simple-usage-nav-${i}`}
- aria-label="Navigation"
- inheritColor
- >
+ <Button id={`simple-usage-nav-${i}`} aria-label="Navigation">
<MenuSVGIcon />
- </AppBarNav>
+ </Button>
<AppBarTitle
id={`simple-usage-title-${i}`}
className="rmd-typography--capitalize"
>
{theme}
</AppBarTitle>
- <AppBarAction
- id={`simple-usage-search-${i}`}
- first
- aria-label="Search"
- >
+ <Button id={`simple-usage-search-${i}`} aria-label="Search">
<SearchSVGIcon />
- </AppBarAction>
- <AppBarAction
- id={`simple-usage-kebab-${i}`}
- last
- aria-label="Actions"
- >
+ </Button>
+ <Button id={`simple-usage-kebab-${i}`} aria-label="Actions">
<MoreVertSVGIcon />
- </AppBarAction>
+ </Button>
</AppBar>
))}
</Container>
✅ update-app-bar-props
npx @react-md/codemod v5-to-v6/app-bar/update-app-bar-props
The following props have changed for the AppBar component:
componentwas renamed toasfixedElevationwas renamed todisableElevationfixedwas removed in favor of the newpositionpropflexWrapandinheritColorwere removed since they are no longer needed
function Example() {
return (
<>
- <AppBar component="div">Hello</AppBar>
- <AppBar fixed={true}>Hello</AppBar>
- <AppBar fixed fixedElevation={false}>
- Hello
- </AppBar>
- <AppBar fixed={false} fixedElevation>
- Hello
- </AppBar>
- <AppBar flexWrap inheritColor>
+ <AppBar as="div">Hello</AppBar>
+ <AppBar position="fixed">Hello</AppBar>
+ <AppBar position="fixed" disableFixedElevation>
Hello
</AppBar>
+ <AppBar>Hello</AppBar>
+ <AppBar>Hello</AppBar>
</>
);
}
✅ update-app-bar-title-props
npx @react-md/codemod v5-to-v6/app-bar/update-app-bar-title-props
The following props have changed for the AppBarTitle component:
noWrapwas removed in favor of the newtextOverflowpropkeylineis no longer a boolean
function Example() {
return (
<>
- <AppBarTitle noWrap>Hello</AppBarTitle>
- <AppBarTitle noWrap={true}>Hello</AppBarTitle>
- <AppBarTitle noWrap={false}>Hello</AppBarTitle>
- <AppBarTitle keyline>Hello</AppBarTitle>
- <AppBarTitle keyline={true}>Hello</AppBarTitle>
- <AppBarTitle keyline={false}>Hello</AppBarTitle>
+ <AppBarTitle textOverflow="nowrap">Hello</AppBarTitle>
+ <AppBarTitle textOverflow="nowrap">Hello</AppBarTitle>
+ <AppBarTitle>Hello</AppBarTitle>
+ <AppBarTitle keyline="nav">Hello</AppBarTitle>
+ <AppBarTitle keyline="nav">Hello</AppBarTitle>
+ <AppBarTitle>Hello</AppBarTitle>
</>
);
}
Auto Complete ❌
The AutoComplete has a completely new API and has been renamed to Autocomplete. It
is recommended to check out the Autocomplete Demos to see
how to use the new API.
The main breaking changes are:
- The
dataprop was renamed tooptions - The
valueprop has been renamed toquerysince thevalueis now the selected option(s) - The
filterprop no longer accepts string values ("case-insensitive","fuzzy","none") and instead should always be a filter function"none"filter can be replaced withnoopAutocompleteFilterfrom@react-md/core/autocomplete/defaults"case-insensitive"filter can be replaced withdefaultAutocompleteFilterfrom@react-md/core/autocomplete/defaultsorcaseInsensitiveSearchfrom@react-md/core/searching/caseInsensitive"fuzzy"filter can be replaced withfuzzySearchfrom@react-md/core/searching/fuzzy
- The
filterfunction now provides a single argument instead of multiple so thequeryanddatamust be destructured. - The
filterOptionsandfilterOnNoValueprops were removed in favor of the customfilterfunction - The
highlight,highlightRepeating,highlightStyle, andhighlightClassNameprops were removed since highlighting is no longer supported. See the Highlights example for a way to add highlights back - The
labelKey,valueKey,omitKeys,getResultId,getResultLabel, andgetResultValueprops have been removed. UsegetOptionLabelandgetOptionPropsinstead - The
beforeResultsChildrenandafterResultsChildrenhave been removed in favor of just providing the customchildreninstead - The
autoCompleteprop has been removed and only supports the"list"or"none"behavior. Set thefilterprop tonoopAutocompleteFilterto enable the"none"behavior. - The
clearOnAutoCompleteprop has been removed in favor of settingupdateQueryOnSelectto"clear" - The
onAutocompleteprop has been removed in favor of controlling thevalueor theonValueChangeprop - The
disableShowOnFocusprop has been removed - The listbox style, className, and positioning options must now be passed to
listboxProps:
🔧 update-simple-props
npx @react-md/codemod v5-to-v6/autocomplete/update-simple-props
This codemod will attempt to fix all the breaking changes and add TODOs for all the manual steps.
+// TODO: Ensure the `Autocomplete` options are strings or add the `getOptionLabel` prop
import { type ReactElement, useState } from "react";
-import { AutoComplete } from "react-md";
+import { Autocomplete } from "react-md";
const fruits = [
"Apple",
"Apricot",
"Banana",
"Blueberry",
"Cranberry",
"Kiwi",
"Peach",
"Plum",
"Strawberry",
];
export default function CustomFilterFunction(): ReactElement {
const [value, setValue] = useState("");
return (
<>
- <AutoComplete
+ <Autocomplete
id="simple-autocomplete-1"
label="Case insensitive"
placeholder="Apple"
- value={value}
+ query={value}
onChange={(event) => {
setValue(event.currentTarget.value)
}}
- data={fruits}
+ options={fruits}
- filter={(query, data, options) => {
+ filter={({ query, list: data, ...options }) => {
return data;
}}
- clearOnAutoComplete
+ updateQueryOnSelect="clear"
- onAutoComplete={({ value, index, result, dataIndex, filteredData }) => {
+ onValueChange={(value) => {
// do something
}}
- listboxStyle={{ color: "red" }}
- listboxClassName="custom-class-name"
- listboxWidth="auto"
- anchor={BELOW_CENTER_ANCHOR}
- vwMargin={20}
- vhMargin={20}
- xMargin={12}
- yMargin={12}
- closeOnResize={false}
- transformOrigin={false}
- closeOnScroll={false}
- preventOverlap={false}
- disableSwapping={false}
- disableVHBounds={false}
+ listboxProps={{
+ style: { color: "red" },
+ className: "custom-class-name",
+ width: "auto",
+ anchor: BELOW_CENTER_ANCHOR,
+ vwMargin: 20,
+ vhMargin: 20,
+ xMargin: 12,
+ yMargin: 12,
+ closeOnResize: false,
+ transformOrigin: false,
+ closeOnScroll: false,
+ preventOverlap: false,
+ disableSwapping: false,
+ disableVHBounds: false,
+ }}
/>
</>
);
}
Avatar 🎉
No breaking changes!
Badge
🎨 remove-badge-container
npx @react-md/codemod v5-to-v6/badge/remove-badge-container
The BadgeContainer was removed and custom styles must be used instead.
import type { ReactElement } from "react";
-import {
- Badge,
- BadgeContainer,
- Button,
- NotificationsSVGIcon,
- Typography,
-} from "react-md";
+import { Badge, Button, NotificationsSVGIcon, Typography } from "react-md";
import { COPYRIGHT } from "constants/unicode";
@@ -14,15 +8,27 @@ import styles from "./CustomizingBadges.module.scss";
export default function CustomizingBadges(): ReactElement {
return (
<>
- <BadgeContainer className={styles.container}>
+ <span
+ className={styles.container}
+ style={{
+ display: "inline-flex",
+ position: "relative",
+ }}
+ >
{/* since the badge is presentational, don't add the `aria-describedby` value */}
<Typography>Some amazing product</Typography>
<Badge id="copyright-badge" theme="clear">
{COPYRIGHT}
</Badge>
- </BadgeContainer>
+ </span>
{/* this is _basically_ the `BadgedButton` component except with an extra `<span>` */}
- <BadgeContainer className={styles.custom}>
+ <span
+ className={styles.custom}
+ style={{
+ display: "inline-flex",
+ position: "relative",
+ }}
+ >
<Button
id="custom-badged-button"
aria-describedby="custom-badged-button-badge"
@@ -31,7 +37,7 @@ export default function CustomizingBadges(): ReactElement {
<NotificationsSVGIcon />
</Button>
<Badge id="custom-badged-button-badge">8</Badge>
- </BadgeContainer>
+ </span>
</>
);
}
🔧 update-badge
npx @react-md/codemod v5-to-v6/badge/update-badge
The BadgedButton was removed and instead just use the Button and Badge
components together.
import { type ReactElement } from "react";
-import { BadgedButton } from "react-md";
+import { Badge, Button, getIcon } from "react-md";
import { NotificationsSVGIcon } from "@react-md/material-icons";
import styles from "./SimpleExamples.module.scss";
@@ -7,16 +7,24 @@ import styles from "./SimpleExamples.module.scss";
export default function Example(): ReactElement {
return (
<>
- <BadgedButton id="badged-button-1" className={styles.container}>
- 3
- </BadgedButton>
- <BadgedButton
+ <Button
+ id="badged-button-1"
+ className={styles.container}
+ aria-label="Notifications"
+ buttonType="icon"
+ >
+ {getIcon("notification")}
+ <Badge>3</Badge>
+ </Button>
+ <Button
id="badged-button-2"
className={styles.container}
- buttonChildren={<NotificationsSVGIcon />}
+ aria-label="Notifications"
+ buttonType="icon"
>
- 7
- </BadgedButton>
+ <NotificationsSVGIcon />
+ <Badge>7</Badge>
+ </Button>
</>
);
}
In addition, the BadgeTheme was updated "default" to be "greyscale". The
codemod will insert a temporary _toBadgeTheme helper when the theme is not
a string.
import type { ReactElement } from "react";
-import type { BadgeTheme } from "react-md";
-import { BadgedButton } from "react-md";
+import { Badge, BadgeTheme, Button, getIcon } from "react-md";
import styles from "./SimpleExamples.module.scss";
@@ -10,15 +9,23 @@ export default function ThemedBadges(): ReactElement {
return (
<>
{themes.map((theme) => (
- <BadgedButton
+ <Button
key={theme}
id={`badged-button-${theme}`}
- badgeTheme={theme}
className={styles.container}
+ aria-label="Notifications"
+ buttonType="icon"
>
- {theme.length}
- </BadgedButton>
+ {getIcon("notification")}
+ <Badge theme={_toBadgeTheme(theme)}>{theme.length}</Badge>
+ </Button>
))}
</>
);
}
+
+function _toBadgeTheme(
+ theme: BadgeTheme | "default" | undefined,
+): BadgeTheme | undefined {
+ return theme === "default" ? "greyscale" : theme;
+}
Button
✅ remove-unused-props
npx @react-md/codemod v5-to-v6/button/remove-unused-props
The Button no longer supports the ripple props.
import { Button } from "react-md";
import styles from "./styles.module.scss";
export default function Example() {
return (
<Button
onClick={() => {
// do something
}}
disableRipple
- disableProgrammaticRipple
- disableEnterClick
- disableSpacebarClick
- disablePressedFallback
- enablePressedAndRipple
- rippleTimeout={100}
- rippleClassName={styles.ripple}
- rippleClassNames={{ enter: "", exit: "" }}
- rippleContainerClassName="example"
>
Hello, world!
</Button>
);
}
✅ rename-button-theme-class-names
npx @react-md/codemod v5-to-v6/button/rename-button-theme-class-names
The buttonThemeClassNames utility function was renamed to button.
import cn from "classnames";
import type { ReactElement } from "react";
import type { ButtonThemeProps, LinkProps } from "react-md";
-import { Link, buttonThemeClassNames } from "react-md";
+import { Link, button } from "react-md";
import styles from "./WithButtonStyles.module.scss";
@@ -17,7 +17,7 @@ function LinkStyledButton({
return (
<Link
{...props}
- className={buttonThemeClassNames({
+ className={button({
disabled,
theme,
themeType,
✅ rename-fab
npx @react-md/codemod v5-to-v6/button/rename-fab
The FAB was renamed to FloatingActionButton.
import { ReactNode, ReactElement } from "react";
-import { FAB, FABProps, FABPosition } from "react-md";
+import {
+ FloatingActionButton,
+ FloatingActionButtonProps,
+ FloatingActionButtonPosition,
+} from "react-md";
-interface CustomProps extends FABProps {
- altPosition?: FABPosition;
+interface CustomProps extends FloatingActionButtonProps {
+ altPosition?: FloatingActionButtonPosition;
children: ReactNode;
}
@@ -10,8 +14,8 @@ export function Custom(props: CustomProps): ReactElement {
const { children, altPosition, ...remaining } = props;
return (
- <FAB {...remaining} position={altPosition}>
+ <FloatingActionButton {...remaining} position={altPosition}>
{children}
- </FAB>
+ </FloatingActionButton>
);
}
✅ rename-unstyled-button
npx @react-md/codemod v5-to-v6/button/rename-unstyled-button
The UnstyledButton component was renamed to ButtonUnstyled.
@@ -1,4 +1,4 @@
-import { Button, UnstyledButton } from "react-md";
+import { Button, ButtonUnstyled } from "react-md";
export default function Example() {
return (
@@ -10,21 +10,21 @@ export default function Example() {
>
Hello!
</Button>
- <UnstyledButton
+ <ButtonUnstyled
onClick={() => {
// do something else
}}
>
Unstyled 1
- </UnstyledButton>
- <UnstyledButton
+ </ButtonUnstyled>
+ <ButtonUnstyled
onClick={() => {
// do something else
}}
className="example-class-name"
>
Unstyled 2
- </UnstyledButton>
+ </ButtonUnstyled>
</>
);
}
Card
✅ card-actions-to-card-footer
npx @react-md/codemod v5-to-v6/card/card-actions-to-card-footer
The CardActions component was renamed to CardFooter and the align prop
was renamed to justify.
import { type ReactElement } from "react";
-import { CardActions } from "react-md";
+import { CardFooter } from "react-md";
export default function Example(): ReactElement {
return (
- <CardActions align="start" className="example">
+ <CardFooter justify="start" className="example">
Content
- </CardActions>
+ </CardFooter>
);
}
✅ remove-deprecated-card-props
npx @react-md/codemod v5-to-v6/card/remove-deprecated-card-props
The deprecated raiseable prop was removed in favor of raisable.
export default function Example() {
return (
<>
- <Card raiseable>Content</Card>
+ <Card raisable>Content</Card>
<Card raisable>Content</Card>
<Card>Content</Card>
</>
✅ update-card-content-props
npx @react-md/codemod v5-to-v6/card/update-card-content-props
The CardContent component updated the following props:
disableExtraPaddingwas renamed todisableLastChildPaddingdisableParagraphMarginwas removed
return (
<>
<CardContent>Content</CardContent>
- <CardContent disableParagraphMargin>Content</CardContent>
- <CardContent disableExtraPadding>Content</CardContent>
+ <CardContent>Content</CardContent>
+ <CardContent disableLastChildPadding>Content</CardContent>
<CardContent disablePadding disableSecondaryColor className="custom">
Content
</CardContent>
✅ update-card-header-props
npx @react-md/codemod v5-to-v6/card/update-card-header-props
The CardHeader updated the following props:
alignwas removedbeforeChildrenwas renamed tobeforeAddonafterChildrenwas renamed toafterAddoncontentClassNamewas removed in favor of the newcontentProps
return (
<>
<CardHeader
- align="top"
- beforeChildren={<p>Hello</p>}
- afterChildren={<Typography>World!</Typography>}
- contentClassName="content-classname"
+ beforeAddon={<p>Hello</p>}
+ afterAddon={<Typography>World!</Typography>}
+ contentProps={{
+ className: "content-classname",
+ }}
>
Content
</CardHeader>
- <CardHeader contentClassName={styles.className}>Content</CardHeader>
- <CardHeader contentClassName={cn(styles.className, "another")}>
+ <CardHeader
+ contentProps={{
+ className: styles.className,
+ }}
+ >
+ Content
+ </CardHeader>
+ <CardHeader
+ contentProps={{
+ className: cn(styles.className, "another"),
+ }}
+ >
Content
</CardHeader>
</>
✅ update-card-subtitle-props
npx @react-md/codemod v5-to-v6/card/update-card-subtitle-props
The CardSubtitle updated the following props:
noWrapwas removed in favor of the newtextOverflowpropdisableSecondaryColorwas removed in favor of the newtextColorprop
}: ExampleProps): ReactElement {
return (
<>
- <CardSubtitle noWrap>{children}</CardSubtitle>
- <CardSubtitle disableSecondaryColor>{children}</CardSubtitle>
+ <CardSubtitle textOverflow="nowrap">{children}</CardSubtitle>
+ <CardSubtitle textColor={null}>{children}</CardSubtitle>
<CardSubtitle
- noWrap={noWrap}
- disableSecondaryColor={disableSecondaryColor}
+ textOverflow={noWrap ? "nowrap" : undefined}
+ textColor={disableSecondaryColor ? null : undefined}
>
{children}
</CardSubtitle>
✅ update-card-title-props
npx @react-md/codemod v5-to-v6/card/update-card-title-props
The CardTitle updated the following props:
noWrapwas removed in favor of the newtextOverflowpropsmallwas removed in favor of setting thetypeTypographyprop
return (
<>
<CardTitle>{children}</CardTitle>
- <CardTitle small>{children}</CardTitle>
- <CardTitle small={false}>{children}</CardTitle>
- <CardTitle noWrap>{children}</CardTitle>
- <CardTitle noWrap={false}>{children}</CardTitle>
- <CardTitle small noWrap>
+ <CardTitle type="subtitle-1">{children}</CardTitle>
+ <CardTitle>{children}</CardTitle>
+ <CardTitle textOverflow="nowrap">{children}</CardTitle>
+ <CardTitle>{children}</CardTitle>
+ <CardTitle type="subtitle-1" textOverflow="nowrap">
{children}
</CardTitle>
</>
Chip
✅ update-chip-props
npx @react-md/codemod v5-to-v6/chip/update-chip-props
The Chip renamed the noninteractable prop to noninteractive.
export default function Example(): ReactElement {
return (
<>
- <Chip noninteractable>Hello!</Chip>
+ <Chip noninteractive>Hello!</Chip>
</>
);
}
Dialog
✅ remove-nested-dialog-context-provider
npx @react-md/codemod v5-to-v6/dialog/remove-nested-dialog-context-provider
The NestedDialogContextProvider has been removed and is no longer required.
IconProvider,
type MenuConfiguration,
MenuConfigurationProvider,
- NestedDialogContextProvider,
StatesConfig,
type StatesConfigProps,
UserInteractionModeListener,
@@ -100,7 +99,7 @@ export function Configuration({
menuConfiguration,
}: ConfigurationProps): ReactElement {
return (
<Dir defaultDir={defaultDir}>
<AppSizeListener
defaultSize={defaultSize}
onChange={onAppResize}
@@ -110,7 +109,7 @@ export function Configuration({
desktopMinWidth={desktopMinWidth}
desktopLargeMinWidth={desktopLargeMinWidth}
>
- <NestedDialogContextProvider>
+ <>
<UserInteractionModeListener>
<StatesConfig
disableRipple={disableRipple}
@@ -129,8 +128,8 @@ export function Configuration({
</HoverModeProvider>
</StatesConfig>
</UserInteractionModeListener>
- </NestedDialogContextProvider>
+ </>
</AppSizeListener>
</Dir>
);
}
🔧 update-dialog-props
npx @react-md/codemod v5-to-v6/dialog/update-dialog-props
The Dialog and FixedDialog components have the following prop changes:
forceContainerhas been removed since there is always a container element nowoverlayhas been renamed todisableOverlayoverlayStyle,overlayClassName, andoverlayHiddenhave been removed in favor of theoverlayPropswhereoverlayHiddenis renamed tonoOpacitycontainerStyleandcontainerClassNamehave been removed in favor ofcontainerPropscomponenthas been removed and only supports being rendered as a"div"disableNestedDialogFixeshas been removed since it is no longer neededdefaultFocushas been removed and default focus must be set manually instead usingautoFocuson a focusable element or custom logicdisableFocusContainer,disableFocusOnMount,disableFocusOnUnmount, anddisableTabFocusWraphave been removed in favor of theisFocusTypeDisabledfunctiondisableFocusCache,disableFocusOnMountScroll, andunmountFocusFallbackhave been removed
+// A `Dialog` set the `defaultFocus` but that is no longer supported. Enable the `autoFocus` prop on the target element instead.
import { ReactElement, useRef } from "react";
import {
Button,
FixedDialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
Typography,
useToggle,
} from "react-md";
export default function Demo(): ReactElement {
const [visible, enable, disable] = useToggle(false);
const fixedTo = useRef<HTMLButtonElement>(null);
return (
@@ -19,37 +20,31 @@ export default function Demo(): ReactElement {
Show Dialog
</Button>
<FixedDialog
id="simple-dialog"
fixedTo={fixedTo}
visible={visible}
onRequestClose={disable}
aria-labelledby="dialog-title"
- forceContainer
- defaultFocus="last"
- disableFocusContainer
- disableFocusCache
- disableFocusOnMount
- disableTabFocusWrap
- disableFocusOnMountScroll
- disableFocusOnUnmount
- unmountFocusFallback
- disableNestedDialogFixes
- component="nav"
- overlay={false}
- overlayHidden
- overlayStyle={{ color: "red" }}
- overlayClassName="custom-overlay-class"
- containerStyle={{ backgroundColor: "orange" }}
- containerClassName="custom-container-class"
+ disableOverlay
options={{ xMargin: 12, yMargin: 12 }}
- getOptions={() => ({
+ getFixedPositionOptions={() => ({
vhMargin: 20,
vwMargin: 20,
})}
+ overlayProps={{
+ noOpacity: true,
+ style: { color: "red" },
+ className: "custom-overlay-class",
+ }}
+ containerProps={{
+ style: { backgroundColor: "orange" },
+ className: "custom-container-class",
+ }}
+ isFocusTypeDisabled={() => true}
>
<DialogHeader>
<DialogTitle id="dialog-title">Simple Dialog</DialogTitle>
</DialogHeader>
<DialogContent>
<Typography margin="none">This is some text in a dialog.</Typography>
</DialogContent>
<DialogFooter>
Divider
🎨 vertical-divider-to-divider
npx @react-md/codemod v5-to-v6/divider/vertical-divider-to-divider
The VerticalDivider component was removed in favor of just enabling the
vertical prop on the Divider.
import { type ReactElement } from "react";
-import { VerticalDivider } from "react-md";
+import { Divider } from "react-md";
export default function Example(): ReactElement {
return (
<>
- <VerticalDivider />
- <VerticalDivider maxHeight={0.8} />
- <VerticalDivider maxHeight={0.8} className="custom-class-name" />
+ <Divider vertical />
+ <Divider vertical />
+ <Divider className="custom-class-name" vertical />
</>
);
}
In addition, the somewhat undocumented useVerticalDividerHeight hook was removed
and there is no replacement.
+// TODO: The following react-md imports have been removed from the library and must be manually removed from the rest of the file: VerticalDividerHeight, VerticalDividerHookOptions, useVerticalDividerHeight
import { type ReactElement } from "react";
-import {
- VerticalDividerHeight,
- VerticalDividerHookOptions,
- useVerticalDividerHeight,
-} from "react-md";
type H = VerticalDividerHeight;
type O = VerticalDividerHookOptions;
export default function Example(): ReactElement {
const { ref, style } = useVerticalDividerHeight({
maxHeight: 0.8,
});
return <div style={style} ref={ref} vertical />;
}
Expansion Panel
✅ update-expansion-panel-props
npx @react-md/codemod v5-to-v6/expansion-panel/update-expansion-panel-props
The ExpansionPanel updated the following props:
raiseablewas renamed toraisabledisablePaddingwas renamed todisableContentPaddingheaderwas renamed toheaderChildrencustomHeaderwas renamed toheader
export function SimpleExample(): ReactElement {
return (
<>
- <ExpansionPanel raiseable />
- <ExpansionPanel disablePadding />
- <ExpansionPanel disableLastParagraphMargin />
- <ExpansionPanel disableSecondaryColor />
- <ExpansionPanel disableSecondaryColor={false} />
- <ExpansionPanel disableSecondaryColor={flag || another} />
+ <ExpansionPanel raisable />
+ <ExpansionPanel disableContentPadding />
+ <ExpansionPanel />
+ <ExpansionPanel />
+ <ExpansionPanel
+ contentProps={{
+ disableSecondaryColor: false,
+ }}
+ />
+ <ExpansionPanel
+ contentProps={{
+ disableSecondaryColor: flag || another,
+ }}
+ />
</>
);
}
export function HeaderExample(): ReactElement {
return (
<>
- <ExpansionPanel header="Some Content">And some more</ExpansionPanel>
- <ExpansionPanel header={<Typography>Some JSX</Typography>}>
+ <ExpansionPanel headerChildren="Some Content">
And some more
</ExpansionPanel>
- <ExpansionPanel customHeader={<ExpansionPanelHeader />}>
- Content
+ <ExpansionPanel headerChildren={<Typography>Some JSX</Typography>}>
+ And some more
</ExpansionPanel>
+ <ExpansionPanel header={<ExpansionPanelHeader />}>Content</ExpansionPanel>
</>
);
}
🔧 use-panels-to-use-expansion-panel
npx @react-md/codemod v5-to-v6/expansion-panel/use-panels-to-use-expansion-panel
The usePanels hook was renamed to useExpansionPanels with a new API:
- the
onKeyDownevent handler is no longer returned since theExpansionListno longer requires it - the hook returns an object instead of an ordered array
- the panel props are generated using
getPanelPropsinstead of providing acountof panel props to generate preventAllClosedwas renamed topreventAllCollapsedidPrefixwas renamed tobaseId- the
expandedIdsare now aReadonlySet<string>instead ofstring[]
@@ -6,7 +6,7 @@ import {
Fieldset,
Grid,
useChecked,
- usePanels,
+ useExpansionPanels,
} from "react-md";
interface Props {
@@ -25,19 +25,19 @@ function Example({
defaultExpandedIndex = multiple ? [1, 2] : 0;
}
- const [panels, onKeyDown] = usePanels({
- count: 3,
- idPrefix: "configuring-panels",
+ const { getPanelProps: getPanelProps } = useExpansionPanels({
+ baseId: "configuring-panels",
multiple,
- preventAllClosed,
+ preventAllCollapsed: preventAllClosed,
+
// this will be considered `0` if the `preventAllClosed` option is enabled
// but still `undefined`
defaultExpandedIndex,
});
return (
- <ExpansionList onKeyDown={onKeyDown}>
- <ExpansionPanel {...panels[0]} header="Panel 1">
+ <ExpansionList>
+ <ExpansionPanel {...getPanelProps(0)} header="Panel 1">
Nam lorem est, porta id tincidunt et, consectetur in nulla. Morbi cursus
at massa a feugiat. Mauris eu convallis elit, ac mollis metus. Quisque
pulvinar ante libero, ut laoreet dolor bibendum volutpat. In diam purus,
@@ -46,7 +46,7 @@ function Example({
ultricies lacus in massa finibus gravida. Maecenas turpis libero,
fringilla nec sodales sed, lacinia eget libero.
</ExpansionPanel>
- <ExpansionPanel {...panels[1]} header="Panel 2">
+ <ExpansionPanel {...getPanelProps(1)} header="Panel 2">
Aenean rhoncus tristique fringilla. Phasellus ac libero porta, iaculis
quam quis, porta nibh. Maecenas laoreet dignissim magna quis ultricies.
Vivamus ut blandit nisl. Curabitur vel turpis vulputate, mollis ante in,
@@ -54,7 +54,7 @@ function Example({
finibus lectus. Donec eleifend felis odio, vitae gravida purus ornare
sed.
</ExpansionPanel>
- <ExpansionPanel {...panels[2]} header="Panel 3">
+ <ExpansionPanel {...getPanelProps(2)} header="Panel 3">
Donec lacinia ut sem vitae molestie. Nam placerat tristique facilisis.
Aliquam iaculis augue eget mollis fermentum. Morbi mattis ultricies
lacinia. Fusce vitae commodo nisl. Donec congue arcu ut porta feugiat.
Form
🔧 replace-with-message-components
npx @react-md/codemod v5-to-v6/form/replace-with-message-components
The TextFieldWithMessage, TextAreaWithMessage, and PasswordWithMessage components
have been removed and instead the default behavior for the TextField,
TextArea, and Password components.
import { ReactElement, useCallback, useMemo, useState } from "react";
import {
Button,
ErrorChangeHandler,
Form,
GetErrorMessage,
- PasswordWithMessage,
- TextAreaWithMessage,
- TextFieldWithMessage,
+ Password,
+ TextArea,
+ TextField,
defaultGetErrorMessage,
useTextField,
} from "react-md";
@@ -38,94 +38,90 @@
return (
<Form>
- <TextFieldWithMessage
+ <TextField
{...nameFieldProps}
label="Name"
placeholder="John Doe"
name="name"
/>
- <TextFieldWithMessage
+ <TextField
{...dateFieldProps}
label="Date *"
placeholder="01/01/2020"
name="date"
/>
- <TextAreaWithMessage
+ <TextArea
{...descriptionFieldProps}
label="Description"
placeholder="Something amazing."
name="description"
/>
- <TextAreaWithMessage
+ <TextArea
{...description2FieldProps}
label="Description 2 *"
placeholder="Something amazing."
name="description2"
/>
- <PasswordWithMessage
+ <Password
{...passwordProps}
label="Password *"
name="password"
/>
<Button
type="submit"
disabled={errored}
theme="primary"
themeType="outline"
>
Submit
</Button>
</Form>
);
}
🔧 update-text-field-container-props
npx @react-md/codemod v5-to-v6/form/update-text-field-container-props
The TextFieldContainer updated a few props which affects the TextField,
TextArea, Password, and Select components:
- The
leftChildrenandrightChildrenprops were renamed toleftAddonandrightAddon - The
isLeftAddonandisRightAddonprops were renamed todisableLeftAddonStylesanddisableRightAddonStyles - The
stretchprop was removed
export default function TextFieldContainerProps(): ReactElement {
const [value, setValue] = useState("");
const isLeftAddon = true;
const isRightAddon = false;
return (
<>
<TextField
label="Label"
- leftChildren={<span>Hello!</span>}
- stretch
- rightChildren={<span>World!</span>}
- isLeftAddon
- isRightAddon={false}
+ leftAddon={<span>Hello!</span>}
+ rightAddon={<span>World!</span>}
+ disableRightAddonStyles
/>
<TextArea
- stretch
label="Label"
- leftChildren={<span>Hello!</span>}
- rightChildren={<span>World!</span>}
- isLeftAddon={isLeftAddon}
- isRightAddon
+ leftAddon={<span>Hello!</span>}
+ rightAddon={<span>World!</span>}
+ disableLeftAddonStyles={!isLeftAddon}
/>
<Password
label="Label"
- leftChildren={<span>Hello!</span>}
- rightChildren={<span>World!</span>}
- stretch
+ leftAddon={<span>Hello!</span>}
+ rightAddon={<span>World!</span>}
/>
<Select
id="simple-select-example"
label="A Label"
placeholder="Choose..."
name="select"
options={states.map(({ abbreviation, name }) => ({
label: name,
value: abbreviation,
}))}
value={value}
onChange={(value) => setValue(value)}
- leftChildren={<span>Hello!</span>}
- rightChildren={<span>World!</span>}
- isLeftAddon={false}
- isRightAddon={false}
- stretch
+ leftAddon={<span>Hello!</span>}
+ rightAddon={<span>World!</span>}
+ disableLeftAddonStyles
+ disableRightAddonStyles
/>
</>
);
}
🔧 update-use-text-field-api
npx @react-md/codemod v5-to-v6/form/update-use-text-field-api
The useTextField and useNumberField hooks have updated their api slightly:
- The hooks return an object instead of an ordered list
- The
validateOnChangeoption was renamed tovalidationTypeand no longer supports boolean values truewould now be"change"falsewould now be[]- ❌ the
getErrorMessageandisErroredoptions also renamed this option, but is not handled by the codemod getErrorIconoption now provides a singleoptionsobject instead of multiple arguments- the
defaultGetErrorIconutil matches this as well
import { defaultGetErrorIcon, useNumberField, useTextField } from "react-md";
+export function ExampleDiff(): null {
- const [, textFieldProps] = useTextField({
+ const { fieldProps: textFieldProps } = useTextField({
name: "field",
- validateOnChange: true,
- getErrorIcon: (errorMessage, error, errorIcon) => {
+ validationType: "change",
+ getErrorIcon: (options) => {
+ const { error, errorIcon, errorMessage } = options;
+
if (errorMessage === "Hello") {
return errorIcon;
}
- return defaultGetErrorIcon(errorMessage, error, errorIcon);
+ return defaultGetErrorIcon({
+ error,
+ errorIcon,
+ errorMessage,
+ });
},
});
- const [numberValue, numberFieldProps, { reset, setState }] = useNumberField({
- name: "field2",
- validateOnChange: false,
- getErrorIcon: (errorMessage, error, errorIcon) => {
+ const {
+ value: numberValue,
+ fieldProps: numberFieldProps,
+ reset,
+ setState,
+ } = useNumberField({
+ name: "field",
+ validationType: [],
+ getErrorIcon: (options) => {
+ const { error, errorIcon, errorMessage } = options;
+
if (errorMessage === "Hello") {
return errorIcon;
}
- return defaultGetErrorIcon(errorMessage, error, errorIcon);
+ return defaultGetErrorIcon({
+ error,
+ errorIcon,
+ errorMessage,
+ });
},
});
return null;
}
❌ update-select-api
npx @react-md/codemod v5-to-v6/form/update-select-api
The Select component has been updated to mimic the native <select> API meaning:
- The
Selectno longer accepts anoptionsprop and instead each option should be rendered as a child with theOptioncomponent - The
labelKey,valueKey,getOptionId,getOptionLabel,getOptionValue, andisOptionDisabledprops have been removed since they are invalid or should be provided to theOptioncomponent instead - The
disableMovementChangeprop was removed since it was bad for accessibility to update the value when the user moves keyboard focus - the
labelStyleandlabelClassNameprops have been removed in favor oflabelProps - The
displayLabelStyleanddisplayLabelClassNameprops have been removed in favor of the newselectedOptionProps - The
getDisplayLabelprop has been removed in favor ofselectedOptionProps.children - The
anchor,listboxWidth,listboxStyle,listboxClassName,closeOnScroll,closeOnResize, andpositionOptionshave been removed in favor ofmenuProps - The
disableLeftAddonhas been renamed todisableOptionAddon - The
onChangeprop has been updated to provide theChangeEvent<HTMLInputElement>instead of the current value. Theevent.currentTarget.valueshould be used instead and will can be strictly typed for typescript users
The codemod will attempt to convert the select API, but there were too many edge cases so I gave up. You'll have to manually handle most of the updates.
import states from "constants/states";
import { type ReactElement, useState } from "react";
-import { Select } from "react-md";
+import { Option, Select } from "react-md";
export default function SimpleSelectExample(): ReactElement {
const [value, setValue] = useState("");
return (
<Select
id="simple-select-example"
label="A Label"
placeholder="Choose..."
name="select"
- options={states.map(({ abbreviation, name }) => ({
- label: name,
- value: abbreviation,
- }))}
value={value}
- onChange={(value) => setValue(value)}
- />
+ onChange={(event) => {
+ const value = event.currentTarget.value;
+ setValue(value);
+ }}
+ >
+ {states.map(({ abbreviation, name }) => (
+ <Option key={abbreviation} value={abbreviation}>
+ {name}
+ </Option>
+ ))}
+ </Select>
);
}
✅ update-file-input-props
npx @react-md/codemod v5-to-v6/form/update-file-input-props
The FileInput removed the disableIconSpacing prop since it is no longer required.
import { type ReactElement } from "react";
import { FileInput } from "react-md";
export default function SimpleFileInput(): ReactElement {
return (
<>
<FileInput />
- <FileInput disableIconSpacing />
- <FileInput disableIconSpacing={someFlag} />
- <FileInput disableIconSpacing={false} />
+ <FileInput />
+ <FileInput />
+ <FileInput />
</>
);
}
❌ update-slider-and-range-slider
npx @react-md/codemod v5-to-v6/form/update-slider-and-range-slider
There were a few breaking changes around the Slider and RangeSlider components:
- The
Slideronly requires thevalueandsetValueprops removingminimum,maximum,increment,incrementJump,decrement,decrementJump, andpersist. - The
RangeSliderwas removed since all the functionality has been merged with theSlidercomponent - The
baseIdwas removed in favor ofid,thumbProps.id,thumb1Props.id,thumb2Props.id, etc. - The
labelandlabelPropsprops have been removed in favor of using anaria-labelledbyfor aFieldset+Legend - The
animationDurationprop was removed
In addition, the useSlider + useRangeSlider hooks have updated their API to
match the new components:
- the
useSlideranduseRangeSlideronly accept a single options argument instead of an optional default value followed by an optional options object - the
useSlideruseRangeSliderreturn a single object of props to pass to theSliderinstead of an ordered tuple - the
useSlideranduseRangeSliderno longer support theupdateOnoption as thevalueis always updated immediately - the
useSlideranduseRangeSliderno longer support anonChangecallback
The codemod is only able to handle the simple conversions of renaming
baseId -> id and removing unused props. The diff shown below is a "real
world" conversion with manual updates.
-import { type ReactElement } from "react";
-import { Slider, useSlider } from "react-md";
+import { type ReactElement, useId } from "react";
+import { Fieldset, Legend, Slider, useSlider } from "react-md";
export default function SimpleSlider(): ReactElement | null {
- const [value, controls] = useSlider(20, { min: 0, max: 100 });
- const { setValue } = controls;
+ const legendId = useId();
+ const slider = useSlider({
+ min: 0,
+ max: 100,
+ defaultValue: 20,
+ });
+ const { value, setValue } = slider;
return (
- <>
- <Slider baseId="slider-1-id" label="Horizontal" {...controls} />
- </>
+ <Fieldset>
+ <Legend id={legendId}>Horizontal</Legend>
+ <Slider id="slider-1-id" {...slider} aria-labelledby={legendId} />
+ </Fieldset>
);
}
-import { type ReactElement } from "react";
-import { RangeSlider, useRangeSlider } from "react-md";
+import { type ReactElement, useId } from "react";
+import { Fieldset, Legend, Slider, useRangeSlider } from "react-md";
export default function SimpleSlider(): ReactElement | null {
- const [[minValue, maxValue], controls] = useRangeSlider([20, 60], { min: 0, max: 100 });
- const { setValue } = controls;
+ const legendId = useId();
+ const rangeSlider = useRangeSlider({
+ min: 0,
+ max: 100,
+ defaultValue: [20, 60],
+ });
+ const { rangeValue, setRangeValue: setValue } = rangeSlider;
+ const [minValue, maxValue] = rangeValue;
return (
- <>
- <Slider baseId="slider-1-id" label="Horizontal" {...controls} />
- </>
+ <Fieldset>
+ <Legend id={legendId}>Horizontal</Legend>
+ <Slider id="slider-1-id" {...rangeSlider} aria-labelledby={legendId} />
+ </Fieldset>
);
}
🔧 update-password-props
npx @react-md/codemod v5-to-v6/form/update-file-input-props
The Password component has the following breaking changes:
- the
visibilityStyle,visibilityClassName, andonVisibilityClickprops were removed in favor of thevisibilityPropsobject - the
disableVisibilityandrightChildrenprops were removed in favor of just using aTextFieldinstead - the
getVisibilityIconbehavior was merged with thevisibilityIconprop- ❌ the
GetVisibilityIcontype was renamed toGetPasswordVisibilityIconand returns abooleanif the password type is visible - ❌ so instead of
(type) => type === "password" ? icon1 : icon, use(isPassword) => isPassword ? icon1 : icon2
- ❌ the
+// TODO: Update `GetPasswordVisibilityIcon` references since it provides the `type === "password"` flag instead of the `type` now
import { type ReactElement } from "react";
-import { GetVisibilityIcon, Password } from "react-md";
+import { GetPasswordVisibilityIcon, Password } from "react-md";
-const getVisibilityIcon: GetVisibilityIcon = (type) =>
- type === "password" ? <span id="password-icon" /> : <span id="text-icon" />;
+// this is not auto-converted
+const getVisibilityIcon: GetPasswordVisibilityIcon = (isPassword) =>
+ isPassword ? <span id="password-icon" /> : <span id="text-icon" />;
export default function PasswordExample(): ReactElement {
return (
<>
<Password
id="example-password-field"
label="Password"
placeholder="Super secret password"
/>
<Password
id="example-password-field-2"
label="Password"
placeholder="Super secret password"
- visibilityStyle={{ opacity: 0.5 }}
- visibilityClassName="visibility-class-name"
- onVisibilityClick={(event) => {
- // do something
- }}
- />
+ visibilityProps={{
+ style: { opacity: 0.5 },
+ className: "visibility-class-name",
+
+ onClick: (event) => {
+ // do something
+ }
+ }} />
<Password
id="example-password-field-2"
label="Password"
placeholder="Super secret password"
- getVisibilityIcon={getVisibilityIcon}
+ visibilityIcon={getVisibilityIcon}
/>
</>
);
}
❌ Update Radio and Checkbox Icons
The Radio and Checkbox components no longer use a single icon and hackily
overlay the icon to show the checked/unchecked states.
- the
inputStyleandinputClassNameprops have been removed - the
toggleStyleandtoggleClassNameprops have been removed - the
disableIconOverlayhas been removed since there is no longer an overlay - the
inlineprop has been removed since labels are always rendered inline - the
labelDisabledprop has been removed in favor oflabelProps={{ disabled: labelDisabled }} - the
labelStyleandlabelClassNameprops have been removed in favor oflabelProps
Layout ❌
There is no longer a pre-built layout component so see the new Layout component documentation for the new setup. For convenience, here's a list of the changes:
- The
Configurationcomponent has been removed in favor of the CoreProviders - The
Layoutcomponent has been removed in favor of building the layout manually with the functionality provided by hooks: - useExpandableLayout - this should be used most of the time
and handles the
"toggleable","floating","clipped", and"full-height"variations - useTemporaryLayout - this should be used if the layout
was set to
"temporary"for all viewports - useResizableLayout - this should be used if the user can manually resize the navigation pane on larger viewports
- useLayoutTree - this should be used if the main navigation was
rendered using the
useLayoutNavigationhook andLayoutTree. See the Tree Main Navigation for example usage. - useNavigationExpansion - this should be used if switching to the new Navigation components
- Use a normal
Sheet+ Navigation or Tree to replace theLayoutNavigationcomponent - There is no longer built-in support for mini navigation panels
- The
LayoutMainhas been renamed toMainand no longer handles transitions - The
LayoutAppBarno longer conditionally renders theLayoutNavToggleandLayoutAppBarTitleand should only be used if theAppBarchanges height. Use the normalAppBarfor all other cases - The
LayoutAppBarTitle,LayoutChildren,LayoutCloseNavigationButton,LayoutNavToggle,LayoutNavigation,LayoutNavigationHeader,LayoutProvider,LayoutTree, andMiniLayoutWrappercomponents have been removed - The
defaultMiniNavigationItemsRendereranddefaultNavigationItemRendererrenderers have been removed - The
getLayoutType,isTemporaryLayout,isToggleableLayout,isPersistentLayout,isFullHeightLayout, andisMiniLayoututils have been removed - Most of the Typescript types have been removed
Here's an example diff for converting the Configurable Layout Example from the v5 website.
A custom renderer must be passed to the Tree component if there
are non-tree items in the navigation tree like dividers or subheaders.
+import { AppBar } from "@react-md/core/app-bar/AppBar";
+import { AppBarTitle } from "@react-md/core/app-bar/AppBarTitle";
+import { Button } from "@react-md/core/button/Button";
+import { LayoutNav } from "@react-md/core/layout/LayoutNav";
+import { Main } from "@react-md/core/layout/Main";
+import { useExpandableLayout } from "@react-md/core/layout/useExpandableLayout";
+import { useLayoutTree } from "@react-md/core/layout/useLayoutTree";
+import { Sheet } from "@react-md/core/sheet/Sheet";
+import { Tree } from "@react-md/core/tree/Tree";
+import { type TreeData } from "@react-md/core/tree/types";
import {
HomeSVGIcon,
SecuritySVGIcon,
SettingsSVGIcon,
ShareSVGIcon,
SnoozeSVGIcon,
StarSVGIcon,
StorageSVGIcon,
} from "@react-md/material-icons";
import { type ReactElement, useState } from "react";
-import {
- DEFAULT_DESKTOP_LAYOUT,
- DEFAULT_LANDSCAPE_TABLET_LAYOUT,
- DEFAULT_PHONE_LAYOUT,
- DEFAULT_TABLET_LAYOUT,
- Layout,
- type LayoutNavigationTree,
- type SupportedPhoneLayout,
- type SupportedTabletLayout,
- type SupportedWideLayout,
- useLayoutNavigation,
-} from "react-md";
-import { ConfigurationForm } from "./ConfigurationForm";
import { CurrentChildren } from "./CurrentChildren";
-const navItems: LayoutNavigationTree = {
+const navItems: TreeData = {
"/": {
itemId: "/",
+ href: "/",
parentId: null,
children: "Home",
leftAddon: <HomeSVGIcon />,
},
"/route-1": {
itemId: "/route-1",
+ href: "/route-1",
parentId: null,
children: "Route 1",
leftAddon: <StarSVGIcon />,
},
"/divider-1": {
itemId: "/divider-1",
parentId: null,
divider: true,
isCustom: true,
},
"/route-2": {
itemId: "/route-2",
+ href: "/route-2",
parentId: null,
children: "Route 2",
leftAddon: <ShareSVGIcon />,
},
"/route-2-1": {
itemId: "/route-2-1",
+ href: "/route-2-1",
parentId: "/route-2",
children: "Route 2-1",
leftAddon: <SettingsSVGIcon />,
},
"/route-2-2": {
itemId: "/route-2-2",
+ href: "/route-2-2",
parentId: "/route-2",
children: "Route 2-2",
leftAddon: <StorageSVGIcon />,
},
"/route-2-3": {
itemId: "/route-2-3",
+ href: "/route-2-3",
parentId: "/route-2",
children: "Route 2-3",
leftAddon: <SecuritySVGIcon />,
},
"/route-3": {
itemId: "/route-3",
+ href: "/route-3",
parentId: null,
children: "Route 3",
leftAddon: <SnoozeSVGIcon />,
},
"/route-4": {
itemId: "/route-4",
+ href: "/route-4",
parentId: null,
children: "Route 4",
},
};
export default function Demo(): ReactElement {
- const [phoneLayout, setPhoneLayout] =
- useState<SupportedPhoneLayout>(DEFAULT_PHONE_LAYOUT);
- const [tabletLayout, setTabletLayout] = useState<SupportedTabletLayout>(
- DEFAULT_TABLET_LAYOUT
- );
- const [landscapeTabletLayout, setLandscapeTabletLayout] =
- useState<SupportedTabletLayout>(DEFAULT_LANDSCAPE_TABLET_LAYOUT);
- const [desktopLayout, setDesktopLayout] = useState<SupportedWideLayout>(
- DEFAULT_DESKTOP_LAYOUT
- );
- const [largeDesktopLayout, setLargeDesktopLayout] =
- useState<SupportedWideLayout>(DEFAULT_DESKTOP_LAYOUT);
-
const [selectedId, setSelectedId] = useState("/");
+ const tree = useLayoutTree({
+ navItems,
+ pathname: selectedId,
+ });
+ const {
+ temporary,
+ persistent,
+ temporaryNavProps,
+ navToggleProps,
+ appBarProps,
+ mainProps,
+ expandableNavProps,
+ } = useExpandableLayout({
+ pathname: selectedId,
+ fullHeightNav: "static",
+ });
return (
- <Layout
- id="configurable-layout"
- title="Configurable Layout Title"
- navHeaderTitle="Another Title"
- phoneLayout={phoneLayout}
- tabletLayout={tabletLayout}
- landscapeTabletLayout={landscapeTabletLayout}
- desktopLayout={desktopLayout}
- treeProps={{
- ...useLayoutNavigation(navItems, selectedId),
- onItemSelect: setSelectedId,
- }}
- // this is only required since I already have a main element due to the
- // documentation site's Layout component
- mainProps={{ component: "div" }}
- >
- <CurrentChildren route={selectedId} />
- <ConfigurationForm
- phoneLayout={phoneLayout}
- setPhoneLayout={setPhoneLayout}
- tabletLayout={tabletLayout}
- setTabletLayout={setTabletLayout}
- landscapeTabletLayout={landscapeTabletLayout}
- setLandscapeTabletLayout={setLandscapeTabletLayout}
- desktopLayout={desktopLayout}
- setDesktopLayout={setDesktopLayout}
- largeDesktopLayout={largeDesktopLayout}
- setLargeDesktopLayout={setLargeDesktopLayout}
- />
- </Layout>
+ <>
+ <AppBar {...appBarProps}>
+ <Button {...navToggleProps} />
+ <AppBarTitle>Configurable Layout Title</AppBarTitle>
+ </AppBar>
+ {persistent && (
+ <LayoutNav {...expandableNavProps}>
+ <AppBar>
+ <AppBarTitle>Another Title</AppBarTitle>
+ </AppBar>
+ <Tree
+ {...tree}
+ aria-label="Navigation"
+ toggleTreeItemSelection={setSelectedId}
+ />
+ </LayoutNav>
+ )}
+ {temporary && (
+ <Sheet {...temporaryNavProps}>
+ <Tree
+ {...tree}
+ aria-label="Navigation"
+ toggleTreeItemSelection={setSelectedId}
+ />
+ </Sheet>
+ )}
+ <Main {...mainProps}>
+ <CurrentChildren route={selectedId} />
+ </Main>
+ </>
);
}
Link
🔧 update-link-props
npx @react-md/codemod v5-to-v6/link/update-link-props
The Link component updated the following props:
preventMaliciousTargetwas removed since browsers implement this behavior automatically nowflexCenteredwas renamed toflex- the
componentprop was removed in favor of using thelinkutility function instead
return (
<>
<Link href="#">Link 1</Link>
- <Link href="#" flexCentered>
+ <Link href="#" flex>
Link 1
</Link>
- <Link href="#" flexCentered={flexCentered}>
- Link 1
- </Link>
- <Link href="#" preventMaliciousTarget={false}>
+ <Link href="#" flex={flexCentered}>
Link 1
</Link>
+ <Link href="#">Link 1</Link>
</>
);
}
List
There are a few breaking changes for the list components:
- The
SimpleListItemwas removed in favor of using an<li>with theListItemChildrencomponent - The
ListItemandListItemLinkremoved support for the ripple props and updated the following props:- The
forceAddonWrapprop was removed in favor of theleftAddonForceWrapandrightAddonForceWrap - The
textChildrenprop was renamed todisableTextChildren
- The
- The
ListItemLinkrenamedcomponenttoas
For Typescript users, the ListItemLink no longer allows
{ [key: string]: unknown } when the as component is provided.
🔧 update-list-item-props
npx @react-md/codemod v5-to-v6/list/update-list-item-props
Update textChildren prop:
import { type ReactElement } from "react";
import { ListItem } from "react-md";
export default function Example(): ReactElement {
return (
<>
- <ListItem textChildren>Hello, world!</ListItem>
- <ListItem textChildren={false}>Hello, world!</ListItem>
- <ListItem textChildren={true}>Hello, world!</ListItem>
- <ListItem textChildren={textChildren}>Hello, world!</ListItem>
+ <ListItem>Hello, world!</ListItem>
+ <ListItem disableTextChildren>Hello, world!</ListItem>
+ <ListItem>Hello, world!</ListItem>
+ <ListItem disableTextChildren={!textChildren}>Hello, world!</ListItem>
</>
);
}
Remove ripple props:
import { type ReactElement } from "react";
import { ListItem } from "react-md";
import styles from "./styles.module.scss";
export default function Example(): ReactElement {
return (
<ListItem
onClick={() => {
// do something
}}
disableRipple
- disableProgrammaticRipple
- disableEnterClick
- disableSpacebarClick
- disablePressedFallback
- enablePressedAndRipple
- rippleTimeout={100}
- rippleClassName={styles.ripple}
- rippleClassNames={{ enter: "", exit: "" }}
- rippleContainerClassName="example"
>
Hello, world!
</ListItem>
);
}
Rename component to as:
export default function Example(): ReactElement {
return (
<>
- <ListItemLink component={CustomLink} to="/some-path">
+ <ListItemLink as={CustomLink} to="/some-path">
Link 1
</ListItemLink>
- <ListItemLink component="a" href="/some-path">
+ <ListItemLink as="a" href="/some-path">
Link 2
</ListItemLink>
</>
Remove SimpleListItem:
import type { ReactElement } from "react";
import cn from "classnames";
-import { FavoriteSVGIcon, List, SimpleListItem } from "react-md";
+import { FavoriteSVGIcon, List, ListItemChildren } from "react-md";
import people from "./people";
@@ -12,33 +12,35 @@ export default function Demo(): ReactElement {
<Container>
<List>
{people.slice(0, 10).map((name) => (
- <SimpleListItem
+ <li
key={name}
className={cn(styles.item, styles.dotted, styles.margin)}
>
- {name}
- </SimpleListItem>
+ <ListItemChildren>{name}</ListItemChildren>
+ </li>
))}
</List>
<List className={styles.ordered}>
{people.slice(11, 20).map((name) => (
- <SimpleListItem key={name} className={cn(styles.item, styles.margin)}>
- {name}
- </SimpleListItem>
+ <li key={name} className={cn(styles.item, styles.margin)}>
+ <ListItemChildren>{name}</ListItemChildren>
+ </li>
))}
</List>
<List>
- <SimpleListItem
- primaryText={<span>Primary Text</span>}
- secondaryText={
- <span className={styles.secondary}>Secondary Text</span>
- }
- leftAddon={<FavoriteSVGIcon />}
- rightAddon={<img alt="" src="https://example.com/image.jpeg" />}
- rightAddonType="media"
- >
- Other children
- </SimpleListItem>
+ <li>
+ <ListItemChildren
+ primaryText={<span>Primary Text</span>}
+ secondaryText={
+ <span className={styles.secondary}>Secondary Text</span>
+ }
+ leftAddon={<FavoriteSVGIcon />}
+ rightAddon={<img alt="" src="https://example.com/image.jpeg" />}
+ rightAddonType="media"
+ >
+ Other children
+ </ListItemChildren>
+ </li>
</List>
</Container>
);
Media
There are a few breaking changes for the media components since the new objectFit class name utility handles most use-cases now.
- the
MediaContainerwas renamed toResponsiveItem- the
heightandwidthprops were removed in favor of theaspectRatiopropaspectRatio={`${width}-${height}}
- the
autoprop was removed in favor of theresponsivepropauto->responsive="auto"(this was the previous default)auto={false}->responsive="manual"
- the
MediaContainerPropswas renamed toResponsiveItemProps
- the
- the
MediaOverlaywas renamed toResponsiveItemOverlay- the
MediaOverlayPropswas renamed toResponsiveItemOverlayProps - the
MediaOverlayPositionwas renamed toResponsiveItemOverlayPosition
- the
🔧 update-media-components
npx @react-md/codemod v5-to-v6/media/update-media-components
import type { ReactElement } from "react";
-import { MediaContainer, MediaOverlay, Typography, type MediaOverlayPosition } from "react-md";
+import { ResponsiveItem, ResponsiveItemOverlay, Typography, ResponsiveItemOverlayPosition } from "react-md";
import styles from "./Container.module.scss";
-const positions: MediaOverlayPosition[] = [
+const positions: ResponsiveItemOverlayPosition[] = [
"top",
"right",
"bottom",
"left",
"middle",
"center",
"absolute-center",
];
export default function WithOverlay(): ReactElement {
return (
<>
{positions.map((position, i) => (
- <MediaContainer
+ <ResponsiveItem
key={position}
id={`overlay-container-${i}`}
- height={9}
- width={16}
className={styles.container}
- >
+ aspectRatio="16-9">
<img
src={`https://picsum.photos/800/800?image=43${i}`}
alt=""
aria-describedby={`overlay-container-overlay-${i}`}
/>
- <MediaOverlay
+ <ResponsiveItemOverlay
id={`overlay-container-overlay-${i}`}
position={position}
>
<Typography
type="headline-5"
margin="none"
align={
["left", "right", "center"].includes(position)
? "center"
: undefined
}
>
This is a random picture!
</Typography>
- </MediaOverlay>
- </MediaContainer>
+ </ResponsiveItemOverlay>
+ </ResponsiveItem>
))}
</>
);
}
Menu
The majority of the menu component changes were internal, but there are a few breaking changes that can mostly be automated through the codemod.
✅ replace-menu-item-link
npx @react-md/codemod v5-to-v6/menu/replace-menu-item-link
The MenuItemLink was removed in favor of just using a ListItemLink with
role="menuitem". All the other transforms from
update-list-item-props must then be applied as well.
This codemod will convert to a ListItemLink and then handle the
ListItemLink migration.
import type { ReactElement } from "react";
-import { DropdownMenu, MenuItemLink, Link } from "react-md";
+import { DropdownMenu, Link, ListItemLink } from "react-md";
export default function SimpleExample(): ReactElement {
return (
<DropdownMenu buttonChildren="Options...">
- <MenuItemLink href="/link-1" component={Link}>
+ <ListItemLink href="/link-1" as={Link} role="menuitem">
Link 1
- </MenuItemLink>
- <MenuItemLink
+ </ListItemLink>
+ <ListItemLink
href="#link-2"
liProps={{ className: "container-class-name" }}
className="link-class-name"
- >
+ role="menuitem">
Link 2
- </MenuItemLink>
+ </ListItemLink>
</DropdownMenu>
);
}
🔧 update-use-context-menu-api
npx @react-md/codemod v5-to-v6/menu/update-use-context-menu-api
The useContextMenu hook was updated for the latest Menu API and only supports
the following options: anchor, menuLabel, preventScroll, and
onContextMenu.
In addition, the hook only returns: visible, setVisible, menuProps, and
onContextMenu. The onContextMenu type definition has also been updated to
better support triggering the context menu from different element types.
Here is an example diff of the most common changes:
import ContentCopyIcon from "@react-md/material-icons/ContentCopyIcon";
import ContentCutIcon from "@react-md/material-icons/ContentCutIcon";
import ContentPasteIcon from "@react-md/material-icons/ContentPasteIcon";
import type { ReactElement } from "react";
import { Menu, MenuItem, TextArea, useContextMenu } from "react-md";
export default function SimpleContextMenu(): ReactElement {
- const { menuRef, menuProps, onContextMenu } = useContextMenu();
+ const {
+ menuProps,
+ onContextMenu
+ } = useContextMenu();
return (
<>
<TextArea
id="simple-context-menu-area"
onContextMenu={onContextMenu}
placeholder="Right click me!"
/>
- <Menu {...menuProps} ref={menuRef}>
+ <Menu {...menuProps}>
<MenuItem leftAddon={<ContentCutIcon />}>Cut</MenuItem>
<MenuItem leftAddon={<ContentCopyIcon />}>Copy</MenuItem>
<MenuItem leftAddon={<ContentPasteIcon />}>Paste</MenuItem>
</Menu>
</>
);
}
Here is an example diff of all the changes and what the codemod can support:
+// TODO: The `useContextMenu` no longer supports the `onFixedPositionScroll` callback
+// TODO: The `useContextMenu` no longer supports the `onFixedPositionResize` callback
+// TODO: The `useContextMenu` no longer returns `setCoords`. Manually provide an `initialX` and `initialY` to the `Menu` instead
+// TODO: The `useContextMenu` no longer returns `menuNodeRef` and must be implemented manually
import ContentCopyIcon from "@react-md/material-icons/ContentCopyIcon";
import ContentCutIcon from "@react-md/material-icons/ContentCutIcon";
import ContentPasteIcon from "@react-md/material-icons/ContentPasteIcon";
import type { ReactElement } from "react";
import { Menu, MenuItem, TextArea, TOP_RIGHT_ANCHOR, useContextMenu } from "react-md";
export default function ComplexContextMenu(): ReactElement {
const onEntering = (): void => {
// entering
};
const {
- menuRef,
- menuNodeRef,
menuProps,
onContextMenu,
- setCoords,
visible,
- setVisible,
+ setVisible
} = useContextMenu({
anchor: TOP_RIGHT_ANCHOR,
- baseId: "context-menu",
- closeOnResize: true,
- closeOnScroll: true,
- disableFocusOnMount: true,
- disableFocusOnUnmount: true,
- getFixedPositionOptions: () => ({}),
- horizontal: false,
menuLabel: "Context Menu",
- menuitem: false,
+
onContextMenu(event) {
// onContextMenu
},
- onEnter() {
- // enter
- },
- onEntering,
- onEntered: () => {
- // entered
- },
- onExited: () => {
- // exited
- },
- onFixedPositionResize: (event) => {
- // resized
- },
- onFixedPositionScroll: (event, data) => {
- // scroll
- },
- preventScroll: true,
- style: {
- background: "orange",
- },
+
+ preventScroll: true
});
return (
<>
<TextArea
id="simple-context-menu-area"
onContextMenu={onContextMenu}
placeholder="Right click me!"
/>
- <Menu {...menuProps} ref={menuRef}>
+ <Menu
+ {...menuProps}
+ id="context-menu"
+ closeOnResize={true}
+ closeOnScroll={true}
+ getFixedPositionOptions={() => ({})}
+ horizontal={false}
+ onEnter={() => {
+ // enter
+ }}
+ onEntering={onEntering}
+ onEntered={() => {
+ // entered
+ }}
+ onExited={() => {
+ // exited
+ }}
+ style={{
+ background: "orange"
+ }}
+ isFocusTypeDisabled={type => {
+ if (type === "mount") {
+ return true;
+ }
+
+ if (type === "unmount") {
+ return true;
+ }
+
+ return false;
+ }}>
<MenuItem leftAddon={<ContentCutIcon />}>Cut</MenuItem>
<MenuItem leftAddon={<ContentCopyIcon />}>Copy</MenuItem>
<MenuItem leftAddon={<ContentPasteIcon />}>Paste</MenuItem>
</Menu>
</>
);
}
Overlay
🔧 update-overlay-props
npx @react-md/codemod v5-to-v6/overlay/update-overlay-props
The Overlay updated the following props:
hiddenwas renamed tonoOpacityso the nativehiddenattribute can be usedonRequestClosewas removed in favor of using theonClickhandler
<>
<Overlay
visible={visible}
- onRequestClose={() => {
+ onClick={() => {
setVisible(false);
}}
/>
- <Overlay visible={visible2} onRequestClose={hide} />
+ <Overlay visible={visible2} onClick={hide} />
<Overlay
visible={visible2}
- onRequestClose={() => {
+ onClick={() => {
hide();
}}
- hidden
+ noOpacity
/>
<Overlay
visible={visible}
- onRequestClose={() => {
+ onClick={() => {
setVisible(false);
}}
clickable
@@ -39,7 +39,7 @@ export default function Example({ handleClick }: ExampleProps): ReactElement {
onClick={(event) => {
handleClick?.(event);
}}
- onRequestClose={() => {
+ onClick={() => {
setVisible(false);
}}
clickable
Portal
🔧 use-new-portal-api
npx @react-md/codemod v5-to-v6/portal/use-new-portal-api
Most of the Portal changes cannot be automated due to the new portal
container behavior, but should not affect most codebases since it is mostly an
internal component. The changes are:
- The
intoandintoIdprops were removed from thePortalcomponent- Use the new
PortalContainerProviderinstead
- Use the new
- The
portal,portalInto, andportalIntoIdconvenience props were removed from all react-md components that used thePortal- Use the new
PortalContainerProviderinstead
- Use the new
- the
PortalIntotype was renamed toPortalContainerand no longer supports functions for getting the portal node - the
ConditionalPortalwas removed in favor of using thedisabledprop on thePortalinstead
+// TODO: Check how the Portal prop `intoId` was used since it is no longer supported.
+// TODO: Check how the Portal prop `into` was used since it is no longer supported.
import { type ReactElement } from "react";
import { Portal } from "react-md";
export default function Example(): ReactElement {
return (
<>
- <Portal into={something}>Content</Portal>
- <Portal intoId="some-id">Content</Portal>
- <Portal into={somethingElse}>Content</Portal>
- <Portal intoId="some-other-id">Content</Portal>
+ <Portal>Content</Portal>
+ <Portal>Content</Portal>
+ <Portal>Content</Portal>
+ <Portal>Content</Portal>
</>
);
}
-import { PortalInto } from "react-md";
+// TODO: The `PortalContainer` replaced the `PortalInto` type but does not support functions. Double check the usage before removing this line.
+import { PortalContainer } from "react-md";
export interface ExampleProps {
- portalInto: PortalInto;
+ portalInto: PortalContainer;
}
import { type ReactElement } from "react";
-import { ConditionalPortal } from "react-md";
+import { Portal } from "react-md";
export default function Example(): ReactElement {
return (
<>
- <ConditionalPortal portal={false}>Content</ConditionalPortal>
- <ConditionalPortal>Hello, world!</ConditionalPortal>
- <ConditionalPortal>
+ <Portal disabled>Content</Portal>
+ <Portal disabled>Hello, world!</Portal>
+ <Portal disabled>
<div>Hello, world!</div>
- </ConditionalPortal>
+ </Portal>
</>
);
}
In addition, the ConditionalPortal was removed.
Progress
✅ update-circular-progress-props
npx @react-md/codemod v5-to-v6/progress/update-circular-progress-props
The CircularProgress updated the following props:
smallwas renamed todensecenteredwas renamed todisableCenteredmaxRotationwas removed
export default function Example(): ReactElement {
return (
<>
- <CircularProgress id="some-id-1" small />
- <CircularProgress id="some-id-2" small={false} />
- <CircularProgress id="some-id-3" centered />
- <CircularProgress id="some-id-4" centered={false} />
- <CircularProgress id="some-id-5" maxRotation={360 * 1.5} />
+ <CircularProgress id="some-id-1" dense />
+ <CircularProgress id="some-id-2" />
+ <CircularProgress id="some-id-3" />
+ <CircularProgress id="some-id-4" disableCentered />
+ <CircularProgress id="some-id-5" />
</>
);
}
Sheet 🎉
States ❌
The @react-md/states packages was mostly internal so codemods will not be provided
to update this package.
Replace StatesConnfig context provider
The StatesConfig context provider has been removed in favor of the new
INTERACTION_CONFIG object. Here is an example on how to update the disableRipple
behavior:
+import { INTERACTION_CONFIG } from "@react-md/core/interaction/config";
-import { StatesConfig } from "react-md";
import { RestOfTheApp } from "./RestOfTheApp.jsx";
+INTERACTION_CONFIG.mode = "none";
export default function App() {
return (
- <StatesConfig disableRipple>
<RestOfTheApp />
- </StatesConfig>
);
}
Replace useInteractionStates with useElementInteraction
If the useInteractionStates hook was used, switch to the
useElementInteraction hook.
import cn from "classnames";
import { type ButtonHTMLAttributes, type ReactElement } from "react";
-import { type InteractionStatesOptions, useInteractionStates } from "react-md";
+import { useElementInteraction } from "react-md";
import styles from "./CustomComponent.module.scss";
-interface CustomButtonProps
- extends ButtonHTMLAttributes<HTMLButtonElement>,
- Omit<InteractionStatesOptions, "handlers"> {}
+interface CustomButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
+ disableRipple?: boolean;
+}
function CustomButton({
disabled,
disableRipple,
- disableSpacebarClick,
- disableProgrammaticRipple,
- className: propClassName,
+ className,
children,
+ onBlur,
+ onClick,
onKeyDown,
onKeyUp,
onMouseDown,
onMouseUp,
onMouseLeave,
+ onDragStart,
onTouchStart,
onTouchMove,
onTouchEnd,
...props
}: CustomButtonProps): ReactElement {
- const { ripples, handlers, className } = useInteractionStates({
- handlers: {
+ const { ripples, handlers, pressed, pressedClassName } =
+ useElementInteraction({
+ onBlur,
+ onClick,
onKeyDown,
onKeyUp,
onMouseDown,
onMouseUp,
onMouseLeave,
+ onDragStart,
onTouchStart,
onTouchMove,
onTouchEnd,
- },
- disabled,
- disableRipple,
- disableSpacebarClick,
- disableProgrammaticRipple,
- className: propClassName,
- });
+ disabled,
+ mode: disableRipple ? "none" : undefined,
+ });
return (
<button
{...props}
type="button"
- className={cn(styles.button, className)}
+ className={cn(
+ styles.button,
+ className,
+ pressedClassName,
+ pressed && styles.pressed
+ )}
{...handlers}
>
{children}
{ripples}
</button>
);
}
Table
🔧 update-table-cell-props
npx @react-md/codemod v5-to-v6/table/update-table-cell-props
The TableCell updated the following props:
colSpanno longer supports a value of100%or any non-numbers- ❌ cannot be automatically updated and must be set to the number of columns in the table instead
disablePaddingwas removed in favor of the newpaddingprop
+// TODO: Update the `TableCell` to have a `colSpan` number equal to the total number of columns in the table
import type { ReactElement } from "react";
import {
Table,
@@ -33,7 +34,7 @@ export default function StickyColumnsPart3(): ReactElement {
</TableBody>
<TableFooter sticky>
<TableRow>
- <TableCell colSpan="100%">
+ <TableCell>
This is the sticky footer content. Any components can be rendered
inside.
</TableCell>
- <TableCell disablePadding className="example">
+ <TableCell padding="none" className="example">
Content
</TableCell>
🔧 update-table-checkbox-props
npx @react-md/codemod v5-to-v6/table/update-table-checkbox-props
The TableCheckbox no longer supports the cellId prop in favor of the id prop.
export function Example(props): ReactElement {
return (
<>
- <TableCheckbox {...props} cellId="some-unique-id" />
+ <TableCheckbox {...props} />
</>
);
}
✅ caption-to-typography
npx @react-md/codemod v5-to-v6/table/caption-to-typography
The Caption component was removed in favor of using the existing Typography
component.
@@ -1,11 +1,11 @@
import type { ReactElement } from "react";
import {
- Caption,
Table,
TableBody,
TableCell,
TableHeader,
TableRow,
+ Typography,
} from "react-md";
import styles from "./DefaultStyles.module.scss";
@@ -13,7 +13,7 @@ import styles from "./DefaultStyles.module.scss";
export default function DefaultStyles(): ReactElement {
return (
<Table className={styles.centered}>
- <Caption>This is a caption</Caption>
+ <Typography type="caption">This is a caption</Typography>
<TableHeader>
<TableRow>
<TableCell>Column 1</TableCell>
Tabs
There is a completely new tabs API which will require manual changes. First,
the TabsManager and Tabs components have been removed and should be
replaced by:
- the
useTabshook for controlling the active tab state - the
TabListcomponent for basic styling and keyboard behavior - the Tab component for rendering each tab
The TabPanels and TabPanel components have been removed in favor of the
getTabPanelsProps and getTabPanelProps returned by the useTabs hook. The
previous slide transition can be implemented using the
SlideContainer and Slide components.
The Slide component behaves like the TabPanel with the
persistent flag enabled. If the tab panels should be unmounted while not
active, enable the temporary flag on the Slide.
To migrate to the new API, the step are as follows:
- Remove the
TabsManagercomponent and replace with theuseTabshook- the
tabsIdcan be removed or added as thebaseIdhook option - the
defaultActiveIndex,stacked, andiconAftercan be moved as hook options - the
activeIndexandonActiveIndexChangemust be provided together and will be theactiveIndex/setActiveIndexhook options - this hook returns
getTabListProps,getTabPanelsProps,getTabPanelProps, andgetTabPropswhich will be required for the new components
- the
- Replace the
Tabscomponent with theTabsListcomponent- The
automaticprop has been removed in favor ofactivationMode="automatic"oractivationMode="manual"(default) - The
orientationprop has been removed in favor ofvertical
- The
- Render each tab as a child of the
TabListusing the Tab component- The Tab component should be rendered with
{...getTabProps(index)} - The Tab component still supports the
icon,stacked, andiconAfterprops
- The Tab component should be rendered with
- Replace the
TabPanelscomponent with theSlideContainercomponent- Add
{...getTabPanelsProps()}to theSlideContainer - If the
disableScrollFixprop was enabled, add it to theuseTabshook instead - Remove the
disableTransitionprop if it existed - Remove the
persistentprop if it existed
- Add
- Replace the
TabPanelcomponent with theSlidecomponent- Add
{...getTabPanelProps(panelIndex)}to theSlidecomponent - If the transition should be disabled, add
timeout={0} - If the panel should unmount while not visible, enable the
temporaryprop
- Add
import type { ReactElement } from "react";
-import { TabPanel, TabPanels, Tabs, TabsManager, Typography } from "react-md";
+import {
+ Slide,
+ SlideContainer,
+ Tab,
+ TabList,
+ Typography,
+ useTabs,
+} from "react-md";
const tabs = ["Tab 1", "Tab 2", "Tab 3"];
const stacked = false;
const iconAfter = false;
const defaultActiveIndex = 0;
export default function Demo(): ReactElement {
+ const { getTabProps, getTabListProps, getTabPanelProps, getTabPanelsProps } =
+ useTabs({
+ baseId: "basic-usage-tabs",
+ stacked: stacked,
+ iconAfter: iconAfter,
+ defaultActiveIndex: defaultActiveIndex,
+ });
+
return (
- <TabsManager
- tabs={tabs}
- tabsId="basic-usage-tabs"
- stacked={stacked}
- iconAfter={iconAfter}
- defaultActiveIndex={defaultActiveIndex}
- >
- <Tabs />
- <TabPanels>
- <TabPanel>
+ <>
+ <TabList {...getTabListProps()}>
+ {tabs.map((tab, i) => (
+ <Tab {...getTabProps(i)}>{tab}</Tab>
+ ))}
+ </TabList>
+ <SlideContainer {...getTabPanelsProps()}>
+ <Slide {...getTabPanelProps(0)}>
<Typography type="headline-4">Panel 1</Typography>
- </TabPanel>
- <TabPanel>
+ </Slide>
+ <Slide {...getTabPanelProps(1)}>
<Typography type="headline-4">Panel 2</Typography>
- </TabPanel>
- <TabPanel>
+ </Slide>
+ <Slide {...getTabPanelProps(2)}>
<Typography type="headline-4">Panel 3</Typography>
- </TabPanel>
- </TabPanels>
- </TabsManager>
+ </Slide>
+ </SlideContainer>
+ </>
);
}
❌ update-tabs-api
npx @react-md/codemod v5-to-v6/tabs/update-tabs-api
This codemod will try its best to convert tabs to the latest API but will
really only work if the TabsManager, Tabs, TabPanels, and TabPanel
components were defined in the same file.
-import type { ReactElement } from "react";
-import { TabPanel, TabPanels, Tabs, TabsManager, Typography } from "react-md";
+import { ReactElement, ReactNode } from "react";
+import {
+ Slide,
+ SlideContainer,
+ Tab,
+ TabList,
+ TabProps,
+ Typography,
+ useTabs,
+} from "react-md";
const tabs = ["Tab 1", "Tab 2", "Tab 3"];
export default function Demo(): ReactElement {
+ const { getTabProps, getTabListProps, getTabPanelProps, getTabPanelsProps } =
+ useTabs({
+ baseId: "basic-usage-tabs",
+ });
+
return (
- <TabsManager tabs={tabs} tabsId="basic-usage-tabs">
- <Tabs />
- <TabPanels>
- <TabPanel>
+ <>
+ <TabList {...getTabListProps()}>
+ {tabs.map((tab, i) => {
+ const tabProps = getTabProps(i);
+ let children: ReactNode;
+ let overrides: TabProps | undefined;
+
+ if (typeof tab !== "string" && "children" in tab) {
+ children = tab.children;
+
+ const {
+ children: _c,
+ contentStyle: _cs,
+ contentClassName: _ccn,
+ ...stillValidProps
+ } = tab;
+
+ overrides = stillValidProps;
+ } else {
+ children = tab;
+ }
+
+ return (
+ <Tab {...tabProps} {...overrides} key={tabProps.id}>
+ {children}
+ </Tab>
+ );
+ })}
+ </TabList>
+ <SlideContainer {...getTabPanelsProps()}>
+ <Slide {...getTabPanelProps(0)}>
<Typography type="headline-4">Panel 1</Typography>
- </TabPanel>
- <TabPanel>
+ </Slide>
+ <Slide {...getTabPanelProps(1)}>
<Typography type="headline-4">Panel 2</Typography>
- </TabPanel>
- <TabPanel>
+ </Slide>
+ <Slide {...getTabPanelProps(2)}>
<Typography type="headline-4">Panel 3</Typography>
- </TabPanel>
- </TabPanels>
- </TabsManager>
+ </Slide>
+ </SlideContainer>
+ </>
);
}
Transition
🔧 update-scale-transition
npx @react-md/codemod v5-to-v6/transition/update-scale-transition
The ScaleTransition component no longer supports the portal, portalInto, and
portalIntoId props.
+// TODO: The `portalInto` for the `ScaleTransition` cannot be converted automatically.
+// TODO: The `portalIntoId` for the `ScaleTransition` cannot be converted automatically.
import { type ReactElement } from "react";
-import { ScaleTransition } from "react-md";
+import { Portal, ScaleTransition } from "react-md";
import SomeComponent from "./SomeComponent";
export default function Example(): ReactElement {
return (
<>
- <ScaleTransition portalIntoId="some-id" transitionIn={transitionIn}>
- <SomeComponent />
- </ScaleTransition>
+ <Portal>
+ <ScaleTransition transitionIn={transitionIn}>
+ <SomeComponent />
+ </ScaleTransition>
+ </Portal>
</>
);
}
Tree
There were a lot of breaking changes for the Tree API and cannot be fully
converted automatically for complex implementations. The list of changes are:
- The
Treecomponent updated the following props:- the
itemRendererandgetItemPropshave been removed in favor of the newrenderer labelKey,valueKey,getItemKey, andgetItemValuewere removedonItemExpansionwas renamed totoggleTreeItemExpansiononMultiItemExpansionwas renamed toexpandMultipleTreeItemsonItemSelectionwas renamed totoggleTreeItemSelectiononMultiItemSelectionwas renamed toexpandMultipleTreeItems
- the
- The
Treecomponent no longer forwards refs and the newtreeRefprop should be used instead defaultTreeItemRendererwas removed in favor of the newDefaultTreeItemRenderercomponentuseTreeItemExpansionwas renamed touseTreeExpansionand the returned value was updated so that:expandedIdsis now aReadonlySet<string>instead ofstring[]onItemExpansionwas renamed totoggleTreeItemExpansiononMultiItemExpansionwas renamed toexpandMultipleTreeItems
useTreeItemSelectionwas renamed touseTreeSelectionand the returned value was updated so that:selectedIdsis now aReadonlySet<string>instead ofstring[]onItemSelectionwas renamed totoggleTreeItemSelectiononMultiItemSelectionwas renamed toexpandMultipleTreeItems
Typescript type changes:
TreeItemExpansiontype was renamed toTreeExpansionTreeItemSelectiontype was renamed toTreeSelectionTreeItemIdwas removed in favor of just using astringTreeItemIdswas renamed toTreeItemNodeExpandedIdsandSelectedIdswere removed in favor ofTreeItemIdSetGetItemPropsandTreeItemRendererwas removed in favor ofTreeItemRendererProps
The new renderer prop on the Tree should be a component that accepts the
following props:
item- the current tree itemdata- the full tree dataparents- an ordered list of parent tree itemschildren- any content to render if the currentitemhas child items
One of the main differences with this new API is that the expanded,
selected, and focused states are no longer provided by default since it is
handled by the TreeItem component internally. Otherwise, the TreeItem no
longer supports the expanderLeft icon so icons must be provided on the Tree
component itself using the TreeProvider around each TreeItem.
See the Custom Tree Item Renderer example for an in-depth example using the API or the diff shown below for convert-get-item-props
All the following codemods can be run at once using:
npx @react-md/codemod v5-to-v6/tree/everything
@@ -1,13 +1,21 @@
+// TODO: The `getItemProps` have been removed from the `Tree` component and need to be manually changed. The `renderer` prop is the closest in functionality.
import cn from "classnames";
-import type { ReactElement, ReactNode } from "react";
-import type { GetItemProps, TreeData, TreeItemIds } from "react-md";
+import { ReactElement, ReactNode, useId } from "react";
+
import {
ArrowDropDownSVGIcon,
+ DefaultTreeItemRenderer,
FolderOpenSVGIcon,
FolderSVGIcon,
Tree,
- useTreeItemExpansion,
- useTreeItemSelection,
+ TreeData,
+ TreeItemNode,
+ TreeItemRendererProps,
+ TreeProvider,
+ useKeyboardMovementContext,
+ useTreeContext,
+ useTreeExpansion,
+ useTreeSelection,
} from "react-md";
import Html5SVGIcon from "icons/Html5SVGIcon";
@@ -19,7 +27,7 @@ import createIdGenerator from "./createIdGenerator";
import styles from "./CustomizingTreeItems.module.scss";
type ItemType = "folder" | "html" | "typescript" | "scss" | "text";
-interface Item extends TreeItemIds {
+interface Item extends TreeItemNode {
name: string;
type: ItemType;
}
@@ -28,7 +36,7 @@ const uuid = createIdGenerator("custom-tree-items");
const createItem = (
name: string,
type: ItemType,
- parentId: string | null = null
+ parentId: string | null = null,
): Item => {
const itemId = uuid();
return {
@@ -57,11 +65,25 @@ const data = [
index,
].reduce<TreeData<Item>>(
(tree, item) => ({ ...tree, [item.itemId]: item }),
- {}
+ {},
);
-const getItemProps: GetItemProps<Item> = (item) => {
- const { selected, focused, expanded, type } = item;
+// TODO: This might need to be renamed to match normal component naming conventions
+const getItemProps = function Renderer(
+ props: TreeItemRendererProps<Item>,
+): ReactElement {
+ const { item } = props;
+
+ const { type, itemId } = item;
+
+ const context = useTreeContext();
+
+ const { expandedIds, selectedIds } = context;
+
+ const expanded = expandedIds.has(itemId);
+ const selected = selectedIds.has(itemId);
+ const id = useId();
+ const focused = useKeyboardMovementContext().activeDescendantId === id;
let leftAddon: ReactNode = null;
switch (type) {
case "folder":
@@ -82,22 +104,24 @@ const getItemProps: GetItemProps<Item> = (item) => {
// no default
}
- return {
- leftAddon,
- expanderIcon: <ArrowDropDownSVGIcon />,
- className: cn(styles.item, {
- [styles.focused]: focused,
- [styles.selected]: selected,
- }),
- };
+ return (
+ <TreeProvider {...context} expanderIcon={<ArrowDropDownSVGIcon />}>
+ <DefaultTreeItemRenderer
+ {...props}
+ leftAddon={leftAddon}
+ className={cn(styles.item, {
+ [styles.focused]: focused,
+ [styles.selected]: selected,
+ })}
+ id={id}
+ />
+ </TreeProvider>
+ );
};
export default function Demo(): ReactElement {
- const selection = useTreeItemSelection([demo.itemId], false);
- const expansion = useTreeItemExpansion([
- srcFolder.itemId,
- publicFolder.itemId,
- ]);
+ const selection = useTreeSelection([demo.itemId], false);
+ const expansion = useTreeExpansion([srcFolder.itemId, publicFolder.itemId]);
return (
<Tree
🔧 convert-get-item-props
npx @react-md/codemod v5-to-v6/tree/convert-get-item-props
import cn from "classnames";
-import type { ReactNode } from "react";
-import type { GetItemProps } from "react-md";
+import { ReactElement, ReactNode, useId } from "react";
import {
ArrowDropDownSVGIcon,
+ DefaultTreeItemRenderer,
FolderOpenSVGIcon,
FolderSVGIcon,
+ TreeItemRendererProps,
+ TreeProvider,
+ useKeyboardMovementContext,
+ useTreeContext,
} from "react-md";
import Html5SVGIcon from "icons/Html5SVGIcon";
import FileSVGIcon from "./FileSVGIcon";
import SassSVGIcon from "./SassSVGIcon";
import TypescriptSVGIcon from "./TypescriptSVGIcon";
import { Item } from "./anotherFile";
import styles from "./styles.module.scss";
-export const getItemProps: GetItemProps<Item> = ({
- selected,
- focused,
- expanded,
- type,
- ...item
-}) => {
+// TODO: This might need to be renamed to match normal component naming conventions
+export const getItemProps = function Renderer(
+ props: TreeItemRendererProps<Item>,
+): ReactElement {
+ const { item: tempItem } = props;
+
+ const { type, itemId, ...item } = tempItem;
+
+ const context = useTreeContext();
+
+ const { expandedIds, selectedIds } = context;
+
+ const expanded = expandedIds.has(itemId);
+ const selected = selectedIds.has(itemId);
+ const id = useId();
+ const focused = useKeyboardMovementContext().activeDescendantId === id;
let leftAddon: ReactNode = null;
switch (type) {
case "folder":
leftAddon = expanded ? <FolderOpenSVGIcon /> : <FolderSVGIcon />;
break;
case "html":
leftAddon = <Html5SVGIcon />;
break;
case "text":
leftAddon = <FileSVGIcon />;
break;
case "scss":
leftAddon = <SassSVGIcon />;
break;
case "typescript":
leftAddon = <TypescriptSVGIcon />;
break;
// no default
}
- return {
- leftAddon,
- expanderIcon: <ArrowDropDownSVGIcon />,
- className: cn(styles.item, {
- [styles.focused]: focused,
- [styles.selected]: selected,
- }),
- };
+ return (
+ <TreeProvider {...context} expanderIcon={<ArrowDropDownSVGIcon />}>
+ <DefaultTreeItemRenderer
+ {...props}
+ leftAddon={leftAddon}
+ className={cn(styles.item, {
+ [styles.focused]: focused,
+ [styles.selected]: selected,
+ })}
+ id={id}
+ />
+ </TreeProvider>
+ );
};
🔧 item-renderer-to-render-component
npx @react-md/codemod v5-to-v6/tree/item-renderer-to-render-component
-import { TreeItemRenderer, defaultTreeItemRenderer } from "react-md";
+// TODO: The `defaultTreeItemRenderer` has been replaced by the `DefaultTreeItemRenderer` component and cannot automatically be converted
+// TODO: The `TreeItemRenderer` type has been replaced by the `TreeItemRendererProps` type and cannot automatically be converted
+import { TreeItemRendererProps, DefaultTreeItemRenderer } from "react-md";
import { MyTreeItem } from "./types";
import MyFancyNonTreeItem from "./MyFancyNonTreeItem";
export const itemRenderer: TreeItemRenderer<MyTreeItem> = (
itemProps,
item,
treeProps
) => {
const { key } = itemProps;
const { isCustom } = item;
if (isCustom) {
return <MyFancyNonTreeItem item={item} key={key} />;
}
return defaultTreeItemRenderer(itemProps, item, treeProps);
};
✅ update-simple-types
npx @react-md/codemod v5-to-v6/tree/update-simple-types
-import { TreeItemId, TreeItemIds, ExpandedIds, SelectedIds } from "react-md";
+import { TreeItemIdSet, TreeItemNode } from "react-md";
-export interface Example1 extends TreeItemIds {
- itemId: TreeItemId;
- selectedIds: SelectedIds;
- expandedIds: ExpandedIds;
+export interface Example1 extends TreeItemNode {
+ itemId: string;
+ selectedIds: TreeItemIdSet;
+ expandedIds: TreeItemIdSet;
}
🔧 update-tree-props
npx @react-md/codemod v5-to-v6/tree/update-tree-props
return (
<>
<Tree
- labelKey="example"
- valueKey="example-2"
- getItemLabel={(item) => item.something}
- getItemValue={(item) => item.somethingElse}
- onItemExpansion={(itemId) => {
+ toggleTreeItemExpansion={(itemId) => {
expand(itemId);
}}
- onMultiItemExpansion={(itemIds) => {
+ expandMultipleTreeItems={(itemIds) => {
setExpanded(itemIds);
}}
- onItemSelect={(itemId) => {
+ toggleTreeItemSelection={(itemId) => {
select(itemId);
}}
- onMultiItemSelect={(itemIds) => {
+ selectMultipleTreeItems={(itemIds) => {
multiSelect(itemIds);
}}
/>
🔧 use-tree-hooks
npx @react-md/codemod v5-to-v6/tree/use-tree-hooks
import type { ReactElement } from "react";
-import { Tree, useTreeItemSelection, useTreeItemExpansion } from "react-md";
+import { Tree, useTreeSelection, useTreeExpansion } from "react-md";
import folders from "./folders";
export default function Demo(): ReactElement {
- const { selectedIds, multiSelect, onItemSelect, onMultiItemSelect } =
- useTreeItemSelection([], false);
- const { expandedIds, onItemExpansion, onMultiItemExpansion } =
- useTreeItemExpansion([]);
+ const {
+ selectedIds,
+ multiSelect,
+ toggleTreeItemSelection: onItemSelect,
+ selectMultipleTreeItems: onMultiItemSelect,
+ } = useTreeSelection([], false);
+ const {
+ expandedIds,
+ toggleTreeItemExpansion: onItemExpansion,
+ expandMultipleTreeItems: onMultiItemExpansion,
+ } = useTreeExpansion([]);
return (
<Tree
Tooltip
🔧 convert-use-tooltip
npx @react-md/codemod v5-to-v6/tooltip/convert-use-tooltip
The useTooltip went through an API change since it no longer uses the shared
"hover mode API" and instead has its own TooltipHoverModeProvider. The other
changes are:
baseIdwas renamed toidtouchTimeandfocusTimewere removed in favor ofhoverTimeoutdisableHoverModewas removed as an option- the returned value was updated:
stuck,active,onClick,onMouseEnter,onMouseLeave, andhandlerswere removedclearHoverTimeoutwas renamed toclearVisibilityTimeoutenableHoverMode,disableHoverMode, andstartDisableTimerwere removed but available through the newuseTooltipHoverModehook
+// TODO: `useTooltip` no longer supports the `disableHoverMode` option and was removed. See the new hover mode API docs or define the `hoverTimeout` to option.
import { type ReactElement } from "react";
import { Button, Tooltip, useTooltip } from "react-md";
export default function Example(): ReactElement {
const { elementProps, tooltipProps } = useTooltip({
- baseId: "example-1-id",
+ id: "example-1-id",
+
onClick(event) {
// DO SOMETHING
},
- touchTime: 500,
- focusTime: 400,
- disableHoverMode: true,
+
+ hoverTimeout: 400,
});
return (
<>
If the hover mode API was used, there will be a diff similar to:
+// TODO: `useTooltip` no longer returns the following keys from the hover mode api and must manually be updated: stuck, active, onClick, onMouseEnter, onMouseLeave
+// TODO: `useTooltip` no longer returns the `handlers` object. The event handlers can be extracted from the `elementProps` if they are still needed.
import { type ReactElement } from "react";
-import { Button, Tooltip, useTooltip } from "react-md";
+import { Button, Tooltip, useTooltip, useTooltipHoverMode } from "react-md";
export default function Example(): ReactElement {
const {
- elementProps,
- tooltipProps,
- stuck,
- active,
- onClick,
- onMouseEnter,
- onMouseLeave,
- handlers,
enableHoverMode: enable,
disableHoverMode,
startDisableTimer,
- clearHoverTimeout,
+ } = useTooltipHoverMode();
+
+ const {
+ elementProps,
+ tooltipProps,
+ clearVisibilityTimeout: clearHoverTimeout,
} = useTooltip({
- baseId: "example-1-id",
+ id: "example-1-id",
onClick(event) {
// DO SOMETHING
},
🔧 remove-tooltipped-component
npx @react-md/codemod v5-to-v6/tooltip/remove-tooltipped-component
The Tooltipped component has been removed and a custom implementation must be
used instead.
+// TODO: The `Tooltipped` component has been removed. Update the code to use the `useTooltip` hook instead.
import { type ReactNode } from "react";
-import { SimplePosition, Tooltipped } from "react-md";
+import { SimplePosition, useTooltip } from "react-md";
interface Test1Props {
onClick?: (event: MouseEvent) => void;
🔧 update-tooltip-props
npx @react-md/codemod v5-to-v6/tooltip/update-tooltip-props
The Tooltip component updated the following props:
portalwas renamed todisablePortalportalIntoandportalIntoIdwere removed due to the new portal APIlineWrapwas removed in favor of the newtextOverflowprop
return (
<>
<Tooltip>Hello</Tooltip>
- <Tooltip portal>Hello</Tooltip>
- <Tooltip portal={false}>Hello</Tooltip>
- <Tooltip portalInto={() => document.getElementById("some-node")}>
- Hello
- </Tooltip>
- <Tooltip portalIntoId="some-dom-id">Hello</Tooltip>
- <Tooltip lineWrap>Hello</Tooltip>
- <Tooltip lineWrap={true}>Hello</Tooltip>
- <Tooltip lineWrap={lineWrap}>Hello</Tooltip>
- <Tooltip lineWrap={false}>Hello</Tooltip>
+ <Tooltip>Hello</Tooltip>
+ <Tooltip disablePortal>Hello</Tooltip>
+ <Tooltip>Hello</Tooltip>
+ <Tooltip>Hello</Tooltip>
+ <Tooltip>Hello</Tooltip>
+ <Tooltip>Hello</Tooltip>
+ <Tooltip textOverflow={lineWrap ? "allow" : "nowrap"}>Hello</Tooltip>
+ <Tooltip textOverflow="nowrap">Hello</Tooltip>
</>
);
}
Typography
❌ remove-removed-types
npx @react-md/codemod v5-to-v6/typography/remove-removed-types
The following types were removed and cannot be migrated automatically.
-import {
- TextContainerSize,
- TextContainerRenderFunction,
- TypographyRenderFunction,
-} from "react-md";
-
+// TODO: Remove the `TypographyRenderFunction` usage since it no longer exists.
+// TODO: Remove the `TextContainerRenderFunction` usage since it no longer exists.
+// TODO: Remove the `TextContainerSize` usage since it no longer exists.
const x: TextContainerRenderFunction = ({ className }) => <>{className}</>;
const y: TypographyRenderFunction = ({ className }) => <>{className}</>;
✅ update-text-container-props
npx @react-md/codemod v5-to-v6/typography/update-text-container-props
The TextContainer no longer supports the size prop and should be removed.
<TextContainer>
<Typography>Hello, world!</Typography>
</TextContainer>
- <TextContainer size="auto">
+ <TextContainer>
<Typography>Hello, world!</Typography>
</TextContainer>
- <TextContainer size="mobile">
+ <TextContainer>
<Typography>Hello, world!</Typography>
</TextContainer>
- <TextContainer size={size}>
+ <TextContainer>
<Typography>Hello, world!</Typography>
</TextContainer>
</>
✅ update-typography-props
npx @react-md/codemod v5-to-v6/typography/update-typography-props
The Typography and SrOnly components renamed the component prop to as.
export default function Example(): ReactElement {
return (
<>
- <Typography component="div">Hello, world!</Typography>
- <Typography component={CustomElement}>Hello, world!</Typography>
- <SrOnly component="div">Hello, world!</SrOnly>
- <SrOnly component={CustomElement}>Hello, world!</SrOnly>
+ <Typography as="div">Hello, world!</Typography>
+ <Typography as={CustomElement}>Hello, world!</Typography>
+ <SrOnly as="div">Hello, world!</SrOnly>
+ <SrOnly as={CustomElement}>Hello, world!</SrOnly>
</>
);
}
In addition, the Typography and SrOnly components no longer support the
child render function behavior and prefer the typography() or srOnly()
class name utility functions instead.
❌ This cannot be updated automatically.
+// TODO: Check the `Typography` usage to see if using the removed children function renderer behavior for getting the class name.
import { type ReactElement } from "react";
-import { Typography } from "react-md";
+import { Typography } from "react-md";
import CustomComponent from "./CustomComponent";
export default function Example(): ReactElement {
return (
- <Typography
- children={({ className }) => (
- <CustomComponent classNameProp={className}>
- Hello, world!
- </CustomComponent>
- )}
- />
+ <CustomComponent classNameProp={typography()}>
+ Hello, world!
+ </CustomComponent>
);
}
Utils
✅ dir-to-writing-direction-provider
npx @react-md/codemod v5-to-v6/utils/dir-to-writing-direction-provider
There have been a few breaking changes around handling the dir attribute:
DEFAULT_DIRwas renamed toDEFAULT_WRITING_DIRECTIONDirwas renamed toWritingDirectionProvider
Typescript only:
DirPropswas renamed toWritingDirectionProviderPropsWritingDirectwas renamed toDir
import { type ReactElement } from "react";
-import { Dir, DirProps, DEFAULT_DIR, WritingDirection, useDir } from "react-md";
+import {
+ WritingDirectionProvider,
+ WritingDirectionProviderProps,
+ DEFAULT_WRITING_DIRECTION,
+ Dir,
+ useDir,
+} from "react-md";
-export function Example1(props: DirProps): ReactElement {
- return <Dir defaultDir={DEFAULT_DIR} {...props} />;
+export function Example1(props: WritingDirectionProviderProps): ReactElement {
+ return (
+ <WritingDirectionProvider
+ defaultDir={DEFAULT_WRITING_DIRECTION}
+ {...props}
+ />
+ );
}
export function Example2(): ReactElement {
- let dir: WritingDirection = "ltr";
+ let dir: Dir = "ltr";
if (something) {
dir = "rtl";
}
- return <Dir defaultDir={dir} />;
+ return <WritingDirectionProvider defaultDir={dir} />;
}
export function Example3(): ReactElement {
✅ nearest-parameters-to-object
npx @react-md/codemod v5-to-v6/utils/nearest-parameters-to-object
The nearest utility function was updated to accept a single object parameter instead of multiple parameters.
const steps = range;
const minValue = 2000;
const maxValue = 8000;
-expect(nearest(10000, min, maxValue, steps, range)).toBe(maxValue);
-expect(nearest(0, minValue, max, steps, range)).toBe(minValue);
+expect(
+ nearest({
+ value: 10000,
+ min: min,
+ max: maxValue,
+ steps: steps,
+ range: range,
+ }),
+).toBe(maxValue);
+expect(
+ nearest({
+ value: 0,
+ min: minValue,
+ max: max,
+ steps: steps,
+ range: range,
+ }),
+).toBe(minValue);
❌ remove-scroll-listener
npx @react-md/codemod v5-to-v6/utils/remove-scroll-listener
The useScrollListener hook and ScrollListener component have been removed
and must be implemented manually.
+// TODO: The `ScrollListener`/`useScrollListener` have been removed from react-md. You will need to implement their behavior manually.
import { ArrowDropDownSVGIcon } from "@react-md/material-icons";
import type { CSSProperties, ReactElement } from "react";
import { useCallback, useRef, useState } from "react";
@@ -6,12 +7,10 @@ import {
List,
ListItem,
Overlay,
- ScrollListener,
TextIconSpacing,
Typography,
getFixedPosition,
useToggle,
- useScrollListener,
} from "react-md";
import styles from "./SimpleExample.module.scss";
@@ -38,10 +37,6 @@ export default function SimpleExample(): ReactElement {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- useScrollListener({
- onUpdate: updatePosition,
- });
-
return (
<div className={styles.container}>
<Button
@@ -77,7 +72,6 @@ export default function SimpleExample(): ReactElement {
}
}}
>
- <ScrollListener onScroll={updatePosition} />
{Array.from({ length: 6 }).map((_, i) => (
<ListItem id={`menu-item-${i}`} key={i} role="menuitem">
{`Option ${i + 1}`}
✅ update-resize-listener
npx @react-md/codemod v5-to-v6/utils/update-resize-listener
The useResizeListener options have been updated as follows:
onResizerenamed toonUpdateimmediateas been removedoptionshas been removed and instead should be passed directly to the hookenabledhas been renamed todisabled
export default function Example(): null {
const [size, setSize] = useState(window.innerWidth);
useResizeListener({
- onResize() {
+ onUpdate() {
setSize(window.innerWidth);
},
});
useResizeListener({
- onResize: () => setSize(window.innerWidth),
- enabled: false,
+ onUpdate: () => setSize(window.innerWidth),
+ disabled: true,
});
useResizeListener({
- onResize: () => setSize(window.innerWidth),
- enabled: someFlag || anotherFlag,
+ onUpdate: () => setSize(window.innerWidth),
+ disabled: !(someFlag || anotherFlag),
});
useResizeListener({
- immediate: false,
- onResize: () => setSize(window.innerWidth),
- options: false,
+ onUpdate: () => setSize(window.innerWidth),
+ capture: false,
});
useResizeListener({
- immediate: someFlag,
- onResize: () => {
+ onUpdate: () => {
console.log(window.innerWidth);
},
- options: {
- once: true,
- passive: true,
- },
+ once: true,
+ passive: true,
});
In addition, the ResizeListener component has been removed in favor of using the
useResizeListener hook.
import type { ReactElement } from "react";
import { useState } from "react";
-import { Checkbox, ResizeListener, Typography, useChecked } from "react-md";
+import { Checkbox, Typography, useChecked, useResizeListener } from "react-md";
import CodeBlock from "./CodeBlock";
@@ -16,6 +16,11 @@ export default function Demo(): ReactElement {
const [enabled, handleEnabledChange] = useChecked(true);
const [immediate, handleImmediateChange] = useChecked(true);
+ useResizeListener({
+ onUpdate: () => setSize(window.innerWidth),
+ disabled: !enabled,
+ });
+
return (
<>
<Checkbox
@@ -32,12 +37,7 @@ export default function Demo(): ReactElement {
onChange={handleImmediateChange}
label="Invoke on mount"
/>
- {enabled && (
- <ResizeListener
- immediate={immediate}
- onResize={() => setSize(window.innerWidth)}
- />
- )}
+
<Typography>The current app size is:</Typography>
<CodeBlock suppressHydrationWarning>{size}px</CodeBlock>
</>
✅ update-use-resize-observer
npx @react-md/codemod v5-to-v6/utils/update-use-resize-observer
The useResizeObserver hook was updated so that it:
- accepts a single argument param
- the callback should now be set to the
onUpdateproperty
- the callback should now be set to the
- only returns a
refCallbackinstead of a tuple - the callback function now provides the
ResizeObserverEntryinstead of theResizeObserverElementData- if the
heightorwidthare needed, get from theentry.contentRectorentry.borderBoxSize[0] - if the
elementis needed, useentry.target - if the
scrollHeightorscrollWidthare needed, useentry.target.scrollHeightorentry.target.scrollWidth
- if the
export default function Example(): ReactElement {
const [state, setState] = useState();
- const [, refCallback] = useResizeObserver(
- useCallback(
- (resizeData) =>
- setState({
- height: resizeData.scrollHeight,
- width: resizeData.scrollWidth,
- }),
- []
- )
- );
+ const refCallback = useResizeObserver({
+ onUpdate: useCallback((entry) => {
+ setState({
+ height: entry.target.scrollHeight,
+ width: entry.target.scrollWidth,
+ });
+ }, []),
+ });
return <></>;
}
If a ref is required within the component, provide it using the ref option
like before:
export default function Example(): ReactElement {
const [state, setState] = useState();
const nodeRef = useRef();
- const [ref, refCallback] = useResizeObserver(
- useCallback(
- (resizeData) =>
- setState({
- height: resizeData.scrollHeight,
- width: resizeData.scrollWidth,
- }),
- []
- ),
- {
- ref: nodeRef,
- }
- );
+ const refCallback = useResizeObserver({
+ onUpdate: useCallback((entry) => {
+ setState({
+ height: entry.target.scrollHeight,
+ width: entry.target.scrollWidth,
+ });
+ }, []),
+
+ ref: nodeRef,
+ });
// do stuff with `nodeRef.current`
If the nodeRef is dynamic, wrap with useEnsuredRef:
@@ -5,7 +5,7 @@ import {
useEffect,
useState,
} from "react";
-import { useResizeObserver } from "react-md";
+import { useEnsuredRef, useResizeObserver } from "react-md";
interface ExampleProps {
nodeRef?: Ref<HTMLDivElement>;
@@ -13,19 +13,17 @@ interface ExampleProps {
export default function Example({ nodeRef }: ExampleProps): ReactElement {
const [state, setState] = useState();
- const [ref, refCallback] = useResizeObserver(
- useCallback(
- (resizeData) =>
- setState({
- height: resizeData.scrollHeight,
- width: resizeData.scrollWidth,
- }),
- []
- ),
- {
- ref: nodeRef,
- }
- );
+ const [ref, nodeRefCallback] = useEnsuredRef(nodeRef);
+ const refCallback = useResizeObserver({
+ onUpdate: useCallback((entry) => {
+ setState({
+ height: entry.target.scrollHeight,
+ width: entry.target.scrollWidth,
+ });
+ }, []),
+
+ ref: nodeRefCallback,
+ });
useEffect(() => {
if (ref.current) {
✅ update-use-toggle-api
npx @react-md/codemod v5-to-v6/utils/update-use-toggle-api
The useToggle hook was updated to return an object instead of an ordered array.
import { type ReactElement } from "react";
import { Button, useToggle } from "react-md";
export default function Example(): ReactElement {
- const [toggled, enable, disable, toggle] = useToggle();
+ const {
+ toggled: toggled,
+ enable: enable,
+ disable: disable,
+ toggle: toggle,
+ } = useToggle();
return (
<>
<Button onClick={enable}>Enable</Button>
<Button onClick={disable}>Diable</Button>
<Button onClick={toggle}>Toggle</Button>
{toggled && <>Hello, world!</>}
</>
);
}
✅ within-range-parameters-to-object
npx @react-md/codemod v5-to-v6/utils/within-range-parameters-to-object
The withinRange util was updated to accept a single object parameter
instead of multiple parameters.
-expect(withinRange(0, 0, 10)).toBe(0);
-expect(withinRange(-1, 0, 10)).toBe(0);
+expect(
+ withinRange({
+ min: 0,
+ max: 10,
+ value: 0,
+ }),
+).toBe(0);
+expect(
+ withinRange({
+ min: 0,
+ max: 10,
+ value: -1,
+ }),
+).toBe(0);
🔧 update-search-functions
npx @react-md/codemod v5-to-v6/utils/update-search-functions
There were a few breaking changes for the caseInsensitiveFilter, fuzzyFilter, and findIgnoreCase functions:
- All three functions now accept a single argument instead of three
caseInsensitiveFilterandfindIgnoreCasehave been renamed tocaseInsensitiveSearchfindIgnoreCaseshould addtype: "search"to the options
fuzzyFilterhas been renamed tofuzzySearch- The
valueKeyoption was removed - The
getItemValueoption was renamed toextractor trimandignoreWhitespacehave been merged into a singlewhitespaceoption which can be one of:"trim","ignore", or"as-is"
- The following constants were removed:
DEFAULT_GET_ITEM_VALUEDEFAULT_VALUE_KEYDEFAULT_IGNORE_WHITESPACEDEFAULT_SEARCH_RESET_TIMEDEFAULT_SEARCH_OPTIONS
- The
GetItemValuetype was renamed toTextExtractor - The
SearchOptionstype was removed
+// TODO: Check if `caseInsensitiveSearch` is using a list of objects and requires an `extractor` option
+// TODO: Check if `fuzzySearch` is using a list of objects and requires an `extractor` option
+import { caseInsensitiveSearch, fuzzySearch } from "react-md";
-import { caseInsensitiveFilter, findIgnoreCase, fuzzyFilter } from "react-md";
const FRUITS = ["Apple", "Banana", "Mango", "Orange"];
-expect(caseInsensitiveFilter("", list1)).toBe(list1);
-expect(caseInsensitiveFilter("ap", FRUITS, { startsWith: true })).toEqual([
- "Apple",
-]);
-expect(caseInsensitiveFilter("an", FRUITS, { startsWith: true })).toEqual([]);
+expect(caseInsensitiveSearch({ query: "", list: list1 })).toBe(list1);
+expect(
+ caseInsensitiveSearch({
+ query: "ap",
+ list: FRUITS,
+ whitespace: "trim",
+ startsWith: true,
+ })
+).toEqual(["Apple"]);
+expect(
+ caseInsensitiveSearch({ query: "an", list: FRUITS, whitespace: "ignore" })
+).toEqual([]);
const list = ["Item 1", "This is Item 1"];
-expect(caseInsensitiveFilter("item", list, { startsWith: true })).toEqual([
- "Item 1",
-]);
+expect(
+ caseInsensitiveSearch({
+ query: "item",
+ list,
+ })
+).toEqual(["Item 1"]);
const item1 = "Lorem ipsum";
const item2 = "another item";
const item3 = "in this string";
const item4 = "not interested, mate";
const item5 = "not in my house";
const list2 = [item1, item2, item3, item4, item5];
-expect(fuzzyFilter("ti", list2)).toEqual([item3]);
-expect(fuzzyFilter("ti", list2, { ignoreWhitespace: true })).toEqual([
- item2,
- item3,
- item4,
- item5,
-]);
-expect(fuzzyFilter("t i", list2, { ignoreWhitespace: true })).toEqual([
- item2,
- item3,
- item4,
- item5,
-]);
-expect(fuzzyFilter("rem", list2, { ignoreWhitespace: true })).toEqual([
- item1,
- item2,
-]);
-expect(fuzzyFilter("tem", list2, { ignoreWhitespace: true })).toEqual([item2]);
+expect(fuzzySearch({ query: "ti", list: list2 })).toEqual([item3]);
+expect(fuzzySearch({ query: "ti", list: list2, whitespace: "ignore" })).toEqual(
+ [item2, item3, item4, item5]
+);
+expect(
+ fuzzySearch({ query: "t i", list: list2, whitespace: "ignore" })
+).toEqual([item2, item3, item4, item5]);
+expect(
+ fuzzySearch({ query: "rem", list: list2, whitespace: "ignore" })
+).toEqual([item1, item2]);
+expect(
+ fuzzySearch({ query: "tem", list: list2, whitespace: "ignore" })
+).toEqual([item2]);
-expect(findIgnoreCase("", list)).toBe(null);
-expect(findIgnoreCase("f", list)).toBe(item1);
-expect(findIgnoreCase("s", list)).toBe(item2);
-expect(findIgnoreCase("thi", list)).toBe(item3);
-const getItemValue1 = (item: string) => `thing-${item}`;
-expect(findIgnoreCase("thing-a", FRUITS, { getItemValue: getItemValue1 })).toBe(
- "Apple"
+expect(caseInsensitiveSearch({ query: "", list, type: "search" })).toBe(null);
+expect(caseInsensitiveSearch({ query: "f", list, type: "search" })).toBe(item1);
+expect(caseInsensitiveSearch({ query: "s", list, type: "search" })).toBe(item2);
+expect(caseInsensitiveSearch({ query: "thi", list, type: "search" })).toBe(
+ item3
);
+const getItemValue1 = (item: string) => `thing-${item}`;
+expect(
+ caseInsensitiveSearch({
+ query: "thing-a",
+ list: FRUITS,
+ type: "search",
+ extractor: getItemValue1,
+ })
+).toBe("Apple");
Sass/SCSS Migration
npx @react-md/codemod sass-migrator v5-to-v6
The provided codemod will attempt to handle most of the sass migrations except for the following:
- migrating react-md imports through
@importor@use - migrating from
@importto@use - updating mixin and function parameters
- updating class name references within react-md
The codemod will:
- handle simple renames
- add
TODO:comments for functions, variables, and mixins that have been removed without a possible fallback
High Level Changes
This version of react-md only supports the new Sass module system through
@use where the main changes are:
-
The
@react-md/{{PACKAGE_NAME}}/dist/*no longer exist. Instead use@react-md/core,@react-md/core/colors, and@react-md/core/a11yinstead:-@use "@react-md/core/dist/color-palette" as *; -@use "@react-md/button/dist/mixins" as *; +@use "@react-md/core/colors" as *; +@use "@react-md/core" as *; -
The theme API has been updated to reference custom properties instead of
theme. The general pattern isrmd-{{PACKAGE_NAME}}-theme-var->{{GROUP_NAME}}-get-var,rmd-{{PACKAGE_NAME}}-theme->{{GROUP_NAME}}-use-var, andrmd-{{PACKAGE_NAME}}-theme-update-var->{{GROUP_NAME}}-set-var:-@include rmd-app-bar-theme-update-var(height, 3.5rem); +@include app-bar-set-var(height, 3.5rem); -@include rmd-avatar-theme(background-color); +@include avatar-use-var(background-color); -color: rmd-button-theme-var(color); +color: button-get-var(color); -
The theme API no longer provides
rmd-themeandrmd-{{PACKAGE_NAME}}-themefunctions since the{{GROUPNAME}}-get-var()function is preferred -
Variables, functions, and mixins are no longer prefixed with
rmd-since the new Sass module system prefers providing namespaces. The general pattern isrmd-{{PACKAGE_NAME}}-{{REMAINING}}to{{GROUP_NAME}}-{{REMAINING}}:-$rmd-badge-size +$badge-size
Color Scheme Changes
This version of react-md now supports switching between, light, dark, and
system color schemes by setting a new $color-scheme variable instead of the
$rmd-theme-light and $rmd-theme-dark-class variables. If you were not using
the prefers-color-scheme behavior for the $rmd-theme-dark-class, just change
$rmd-theme-light: true|false to $color-scheme: light|dark
@use "react-md" with (
+ $color-scheme: dark
- $rmd-theme-light: false
);
If you were using the $rmd-theme-dark-class: prefers-color-scheme, set
$color-scheme: system and $disable-default-system-theme: true:
@use "react-md" with (
+ $color-scheme: system,
+ $disable-default-system-theme: true
- $rmd-theme-light: false,
- $rmd-theme-dark-class: 'prefers-color-scheme'
);
If you want to use the new system theme behavior, remove the
$disable-default-system-theme and every @media (prefers-color-scheme: dark)
that exist in your app.
Theme 🔧
- the theme API renamed the following variables:
background->background-colorprimary->primary-coloron-primary->on-primary-colorsecondary->secondary-coloron-secondary->on-secondary-colorsurface->surface-coloron-surface-> usetext-primary-colororinverse-colorinsteadwarning->warning-coloron-warning->on-warning-colorerror->error-coloron-error->on-error-colorsuccess->success-coloron-success->on-success-colortext-primary-on-background->text-primary-colortext-secondary-on-background->text-secondary-colortext-hint-on-background->text-hint-colortext-disabled-on-background->text-disabled-colortext-icon-on-background-> use the core.icon-get-var(color) or core.icon-use-var(color) instead
-@include rmd-theme(background-color, background);
+@include theme-use-var(background-color, background-color);
-@include rmd-theme(background-color, surface);
+@include theme-use-var(background-color, surface-color);
/* there is no `on-surface` variable type in v6, but inverse-color or text-primary-color are the closest */
-@include rmd-theme(color, on-surface);
+@include theme-use-var(color, inverse-color);
-@include rmd-theme(background-color, primary);
-@include rmd-theme(color, on-primary);
+@include theme-use-var(background-color, primary-color);
+@include theme-use-var(color, on-primary-color);
-@include rmd-theme(background-color, secondary);
-@include rmd-theme(color, on-secondary);
+@include theme-use-var(background-color, secondary-color);
+@include theme-use-var(color, on-secondary-color);
-@include rmd-theme(background-color, warning);
-@include rmd-theme(color, on-warning);
+@include theme-use-var(background-color, warning-color);
+@include theme-use-var(color, on-warning-color);
-@include rmd-theme(background-color, error);
-@include rmd-theme(color, on-error);
+@include theme-use-var(background-color, error-color);
+@include theme-use-var(color, on-error-color);
-@include rmd-theme(background-color, success);
-@include rmd-theme(color, on-success);
+@include theme-use-var(background-color, success-color);
+@include theme-use-var(color, on-success-color);
-@include rmd-theme(color, text-primary-on-background);
+@include theme-use-var(color, text-primary-color);
-@include rmd-theme(color, text-secondary-on-background);
+@include theme-use-var(color, text-secondary-color);
-@include rmd-theme(color, text-hint-on-background);
+@include theme-use-var(color, text-hint-color);
-@include rmd-theme(color, text-disabled-on-background);
+@include theme-use-var(color, text-disabled-color);
-@include rmd-theme(color, text-icon-on-background);
+@include icon-use-var(color);
- the theme API no longer supports the following variables:
light-backgroundlight-surfacedark-backgrounddark-surfacetext-primary-on-lighttext-secondary-on-lighttext-hint-on-lighttext-disabled-on-lighttext-icon-on-lighttext-primary-on-darktext-secondary-on-darktext-hint-on-darktext-disabled-on-darktext-icon-on-dark
-@include rmd-theme(background-color, light-background);
-@include rmd-theme(background-color, light-surface);
-@include rmd-theme(background-color, dark-background);
-@include rmd-theme(background-color, dark-surface);
-@include rmd-theme(color, text-primary-on-light);
-@include rmd-theme(color, text-secondary-on-light);
-@include rmd-theme(color, text-hint-on-light);
-@include rmd-theme(color, text-disabled-on-light);
-@include rmd-theme(color, text-icon-on-light);
-@include rmd-theme(color, text-primary-on-dark);
-@include rmd-theme(color, text-secondary-on-dark);
-@include rmd-theme(color, text-hint-on-dark);
-@include rmd-theme(color, text-disabled-on-dark);
-@include rmd-theme(color, text-icon-on-dark);
- the following functions, mixins, and variables have been removed:
@function rmd-theme@function rmd-theme-text-color@mixin rmd-theme-tone@mixin rmd-theme-dark-elevation-styles@mixin rmd-theme-dark-elevation$rmd-theme-default-contrast-ratio$rmd-theme-better-contrast-colors$rmd-theme-no-css-variables-fallback$rmd-theme-define-colors-with-rgba$rmd-theme-light- use$color-scheme: light,$color-scheme: dark, or$color-scheme: systeminstead$rmd-theme-dark-class$rmd-theme-on-surface$rmd-theme-light-text-colors$rmd-theme-dark-text-colors$rmd-theme-primary-text-on-light-color$rmd-theme-secondary-text-on-light-color$rmd-theme-hint-text-on-light-color$rmd-theme-disabled-text-on-light-color$rmd-theme-primary-text-on-dark-color$rmd-theme-secondary-text-on-dark-color$rmd-theme-hint-text-on-dark-color$rmd-theme-disabled-text-on-dark-color$rmd-theme-icon-on-light-color$rmd-theme-icon-on-dark-color$rmd-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-theme-var->theme-get-var@mixin rmd-theme->theme-use-var@mixin rmd-theme-update-var->theme-set-var@mixin rmd-theme-light->use-light-theme(all components and themes) /use-light-theme-colors(only base theme colors)@mixin rmd-theme-dark->use-dark-theme(all components and themes) /use-dark-theme-colors(only base theme colors)@mixin rmd-theme-get-swatch->get-swatch@mixin rmd-theme-contrast-tone->contrast-color@mixin rmd-theme-best-contrast-color->contrast-color@mixin react-md-theme->theme-styles$rmd-theme-dark-elevation->$disable-dark-elevation$rmd-theme-primary->$primary-color$rmd-theme-on-primary->$on-primary-color$rmd-theme-secondary->$secondary-color$rmd-theme-on-secondary->$on-secondary-color$rmd-theme-warning->$warning-color$rmd-theme-on-warning->$on-warning-color$rmd-theme-error->$error-color$rmd-theme-on-error->$on-error-color$rmd-theme-success->$success-color$rmd-theme-on-success->$on-success-color$rmd-theme-light-background->$light-theme-background-color$rmd-theme-light-surface->$light-theme-surface-color$rmd-theme-light-primary-text-color->$light-theme-text-primary-color$rmd-theme-light-secondary-text-color->$light-theme-text-secondary-color$rmd-theme-light-hint-text-color->$light-theme-text-hint-color$rmd-theme-light-disabled-text-color->$light-theme-text-disabled-color$rmd-theme-dark-background->$dark-theme-background-colorand changed the default value to always be#121212$rmd-theme-dark-surface->$dark-theme-surface-colorand changed the default value to beif($disable-dark-elevation, colors.$grey-800, null)$rmd-theme-dark-primary-text-color->$dark-theme-text-primary-color$rmd-theme-dark-secondary-text-color->$dark-theme-text-secondary-color$rmd-theme-dark-hint-text-color->$dark-theme-text-hint-color$rmd-theme-dark-disabled-text-color->$dark-theme-text-disabled-color$rmd-theme-light-icon-color->$icon-light-theme-color$rmd-theme-dark-icon-color->$icon-dark-theme-color$rmd-theme-icon-on-background-color->$icon-color$rmd-theme-background->$background-color$rmd-theme-surface->$surface-color$rmd-theme-primary-text-on-background-color->$text-primary-color$rmd-theme-secondary-text-on-background-color->$text-secondary-color$rmd-theme-hint-text-on-background-color->$text-hint-color$rmd-theme-disabled-text-on-background-color->$text-disabled-color$rmd-theme-dark-elevation-colors->$dark-elevation-colors$rmd-theme-color-map->$color-map$rmd-theme-primary-suffixes->$primary-suffixes$rmd-theme-accent-suffixes->$accent-suffixes$rmd-theme-colors->$available-color-names
Alert 🔧
- the alert theme API no longer support the
light-background-color,light-color,dark-background-color, anddark-colorvariables - the following functions, mixins, and variables were removed:
@function rmd-alert-theme@mixin rmd-snackbar@mixin rmd-toast$rmd-toast-two-line-min-height$rmd-toast-action-margin$rmd-toast-stacked-action-margin-top$rmd-toast-enter-duration$rmd-toast-exit-duration$rmd-alert-theme-values
- the following functions, mixins, and variables were renamed:
@function rmd-alert-theme-var->snackbar-get-var@mixin rmd-alert-theme->snackbar-use-var@mixin rmd-alert-theme-update-var->snackbar-set-var@mxin react-md-alert->snackbar-styles
App Bar 🔧
- the app bar theme API no longer supports the
background-color,color,primary,on-primary,secondary,on-secondary,default-background-color,default-color,default-light-background-color,default-light-color,default-dark-background-color,default-dark-color,dense-height,priminent-height, andprominent-dense-heightvariables - the following functions, mixins, and variables have been removed:
@function rmd-app-bar-theme@mixin rmd-app-bar-fixed@mixin rmd-app-bar-themes@mixin rmd-app-bar-nav@mixin rmd-app-bar-action-position@mixin rmd-app-bar-action@mixin rmd-app-bar-offset@mixin rmd-app-bar-offsets$rmd-app-bar-nav-margin$rmd-app-bar-primary-background-color$rmd-app-bar-primary-color$rmd-app-bar-secondary-background-color$rmd-app-bar-secondary-color$rmd-app-bar-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-app-bar-theme-var->app-bar-get-var@mixin rmd-app-bar-theme->app-bar-use-var@mixin rmd-app-bar-theme-update-var->app-bar-set-var@mixin rmd-app-bar-dense-theme->app-bar-dense-variables@mixin react-md-app-bar->app-bar-styles$rmd-app-bar-z-index->$app-bar-fixed-z-index$rmd-app-bar-fixed-elevation->$app-bar-fixed-elevation$rmd-app-bar-height->$app-bar-height$rmd-app-bar-dense-height->app-bar-dense-height$rmd-app-bar-prominent-height->app-bar-prominent-height$rmd-app-bar-prominent-dense-height->app-bar-prominent-dense-height$rmd-app-bar-keyline->$app-bar-keyline$rmd-app-bar-title-keyline->$app-bar-title-keyline$rmd-app-bar-title-nav-margin->$app-bar-nav-keylineand is now configurable$rmd-app-bar-lr-margin->$app-bar-horizontal-paddingand is applied as padding instead of margin$rmd-app-bar-default-light-theme-background-color->$app-bar-light-theme-surface-background-colorand changed the default value from$grey-100to$light-theme-surface-color($white)$rmd-app-bar-default-light-theme-color->$app-bar-light-theme-surface-color$rmd-app-bar-default-dark-theme-background-color->$app-bar-dark-theme-surface-background-colorand changed the default value from$rmd-grey-900toif($disable-dark-elevation, $grey-800, null)$rmd-app-bar-default-dark-theme-color->$app-bar-dark-theme-surface-colorand changed the default value to$white$rmd-app-bar-default-background-color->$app-bar-surface-background-color$rmd-app-bar-default-color->$app-bar-surface-color
Autocomplete 🎉
The previous version did not have any custom Sass/SCSS.
Avatar 🔧
- the following functions, mixins, and variables have been removed:
@function rmd-avatar-theme@mixin rmd-avatar-colorand@mixin rmd-avtar-colorswere removed in favor of core.avatar-custom-color$rmd-avatar-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-avatar-theme-var->avatar-get-var@mixin rmd-avatar-theme->avatar-use-var@mixin rmd-avatar-theme-update-var->avatar-set-var@mixin react-md-avatar->avatar-styles$rmd-avatar-color->$avatar-color$rmd-avatar-background-color->$avatar-background-color$rmd-avatar-border-color->$avatar-border-colorand the default value changed totransparent$rmd-avatar-border-radius->$avatar-border-radius$rmd-avatar-size->$avatar-size->size$rmd-avatar-font-size->$avatar-font-size$rmd-avatar-line-height->$avatar-line-height$rmd-avatar-colors->$avatar-colors
Badge 🔧
- the following functions, mixins, and variables have been removed:
@function rmd-badge-theme$rmd-badge-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-badge-theme-var->badge-get-var@mixin rmd-badge-theme->badge-use-var@mixin rmd-badge-theme-update-var->badge-set-var@mixin react-md-badge->badge-styles$rmd-badge-size->$badge-size$rmd-badge-border-radius->$badge-border-radius$rmd-badge-default-background-color->$badge-greyscale-background-colorand changed the default value fromrgba($rmd-black-base, 0.2)toif($light-theme, #ccc, $grey-700)$rmd-badge-default-color->$badge-greyscale-color$rmd-badge-font-size->$badge-font-size$rmd-badge-offset-top->$badge-offset-topand changed the default value to$badge-offset(0)$rmd-bagde-offset-right->$badge-offset-rightand changed the default value to$badge-offset(0)
Button 🔧
- the button theme API no longer supports the
outlineandoutline-widthvariables. Instead, use the core.theme-get-var(outline-color), core.theme-set-var(outline-color), and core.theme-use-var(outline-color) withoutline-colororoutline-width - the button theme API renamed the following variables:
text-border-radius->border-radiustext-height->text-min-height
- the following functions, mixins, and variables have been removed:
@function rmd-button-theme@mixin rmd-button-base@mixin rmd-button-icon@mixin rmd-button@mixin rmd-button-floating-positions@mixin rmd-fab$rmd-button-text-icon-inherit-color$rmd-button-outline-width$rmd-button-outline-color$rmd-button-box-shadow$rmd-button-background-color$rmd-button-color$rmd-button-contained-elevation-transition-time$rmd-button-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-button-theme-var->button-get-var@mixin rmd-button-theme->button-use-var@mixin rmd-button-theme-update-var->button-set-var@mixin rmd-button-reset->button-unstyled@mixin rmd-button-unstyled->button-unstyled@mixin rmd-button-text->button-text-styles@mixin react-md-button->button-styles$rmd-button-text-border-radius->$button-text-border-radius$rmd-button-text-horizontal-padding->$button-text-horizontal-padding$rmd-button-text-vertical-padding->$button-text-vertical-padding$rmd-button-text-height->$button-text-min-height$rmd-button-text-min-width->$button-text-min-width$rmd-button-text-icon-size->$button-text-icon-size$rmd-button-icon-border-radius->$button-icon-border-radius$rmd-button-icon-size->$button-icon-sizeand changed the default value from3remtoauto$rmd-button-contained-resting-elevation->$button-contained-elevation$rmd-button-contained-pressed-elevation->$button-contained-pressed-elevation$rmd-button-floating-z-index->$button-floating-z-index$rmd-button-floating-margin->$button-floating-margin$rmd-button-floating-positions->$button-floating-positions$rmd-button-circular-progress-size->$button-circular-progress-size
Card 🔧
- the card theme API no longer supports the
secondary-colorvariables - the following functions, mixins, and variables have been removed:
@function rmd-card-theme@mixin rmd-card@mixin rmd-card-header@mixin rmd-card-title@mixin rmd-card-subtitle@mixin rmd-card-content@mixin rmd-card-actions$rmd-card-dark-elevation-background-color$rmd-card-secondary-color$rmd-card-actions-padding$rmd-card-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-card-theme-var->card-get-var@mixin rmd-card-theme->card-use-var@mixin rmd-card-theme-update-var->card-set-var@mixin react-md-card->card-styles$rmd-card-elevation->$card-elevation$rmd-card-light-background-color->$card-light-background-color$rmd-card-dark-background-color->$card-dark-background-color$rmd-card-background-color->$card-background-color$rmd-card-color->$card-color$rmd-card-base-elevation->$card-raisable-start-elevation$rmd-card-raised-elevation->$card-raisable-end-elevation$rmd-card-border-radius->$card-border-radius$rmd-card-header-padding->$card-header-padding$rmd-card-header-padding-top->$card-header-padding-top$rmd-card-header-spacing->$card-header-spacing$rmd-card-content-padding->$card-content-padding$rmd-card-content-padding-extra->$card-content-padding-bottom$rmd-card-border-color->$card-border-color$rmd-card-border-width->$card-border-width
Chip 🔧
- the chip theme API no longer supports the
background-colorandcolorvariables - the following functions, mixins, and variables have been removed:
@function rmd-chip-theme@mixin rmd-chip$rmd-chip-disable-focus-background-color$rmd-chip-box-shadow$rmd-chip-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-chip-theme-var->chip-get-var@mixin rmd-chip-theme->chip-use-var@mixin rmd-chip-theme-update-var->chip-set-var@mixin react-md-chip->chip-styles$rmd-chip-height->$chip-height$rmd-chip-border-radius->$chip-border-radius$rmd-chip-small-spacing->$chip-addon-left-padding$rmd-chip-medium-spacing->$chip-addon-right-padding$rmd-chip-large-spacing->$chip-horizonal-padding$rmd-chip-icon-size->$chip-icon-size$rmd-chip-avatar-size->$chip-avatar-size$rmd-chip-progress-size->$chip-progress-size$rmd-chip-progress-width->$chip-progress-width$rmd-chip-themed-background-color->$chip-theme-background-color$rmd-chip-themed-color->$chip-theme-color$rmd-chip-solid-light-background-color->$chip-solid-light-background-color$rmd-chip-solid-light-color->$chip-solid-light-color$rmd-chip-solid-light-disabled-background-color->$chip-solid-light-disabled-background-color$rmd-chip-solid-dark-background-color->$chip-solid-dark-background-color$rmd-chip-solid-dark-color->$chip-solid-dark-color$rmd-chip-solid-dark-disabled-background-color->$chip-solid-dark-disabled-background-color$rmd-chip-solid-background-color->$chip-solid-background-color$rmd-chip-solid-color->$chip-solid-color$rmd-chip-solid-disabled-background-color->$chip-solid-disabled-background-color$rmd-chip-outline-light-background-color->$chip-outline-light-background-color$rmd-chip-outline-light-color->$chip-outline-light-text-color$rmd-chip-outline-dark-background-color->$chip-outline-dark-background-color$rmd-chip-outline-dark-color->$chip-outline-dark-text-color$rmd-chip-outline-background-color->$chip-outline-background-color$rmd-chip-outline-color->$chip-outline-text-color$rmd-chip-outline-border-color->$chip-outline-color$rmd-chip-transition-duration->$chip-outline-raisable-transition-duration
Dialog 🔧
- the dialog theme API no longer supports the
background-colorvariable and renamedmin-widthtowidth - the following functions, mixins, and variables have been removed:
@function rmd-dialog-theme@mixin rmd-dialog@mixin rmd-dialog-header@mixin rmd-dialog-title@mixin rmd-dialog-content@mixin rmd-dialog-footer@mixin rmd-dialog-container@mixin rmd-dialog-overlay$rmd-dialog-light-background-color$rmd-dialog-dark-elevation-background-color$rmd-dialog-dark-background-color$rmd-dialog-background-color$rmd-dialog-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-dialog-theme-var->dialog-get-var@mixin rmd-dialog-theme->dialog-use-var@mixin rmd-dialog-theme-update-var->dialog-set-var@mixin react-md-dialog->dialog-styles$rmd-dialog-z-index->$dialog-z-index$rmd-dialog-elevation->$dialog-elevation$rmd-dialog-min-width->$dialog-min-width$rmd-dialog-vertical-margin->$dialog-vertical-margin$rmd-dialog-horizontal-margin->$dialog-horizontal-margin$rmd-dialog-header-padding->$dialog-header-padding$rmd-dialog-header-padding-bottom->$dialog-header-padding-bottom$rmd-dialog-content-padding->$dialog-content-padding$rmd-dialog-footer-padding->$dialog-footer-padding$rmd-dialog-transition-distance->$dialog-transition-distance$rmd-dialog-enter-duration->$dialog-enter-duration$rmd-dialog-leave-duration->$dialog-leave-duration
Divider 🔧
- the divider theme API renamed the following variables:
background-color->color
- the divider theme API no longer supports the following variables:
background-color-on-lightbackground-color-on-dark
- the following functions, mixins, and variables have been removed:
@function rmd-divider-theme@mixin rmd-divider$rmd-divider-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-divider-theme-var->divider-get-var@mixin rmd-divider-theme->divider-use-var@mixin rmd-divider-theme-update-var->divider-set-var@mixin rmd-divider-border->divider-border-style@mixin react-md-divider->divider-styles$rmd-divider-size->$divider-size$rmd-divider-max-size->$divider-max-size$rmd-divider-inset->$divider-inset$rmd-divider-spacing->$divider-spacing$rmd-divider-vertical-spacing->$divider-vertical-spacing$rmd-divider-background-color-on-light->$divider-light-theme-color$rmd-divider-background-color-on-dark->$divider-dark-theme-color$rmd-divider-background-color->$divider-color
Elevation 🔧
- the following functions, mixins, and variables have been renamed:
@function rmd-elevation->box-shadow@mixin rmd-elevation->box-shadow@mixin rmd-elevation-transition->box-shadow-transition$rmd-elevation-color->$box-shadow-color$rmd-elevation-shadow-1-opacity->$box-shadow-1-opacity$rmd-elevation-shadow-2-opacity->$box-shadow-2-opacity$rmd-elevation-shadow-3-opacity->$box-shadow-3-opacity$rmd-elevation-shadow-1-map->$box-shadow-1-layers$rmd-elevation-shadow-2-map->$box-shadow-2-layers$rmd-elevation-shadow-3-map->$box-shadow-3-layers
Expansion Panel 🔧
- the expansion-panel no longer has a theme API
- the following functions, mixins, and variables have been removed:
@function rmd-expansion-panel-theme@function rmd-expansion-panel-theme-var@mixin rmd-expansion-panel-theme@mixin rmd-expansion-panel-theme-update-var@mixin rmd-expansion-panel$rmd-expansion-panel-theme-values
- the following functions, mixins, and variables have been renamed:
@mixin react-md-expansion-panel->expansion-panel-styles$rmd-expansion-panel-spacing->$expansion-panel-spacing$rmd-expansion-panel-header-padding->$expansion-panel-padding$rmd-expansion-panel-expander-icon-spacing->$expansion-panel-button-spacing
Form 🔧
- the form theme API has been split into multiple themes based on components:
form-form-get-var,form-use-var,form-set-varactive-colorfocus-color
label-label-get-var,label-use-var,label-set-varfloating-top->floating-ylabel-left-offset->floating-active-xlabel-top-offset->floating-active-ylabel-active-padding->active-paddinglabel-active-background-color->active-background-color
text-field-text-field-get-var,text-field-use-var,text-field-set-varaddon-topaddon-margin-toptext-padding-left->padding-lefttext-padding-right->padding-righttext-padding-top->padding-toptext-border-color->border-colortext-filled-color->filled-colortext-height->height
text-area-text-area-get-var,text-area-use-var,text-area-set-vartextarea-padding->padding
slider-slider-get-var,slider-use-var,slider-set-varswitch-switch-get-var,switch-use-var,switch-set-vartrack-background-color
- the following form theme variables were removed:
error-colorerror-hover-colordisabled-colortoggle-insettoggle-dense-insetindeterminate-heightindeterminate-dense-heightfloating-dense-toplistbox-background-colortext-offsettext-active-colortext-border-hover-colortext-label-heighttext-label-dense-heighttext-placeholder-heighttext-placeholder-dense-height
- the following functions, mixins, and variables have been removed:
@function rmd-form-theme@mixin rmd-label$rmd-label-floating-font-size$rmd-text-field-filled-border-radius$rmd-listbox-elevation$rmd-listbox-light-background-color$rmd-listbox-dark-elevation-background-color$rmd-listbox-dark-background-color$rmd-listbox-background-color$rmd-listbox-z-index$rmd-option-focused-styles$rmd-option-selected-offset$rmd-option-selected-content$rmd-option-horizontal-padding$rmd-text-field-active-color$rmd-form-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-form-theme-var->form-get-var@mixin rmd-form-theme->form-use-var@mixin rmd-form-theme-update-var->form-set-var@mixin react-md-form:@mixin form-message-styles@mixin fieldset-styles@mixin label-styles@mixin text-field-styles@mixin text-area-styles@mixin password-styles@mixin slider-styles@mixin input-toggle-styles@mixin switch-styles@mixin files-styles
$rmd-label-font-size->$label-font-size$rmd-label-floating-padding->$label-floating-padding$rmd-label-floating-top->$label-floating-y$rmd-label-floating-dense-top->$label-floating-y-dense$rmd-label-padding->$label-floating-padding$rmd-select-native-multiple-padding->$select-native-select-multiple-padding$rmd-select-native-addon-top->$select-native-select-addon-top$rmd-option-selected-styles->$select-option-selected-styles$rmd-slider-include-vertical->$slider-disable-vertical$rmd-slider-size->$slider-size$rmd-slider-vertical-size->$slider-vertical-size$rmd-slider-active-track-size->$slider-track-active-size$rmd-slider-active-track-color->$slider-track-active-color$rmd-slider-active-track-opacity->$slider-track-active-opacity$rmd-slider-inactive-track-size->$slider-track-inactive-size$rmd-slider-inactive-track-color->$slider-track-inactive-color$rmd-slider-disabled-track-color->$slider-track-disabled-color$rmd-slider-disabled-thumb-color->$slider-thumb-disabled-color$rmd-slider-inactive-track-opacity->$slider-track-inactive-opacity$rmd-slider-inactive-track-z-index->$slider-track-inactive-z-index$rmd-slider-active-track-z-index->$slider-track-active-z-index$rmd-slider-thumb-size->$slider-thumb-size$rmd-slider-thumb-radius->$slider-thumb-border-radius$rmd-slider-thumb-z-index->$slider-thumb-z-index$rmd-slider-thumb-bubble-opacity->$slider-thumb-bubble-opacity$rmd-slider-thumb-focus-scale->$slider-thumb-focus-scale$rmd-slider-thumb-active-scale->$slider-thumb-active-scale$rmd-slider-thumb-disabled-scale->$slider-thumb-disabled-scale$rmd-slider-thumb-disabled-mask-scale->$slider-thumb-disabled-mask-scale$rmd-slider-thumb-value-caret-size->$slider-tooltip-caret-size$rmd-slider-thumb-value-offset->$slider-tooltip-offset$rmd-slider-container-padding->$slider-container-padding$rmd-slider-container-addon-spacing->$slider-container-addon-spacing$rmd-text-field-light-border-color->$text-field-light-border-color$rmd-text-field-dark-border-color->$text-field-dark-border-color$rmd-text-field-border-color->$text-field-border-color$rmd-text-field-light-border-hover-color->$text-field-light-hover-border-color$rmd-text-field-dark-border-hover-color->$text-field-dark-hover-border-color$rmd-text-field-border-hover-color->$text-field-hover-border-color$rmd-text-field-border-radius->$text-field-border-radius$rmd-text-field-border-width->$text-field-border-width$rmd-text-field-border-width-active->$text-field-border-width-active$rmd-text-field-label-height->$text-field-label-height$rmd-text-field-label-dense-height->$text-field-label-dense-height$rmd-text-field-height->$text-field-height$rmd-text-field-dense-height->$text-field-dense-height$rmd-text-field-outline-padding->$text-field-outlined-padding$rmd-text-field-underline-label-padding-top->$text-field-underlined-label-padding-top$rmd-text-field-underline-label-left-offset->$text-field-underlined-label-left-offset$rmd-text-field-underline-dense-padding-top->$text-field-underlined-placeholder-addon-padding-top$rmd-text-field-underline-padding->$text-field-underlined-padding$rmd-text-field-filled-padding->$text-field-filled-padding$rmd-text-field-filled-light-background-color->$text-field-light-filled-background-color$rmd-text-field-filled-dark-background-color->$text-field-dark-filled-background-color$rmd-text-field-filled-background-color->$text-field-filled-background-color$rmd-text-field-addon-margin->$text-field-addon-margin$rmd-textarea-vertical-padding->$text-area-vertical-padding$rmd-textarea-addon-top->$text-area-addon-top$rmd-form-message-min-height->$form-message-min-height$rmd-form-message-margin-top->$form-message-margin-top$rmd-form-message-margin-bottom->$form-message-margin-bottom$rmd-form-message-counter-spacing->$form-message-counter-spacing$rmd-form-message-font-size->$form-message-font-size
Icon 🔧
- the icon theme API renamed the following variables;
text-spacing->spacing
- the following functions, mixins, and variables have been removed:
@function rmd-icon-theme@mixin rmd-icon-base@mixin rmd-icon-font@mixin rmd-icon-dense-theme@mixin rmd-icon-svg@mixin rmd-icon-text-icon-spacing@mixin rmd-icon-spaced-with-text@mixin rmd-icon-icon-rotator@mixin rmd-icon@mixin rmd-icon-spacing@mixin rmd-icon-material-icons-font-face@mixin rmd-icon-material-icons-class@mixin rmd-icon-host-material-icons$rmd-icon-material-icons-font$rmd-icon-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-icon-theme-var->icon-get-var@mixin rmd-icon-theme->icon-use-var@mixin rmd-icon-theme-update-var->icon-set-var@mixin react-md-icon->icon-styles$rmd-icon-color->$icon-color$rmd-icon-size->$icon-size$rmd-icon-dense-size->$icon-dense-size$rmd-icon-include-dense->$icon-disable-dense$rmd-icon-use-font-icons->$icon-disable-font$rmd-icon-use-svg-icons->$icon-disable-svg$rmd-icon-spacing-with-text->$icon-spacing$rmd-icon-rotator-transition-time->$icon-rotate-duration$rmd-icon-rotator-from->$icon-rotate-from$rmd-icon-rotator-to->$icon-rotate-to
Layout 🔧
- the layout theme API renamed the following variables:
nav-width->size
- the layout theme API no longer supports the following variables:
mini-nav-widthmain-offset
- the following functions, mixins, and variables have been removed:
@function rmd-layout-theme$rmd-layout-main-focus-shadow$rmd-layout-navigation-mini-z-index$rmd-layout-mini-navigation-width$rmd-layout-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-layout-theme-var->layout-get-var@mixin rmd-layout-theme->layout-use-var@mixin rmd-layout-theme-update-var->layout-set-var@mixin react-md-layout->layout-styles$rmd-layout-enter-duration->$layout-enter-duration$rmd-layout-leave-duration->$layout-leave-duration$rmd-layout-main-focus-z-index->$layout-main-focus-z-index$rmd-layout-navigation-z-index->$layout-navigation-z-index$rmd-layout-navigation-width->$layout-navigation-static-width
Link 🔧
- the following functions, mixins, and variables have been removed:
@function rmd-link-theme@mixin rmd-link@mixin rmd-link-skip$rmd-link-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-link-theme-var->link-get-var@mixin rmd-link-theme->link-use-var@mixin rmd-link-theme-update-var->link-set-var@mixin react-md-link->link-styles$rmd-link-transition-time->$link-transition-duration$rmd-link-color->$link-color$rmd-link-visited-color->$link-visited-color$rmd-link-hover-color->$link-hover-color$rmd-link-skip-z-index->$link-skip-to-main-z-index$rmd-link-skip-styles->$link-skip-to-main-styles$rmd-link-skip-active-styles->$link-skip-to-main-active-styles
List 🔧
- the list theme API no longer supports the following variables:
vertical-paddinghorizontal-paddingfont-sizetext-keylineitem-heightitem-medium-heightitem-large-heightitem-extra-large-heightitem-three-line-heightitem-vertical-paddingitem-horizontal-paddingitem-secondary-three-line-heightdense-font-sizedense-vertical-paddingdense-horizontal-paddingdense-item-heightdense-item-medium-heightdense-item-large-heightdense-item-extra-large-heightdense-item-three-line-heightdense-item-secondary-three-line-heightmedia-sizemedia-spacingmedia-large-size
- the following functions, mixins, and variables have been removed:
@function rmd-list-theme@mixin rmd-list-unstyled@mixin rmd-list-dense-theme@mixin rmd-list@mixin rmd-list-item-base@mixin rmd-list-item-dense-theme@mixin rmd-list-item-addon-spacing@mixin rmd-list-item@mixin rmd-list-subheader$rmd-list-line-height$rmd-list-font-size$rmd-list-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-list-theme-var->list-get-var@mixin rmd-list-theme->list-use-var@mixin rmd-list-theme-update-var->list-set-var@mixin react-md-list->list-styles$rmd-list-vertical-padding->$list-vertical-padding$rmd-list-dense-vertical-padding->$list-dense-vertical-padding$rmd-list-horizontal-padding->$list-horizontal-padding$rmd-list-dense-horizontal-padding->$list-dense-horizontal-padding$rmd-list-dense-font-size->$list-dense-font-size$rmd-list-item-vertical-padding->$list-item-vertical-padding$rmd-list-item-horizontal-padding->$list-item-horizontal-padding$rmd-list-item-height->$list-item-height$rmd-list-item-dense-height->$list-item-dense-height$rmd-list-item-medium-height->$list-item-medium-height$rmd-list-item-dense-medium-height->$list-item-dense-medium-height$rmd-list-item-large-height->$list-item-large-height$rmd-list-item-dense-large-height->$list-item-dense-large-height$rmd-list-item-extra-large-height->$list-item-extra-large-height$rmd-list-item-dense-extra-large-height->$list-item-dense-extra-large-height$rmd-list-item-three-line-height->$list-item-mulitline-height$rmd-list-item-dense-three-line-height->$list-item-dense-mulitline-height$rmd-list-item-secondary-text-line-height->$list-item-secondary-text-line-height$rmd-list-item-secondary-text-three-line-max-height->$list-item-mulitline-max-height$rmd-list-item-dense-secondary-text-three-line-max-height->$list-item-dense-mulitline-max-height$rmd-list-item-text-keyline->$list-item-keyline$rmd-list-item-media-size->$list-item-media-size$rmd-list-item-media-large-size->$list-item-media-large-size$rmd-list-item-media-spacing->$list-item-media-spacing$rmd-list-item-disabled-opacity->$list-item-disabled-opacity
Media 🔧
- the following functions, mixins, and variables have been removed:
@function rmd-media-theme@mixin rmd-media-responsive-item@mixin rmd-media-overlay-position$rmd-media-default-aspect-ratio$rmd-media-overlay-positions- use$responsive-item-disable-overlay-{top|right|bottom|left|middle|center|absoluite-center}variables instead$rmd-media-theme-values
- the following functions, mixins, and variables have been renamed:
@mixin react-md-media->responsive-item-styles@mixin rmd-media-aspect-ratio->responsive-item-aspect-ratio@mixin rmd-media-aspect-ratio-container->responsive-item-aspect-ratio-container@mixin rmd-media-forced-aspect-ratio-item->responsive-item-forced-aspect-ratio@mixin rmd-media-overlay->responsive-item-overlay-styles@mixin rmd-media-container->responsive-item-base-styles$rmd-media-selectors->$responsive-item-selectors$rmd-media-default-aspect-ratios->$responsive-item-default-aspect-ratios$rmd-media-overlay-background-color->$responsive-item-overlay-background-color$rmd-media-overlay-padding->$responsive-item-overlay-padding$rmd-media-overlay-horizontal-width->$responsive-item-overlay-horizontal-width
Overlay 🔧
- the overlay theme API no longer supports the
active-opacityvariable - the following functions, mixins, and variables have been removed:
@function rmd-overlay-theme@mixin rmd-overlay$rmd-overlay-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-overlay-theme-var->overlay-get-var@mixin rmd-overlay-theme->overlay-use-var@mixin rmd-overlay-theme-update-var->overlay-set-var@mixin react-md-overlay->overlay-styles$rmd-overlay-z-index->$overlay-z-index$rmd-overlay-transition-duration->$overlay-transition-duration$rmd-overlay-color->$overlay-background-color
Progress 🔧
- the progress theme API renamed
circular-widthtocircular-stroke-width - the following functions, mixins, and variables have been removed:
@function rmd-progress-theme@mixin rmd-progress-animation@mixin rmd-linear-progress-styles@mixin rmd-linear-progress-bar@mixin rmd-linear-progress@mixin rmd-circular-progress$rmd-progress-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-progress-theme-var->progress-get-var@mixin rmd-progress-theme->progress-use-var@mixin rmd-progress-theme-update-var->progress-set-var@mixin react-md-progress->progress-styles$rmd-progress-include-linear->$progress-disable-linear$rmd-progress-include-circular->$progress-disable-circular$rmd-progress-color->$progress-color$rmd-progress-background-color->$progress-background-color$rmd-linear-progress-size->$progress-linear-size$rmd-linear-progress-transition-duration->$progress-linear-transition-duration$rmd-linear-progress-short-animation-delay->$progress-linear-short-animation-delay$rmd-linear-progress-styles->$progress-linear-styles$rmd-linear-progress-short-styles->$progress-linear-short-styles$rmd-linear-progress-reverse-styles->$progress-linear-reverse-styles$rmd-linear-progress-reverse-short-styles->$progress-linear-reverse-short-styles$rmd-linear-progress-vertical-styles->$progress-linear-vertical-styles$rmd-linear-progress-vertical-short-styles->$progress-linear-vertical-short-styles$rmd-linear-progress-vertical-reverse-styles->$progress-linear-vertical-reverse-styles$rmd-linear-progress-vertical-reverse-short-styles->$progress-linear-vertical-reverse-short-styles$rmd-circular-progress-size->$progress-circular-size$rmd-circular-progress-small-size->$progress-circular-dense-size$rmd-circular-progress-stroke-width->$progress-circular-stroke-width$rmd-circular-progress-dasharray->$progress-circular-dasharray$rmd-circular-progress-transition-duration->$progress-circular-transition-duration$rmd-circular-progress-start-offset->$progress-circular-start-offset$rmd-circular-progress-end-offset->$progress-circular-end-offset$rmd-circular-progress-rotate-styles->$progress-circular-rotate-styles$rmd-circular-progress-dash-styles->$progress-circular-dash-styles
Sheet 🔧
- the sheet theme API renamed the following variables:
touchable-max-height->touch-max-height
- the sheet theme API no longer supports the following variables:
background-colorraised-background-color
- the following functions, mixins, and variables have been removed:
@function rmd-sheet-theme@mixin rmd-sheet-positions@mixin rmd-sheet$rmd-sheet-overlay-z-index$rmd-sheet-light-background-color$rmd-sheet-dark-elevation-background-color$rmd-sheet-dark-background-color$rmd-sheet-background-color$rmd-sheet-raised-light-background-color$rmd-sheet-raised-dark-elevation-background-color$rmd-sheet-raised-dark-background-color$rmd-sheet-raised-background-color$rmd-sheet-positions$rmd-sheet-enabled-positions- use
$sheet-disable-position-{left|right|bottom|top}variables instead
- use
$rmd-sheet-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-sheet-theme-var->sheet-get-var@mixin rmd-sheet-theme->sheet-use-var@mixin rmd-sheet-theme-update-var->sheet-set-var@mixin react-md-sheet->sheet-styles$rmd-sheet-z-index->$sheet-z-index$rmd-sheet-raised-z-index->$sheet-raised-z-index$rmd-sheet-elevation->$sheet-elevation$rmd-sheet-raised-elevation->$sheet-raised-elevation$rmd-sheet-enter-duration->$sheet-enter-duration$rmd-sheet-leave-duration->$sheet-leave-duration$rmd-sheet-touch-margin->$sheet-touch-margin$rmd-sheet-touch-width->$sheet-touch-width$rmd-sheet-static-width->$sheet-static-width$rmd-sheet-max-height->$sheet-max-height$rmd-sheet-touchable-max-height->$sheet-touch-max-height$rmd-sheet-recommended-min-height->$sheet-recommended-min-height$rmd-sheet-recommended-max-height->$sheet-recommended-max-height
States 🔧
- the states theme API renamed the following variables:
hover-color->hover-background-colorfocus-color->focus-background-colorpressed-color->press-background-colorselected-color->selected-background-color
- the states theme API no longer removed the following variables:
focus-shadowlight-hover-colorlight-focus-colorlight-pressed-colorlight-selected-colorlight-ripple-background-colordark-hover-colordark-focus-colordark-pressed-colordark-selected-colordark-ripple-background-color
- the following functions, mixins, and variables have been removed:
@function rmd-states-theme$rmd-states-use-ripple- use$interaction-mode: noneor$interaction-mode: pressinstead$rmd-states-use-pressed-states-fallback- use$interaction-mode: pressinstead$rmd-states-background-color$rmd-states-focus-shadow$rmd-states-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-states-theme-var->interaction-get-var@mixin rmd-states-theme->interaction-use-var@mixin rmd-states-theme-update-var->interaction-set-var@mixin react-md-states->interaction-styles$rmd-states-use-focus-shadow->$interaction-focus-box-shadowand changed the default value fromtruetofalse$rmd-states-use-focus-background->$interaction-disable-focus-background$rmd-states-light-theme-background-color->$interaction-light-surface-base-background-color$rmd-states-dark-theme-background-color->$interaction-dark-surface-base-background-color$rmd-states-light-theme-hover-color->$interaction-light-surface-hover-color$rmd-states-light-theme-focus-color->$interaction-light-surface-focus-color$rmd-states-light-theme-pressed-color->$interaction-light-surface-pressed-color$rmd-states-light-theme-selected-color->$interaction-light-surface-selected-color$rmd-states-dark-theme-hover-color->$interaction-dark-surface-hover-color$rmd-states-dark-theme-focus-color->$interaction-dark-surface-focus-color$rmd-states-dark-theme-pressed-color->$interaction-dark-surface-pressed-color$rmd-states-dark-theme-selected-color->$interaction-dark-surface-selected-color$rmd-states-light-theme-ripple-background-color->$interaction-light-surface-ripple-background-color$rmd-states-dark-theme-ripple-background-color->$interaction-dark-surface-ripple-background-color$rmd-states-hover-color->$interaction-hover-color$rmd-states-focus-color->$interaction-focus-color$rmd-states-pressed-color->$interaction-pressed-color$rmd-states-selected-color->$interaction-selected-color$rmd-states-focus-shadow-width->$interaction-focus-width$rmd-states-focus-shadow-color->$interaction-focus-color$rmd-states-ripple-background-color->$interaction-ripple-background-color$rmd-states-ripple-transform-duration->$interaction-ripple-transform-duration$rmd-states-ripple-opacity-duration->$interaction-ripple-opacity-duration$rmd-states-pressed-class-name->$interaction-pressed-class-name- this value is no longer configurable
- this value is changed from
.rmd-states--pressedtormd-pressed
Table 🔧
- the table theme API renamed the following variables:
cell-h-padding->cell-horizontal-paddingcell-v-padding->cell-vertical-padding
- the table theme API removed the following variables:
cell-dense-height
- the following functions, mixins, and variables have been removed:
@function rmd-table-theme@mixin rmd-table@mixin rmd-thead@mixin rmd-table-cell-horizontal-alignments@mixin rmd-table-cell-vertical-alignments@mixin rmd-table-cell@mixin rmd-table-row$rmd-table-cell-horizontal-alignments$rmd-table-cell-vertical-alignments- use$table-disable-cell-align-{top|bottom}instead$rmd-table-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-table-theme-var->table-get-var@mixin rmd-table-theme->table-use-var@mixin rmd-table-theme-update-var->table-set-var@mixin react-md-table->table-styles$rmd-table-light-border-color->$table-light-theme-border-color$rmd-table-dark-border-color->$table-dark-theme-border-color$rmd-table-border-color->$table-border-color$rmd-table-cell-horizontal-padding->$table-cell-horizontal-padding$rmd-table-cell-vertical-padding->$table-cell-vertical-padding$rmd-table-cell-sticky-position->$table-sticky-cell-position$rmd-table-cell-sticky-z-index->$table-sticky-cell-z-index$rmd-table-cell-height->$table-cell-height$rmd-table-cell-dense-height->$table-cell-dense-height$rmd-table-cell-color->$table-cell-color$rmd-table-header-cell-height->$table-cell-header-height$rmd-table-header-cell-dense-height->$table-cell-header-dense-height$rmd-table-header-cell-color->$table-cell-header-color$rmd-table-header-sticky-position->$table-sticky-header-position$rmd-table-row-hover-color->$table-row-hover-color$rmd-table-row-selected-color->$table-row-selected-color$rmd-table-footer-sticky-position->$table-sticky-footer-position$rmd-table-checkbox-padding->$table-cell-input-toggle-horizontal-padding
Tabs 🔧
- the tabs theme API renamed the following variables:
active->active-colorinactive->inactive-colordisabled->disabled-colorindicator-color->indicator-background
- the following functions, mixins, and variables have been removed:
@function rmd-tabs-theme@mixin rmd-tabs@mixin rmd-tab@mixin rmd-tab-panels@mixin rmd-tab-panel$rmd-tabs-positions$rmd-tab-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-tabs-theme-var->tabs-get-var@mixin rmd-tabs-theme->tabs-use-var@mixin rmd-tabs-theme-update-var->tabs-set-var@mixin react-md-tabs->tabs-styles$rmd-tab-height->$tabs-height$rmd-tab-stacked-height->$tabs-stacked-height$rmd-tab-horizontal-padding->$tabs-horizontal-padding$rmd-tab-vertical-padding->$tabs-vertical-padding$rmd-tab-min-width->$tabs-min-width$rmd-tab-max-width->$tabs-max-width$rmd-tab-indicator-color->$tabs-indicator-background$rmd-tab-active-color->$tabs-active-color$rmd-tab-inactive-color->$tabs-inactive-color$rmd-tab-disabled-color->$tabs-disabled-color$rmd-tab-active-indicator-height->$tabs-indicator-height$rmd-tabs-scrollable-padding->$tabs-tablist-scrollable-horizontal-padding
Tooltip 🔧
- the tooltip theme API no longer supports the following variables:
spacingfont-sizeline-heightdense-spacingdense-font-sizedense-line-height
- the following functions, mixins, and variables have been removed:
@function rmd-tooltip-theme@function rmd-tooltip-position-to-property@function rmd-tooltip-inverse-position@mixin rmd-tooltip-base@mixin rmd-tooltip-line-wrap@mixin rmd-tooltip$rmd-tooltip-font-size- use$tooltip-typographyinstead$rmd-tooltip-line-height- use$tooltip-typographyinstead$rmd-tooltip-dense-font-size- use$tooltip-dense-typographyinstead$rmd-tooltip-dense-line-height- use$tooltip-dense-typographyinstead$rmd-tooltip-line-wrap-vertical-padding$rmd-tooltip-dense-line-wrap-vertical-padding$rmd-tooltip-position-values- use$tooltip-disable-{above|below|left|right}variables instead$rmd-tooltip-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-tooltip-theme-var->tooltip-get-var@mixin rmd-tooltip-theme->tooltip-use-var@mixin rmd-tooltip-theme-update-var->tooltip-set-var@mixin rmd-tooltip-dense-theme->tooltip-dense-variables@mixin react-md-tooltip->tooltip-styles$rmd-tooltip-background-color->$tooltip-background-color$rmd-tooltip-color->$tooltip-color$rmd-tooltip-max-width->$tooltip-max-width$rmd-tooltip-enter-duration->$tooltip-enter-duration$rmd-tooltip-exit-duration->$tooltip-leave-duration$rmd-tooltip-z-index->$tooltip-z-index$rmd-tooltip-min-height->$tooltip-min-height$rmd-tooltip-horizontal-padding->$tooltip-horizontal-padding$rmd-tooltip-spacing->$tooltip-spacing$rmd-tooltip-dense-min-height->$tooltip-dense-min-height$rmd-tooltip-dense-horizontal-padding->$tooltip-dense-horizontal-padding$rmd-tooltip-dense-spacing->$tooltip-dense-spacing$rmd-tooltip-border-radius->$tooltip-border-radius$rmd-tooltip-transition-distance->$tooltip-transition-distance
Transition 🔧
- the following functions, mixins, and variables have been removed:
@mixin rmd-transition@mixin rmd-transition-parent-shadow@mixin rmd-transition-pseudo-shadow@mixin rmd-collapse@mixin rmd-cross-fade$rmd-collapse-enter-transition-func$rmd-collapse-leave-transition-func$rmd-transitions
- the following functions, mixins, and variables have been renamed:
@mixin rmd-transition-shadow-transition->box-shadow-transition@mixin rmd-transition-classes->rmd-scale-transitionandrmd-scale-y-transition@mixin react-md-transition->transition-styles$rmd-transition-sharp->$sharp-timing-function$rmd-transition-standard->$standard-timing-function$rmd-transition-acceleration->$acceleration-timing-function$rmd-transition-deceleration->$deceleration-timing-function$rmd-transition-standard-time->$linear-duration$rmd-transition-enter-duration->$enter-duration$rmd-transition-leave-duration->$leave-duration$rmd-cross-fade-translate-distance->$cross-fade-translate-distance$rmd-cross-fade-transition-duration->$cross-fade-transition-duration$rmd-transition-scale-enter-duration->$scale-transition-enter-duration$rmd-transition-scale-leave-duration->$scale-transition-leave-duration$rmd-transition-scale-y-enter-duration->$scale-y-transition-enter-duration$rmd-transition-scale-y-leave-duration->$scale-y-transition-leave-duration
Tree 🔧
- the tree theme API renamed the following variables:
incrementor->item-padding-incrementorbase-padding->item-padding-base
- the following functions, mixins, and variables have been removed:
@function rmd-tree-theme@mixin rmd-tree-depths@mixin rmd-tree-item-at-depth@mixin rmd-tree@mixin rmd-tree-item@mixin rmd-tree-group$rmd-tree-item-focused-styles$rmd-tree-item-keyboard-focused-styles$rmd-tree-max-depth$rmd-tree-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-tree-theme-var->tree-get-var@mixin rmd-tree-theme->tree-use-var@mixin rmd-tree-theme-update-var->tree-set-var@mixin react-md-tree->tree-styles$rmd-tree-item-padding-incrementor->$tree-item-padding-incrementor$rmd-tree-item-padding-base->$tree-item-padding-base
Typography 🔧
- the typography theme API renamed the following variables:
line-width->line-length
- the typography theme API removed the following variables:
mobile-line-widthdesktop-line-width
- the following functions, mixins, and variables have been removed:
@function rmd-typography-theme@function rmd-typography-value@function rmd-typography-google-font-suffix@mixin rmd-typography-value@mixin rmd-typography-base@mixin rmd-typography@mixin rmd-text-container-base@mixin rmd-text-container-auto@mixin rmd-text-container@mixin rmd-typography-google-font-face@mixin rmd-typography-host-google-font$rmd-typography-mobile-max-line-length$rmd-typography-desktop-max-line-length$rmd-typography-colors$rmd-typography-google-font-weight-suffixes$rmd-typography-text-container-breakpoint$rmd-typography-theme-values
- the following functions, mixins, and variables have been renamed:
@function rmd-typography-theme-var->typography-get-var@mixin rmd-typography-theme->typography-use-var@mixin rmd-typography-theme-update-var->typography-set-var@mixin rmd-typography-text-overflow-ellipsis->text-overflow@mixin rmd-typography-line-clamp->line-clamp@mixin react-md-typography->typography-styles$rmd-typography-font-family->$font-family$rmd-typography-base->$base-font-styles$rmd-typography-thin->$font-weight-thin$rmd-typography-light->$font-weight-light$rmd-typography-regular->$font-weight-regular$rmd-typography-medium->$font-weight-medium$rmd-typography-bold->$font-weight-bold$rmd-typography-semi-bold->$font-weight-semi-bold$rmd-typography-black->$font-weight-black$rmd-typography-font-weights->$font-weights$rmd-typography-default-font-weights->$font-weights$rmd-typography-alignments->$text-alignments$rmd-typography-decorations->$text-decorfations$rmd-typography-transforms->$text-transforms$rmd-typography-font-styles->$font-styles$rmd-typography-default-headline-1-styles->$headline-1-recommended-styles$rmd-typography-headline-1-styles->$headline-1-custom-styles$rmd-typography-default-headline-2-styles->$headline-2-recommended-styles$rmd-typography-headline-2-styles->$headline-2-custom-styles$rmd-typography-default-headline-3-styles->$headline-3-recommended-styles$rmd-typography-headline-3-styles->$headline-3-custom-styles$rmd-typography-default-headline-4-styles->$headline-4-recommended-styles$rmd-typography-headline-4-styles->$headline-4-custom-styles$rmd-typography-default-headline-5-styles->$headline-5-recommended-styles$rmd-typography-headline-5-styles->$headline-5-custom-styles$rmd-typography-default-headline-6-styles->$headline-6-recommended-styles$rmd-typography-headline-6-styles->$headline-6-custom-styles$rmd-typography-default-subtitle-1-styles->$subtitle-1-recommended-styles$rmd-typography-subtitle-1-styles->$subtitle-1-custom-styles$rmd-typography-default-subtitle-2-styles->$subtitle-2-recommended-styles$rmd-typography-subtitle-2-styles->$subtitle-2-custom-styles$rmd-typography-default-body-1-styles->$body-1-recommended-styles$rmd-typography-body-1-styles->$body-1-custom-styles$rmd-typography-default-body-2-styles->$body-2-recommended-styles$rmd-typography-body-2-styles->$body-2-custom-styles$rmd-typography-default-caption-styles->$caption-recommended-styles$rmd-typography-caption-styles->$caption-custom-styles$rmd-typography-default-button-styles->$button-recommended-styles$rmd-typography-button-styles->$button-custom-styles$rmd-typography-default-overline-styles->$overline-recommended-styles$rmd-typography-overline-styles->$overline-custom-styles$rmd-typography-styles->$typography-styles
Utils 🔧
- the following functions, mixins, and variables have been removed:
rmd-utils-rtl-autormd-utils-rtl-auto-grouprmd-utils-block-centeredrmd-utils-absolute-centeredrmd-utils-scrollrmd-utils-hide-focus-outlinermd-utils-full-screenrmd-utils-sr-only-focusablermd-grid- try using the new Box component instead!rmd-grid-cell-fullrmd-grid-cell-sizermd-grid-cellrmd-grid-list-cell-sizermd-grid-list-cellrmd-grid-listreact-md-utils-gridrmd-utils-dense$rmd-grid-columns-var$rmd-grid-gutter-var$rmd-grid-cell-margin-var$rmd-grid-cell-size-var$rmd-grid-padding$rmd-grid-cell-margin$rmd-grid-columns$rmd-grid-phone-columns$rmd-grid-tablet-columns$rmd-grid-desktop-columns$rmd-grid-large-desktop-columns$rmd-grid-list-padding$rmd-grid-list-cell-margin$rmd-grid-list-cell-max-size$rmd-utils-ios-scroll-momentum$rmd-utils-auto-dense$rmd-utils-swappable-positions$rmd-utils-swappable-position-prefixes$rmd-utils-fix-moz-focus
- the following functions, mixins, and variables have been renamed:
@function rmd-utils-validate->validate@function rmd-utils-swap-position->swap-position@function rmd-utils-negate-var->negate-var@mixin rmd-utils-map-to-styles->map-to-styles@mixin rmd-utils-rtl->@rtl@mixin rmd-utils-pseudo-element->pseudo-element@mixin rmd-utils-sr-only->sr-only@mixin rmd-utils-hide-scrollbar->hide-scrollbar@mixin rmd-utils-phone-media->phone-media@mixin rmd-utils-tablet-media->tablet-media@mixin rmd-utils-tablet-only-media->tablet-only-media@mixin rmd-utils-desktop-media->desktop-media@mixin rmd-utils-large-desktop-media->large-desktop-media@mixin rmd-utils-optional-css-modules->optional-css-modules@mixin rmd-utils-touch-only->touch-only@mixin rmd-utils-keyboard-only->keyboard-only@mixin rmd-utils-mouse-only->mouse-only@mixin rmd-utils-base->css-reset@mixin react-md-utils->styles- NOTE: Since the global dense theme has been removed, this will not enable the dense mode for desktops automatically
$rmd-utils-enable-rtl->$disable-rtl$rmd-utils-temporary-element-z-index->$utils-temporary-element-z-index$rmd-utils-skip-validation->$disable-validation$rmd-utils-phone-max-width->$phone-max-width$rmd-utils-tablet-min-width->$tablet-min-width$rmd-utils-tablet-max-width->$tablet-max-width$rmd-utils-desktop-min-width->$desktop-min-width$rmd-utils-large-desktop-min-width->$large-desktop-min-width