Description
Introduction
Material-UI v4 was released 10 months ago, per our release schedule. It's time to plan for v5.
Our GitHub milestone has a due date for October 1st 2020, and while I doubt we will release in time, planning 6 months ahead seems relevant.
Developers made it clear in the past that they don't enjoy breaking changes. This is feedback we took into consideration when designing our versioning strategy, and for each minor/patch releases. The result was to commit to a minimum of 1 year between each major release.
At the same time, the v0 to v1 upgrade was a major breaking change (a rewrite with a brand new API) and yet it was successful. I think that we should be willing (taking the risk) to make bold changes, as long as they fit in the direction we see the community going in the long term (with Material-UI empowering it).
Structural changes
1. Unstyled components
Similar to Angular Material CDK components (Component Development Kit) #6218.
In practice, it could be a new hook version of all the components, something we have started to experiment with the useAutocomplete
and usePagination
in the lab.
The problem:
- The React OSS component community is fragmented. You will find both standalone components for a specific problem, as well as and a growing number of component libraries, with a wide range of API consistency, a11y, bug density, performance, bundle size, quality, and support.
- Styling solution usage is fragmented. We can get a glimpse of this by looking at the CodeSandbox usage stats for the style interoperability page:
- plain css: 34%
- styled components: 30%
- global css: 18%
- css modules: 12%
- emotion: 5%
- Developers and designers use different design systems. Material Design doesn't have a monopoly.
- How can we help with the unstyled story of notistack, raised by @iamhosseindhv?
Why this solution?:
- This will enable Material-UI to stay relevant in the long term. This is a cornerstone of our strapline. It will shift the developer's perception, that Material-UI is, at its core, about providing material to build UIs.
React components for faster and easier web development. Build your own design system, or start with Material Design.
- Talking with backend and fullstack users, we know that they are craving for a single component store rather than having to deal with a wide range of dependencies. We could expect the same from front-end developers.
- This new "offering" should better resonate with front-end developers. We could expect to gain more and higher quality contributions from the front-end community thanks to this shift.
- Based of our current trust, usage, and exposure in the React community, we are well-positioned to gain usage with this new "offering".
- Maintaining standalone components is rarely sustainable. I have seen too many projects left abandoned. But by aggregating them in Material-UI, it helps our flywheel. It can incentivize new maintainers to work on the OSS. It can also strengthen our current monetization channels and invest resources back into the OSS components.
- It's important to support different style engines and design systems.
2. Full strict mode support
The problem:
- While developers can set up strict mode in their app to identify incorrect patterns, Material-UI prevents them from keeping this mode enable on a daily basis, as there would be too much noise in the console. We have, for example, disabled it for the Material-UI documentation.
Why this solution?
- It's the future.
- It helps with the unstyled story.
3. Migrate to styled-components
The problem:
- We have left important issues related to our styling solution unhandled over the last few months: streaming, strict mode, performance, CSS template support, style functions, class name mismatch, etc.
- We need to support dynamic props, this is important for the features we want to implement on the components.
- JSS popularity didn't stick with the front-end community.
Why this solution?
- A migration to styled-components is our most requested (upvoted) issue to date.
- We want to remove the need for the majority of developers to bundle two CSS-in-JS runtimes.
It could be interesting to provide a choice between different style engines. v5's users would be able to replace @material-ui/styles with react-jss.
4. Enable the use of @material-ui/system's props in the core components
The problem
- Naming things is hard.
- Indirections can be inefficient.
Why this solution?
This is mainly driven by the positive feedback Tailwind and styled-system have had recently in the community. I enjoy the pattern a lot for one-off layout problems. It's frustrating that only the Box component supports it. I think that it should also cover #6140.
<Typography textAlign={{ xs: 'left', md: 'center' }} />
<Button mt={3}>
Regarding the implementation and final API, we could still reconsider the tradeoff (relying on global class names rather than style functions).
5. Allow the use of dynamic theme variants and colors
#15573 & #13875. Allow breakpoints customization #11649.
I was wondering about revamping the theme structure to match System-UI Theme Specification
but we don't see a clear win so far.
Material-UI's theme structure, on its own, is a specification, the structure is set.
Assuming that Material-UI aims to support a wide range of components (unstyled or not), matching this spec, not just Material Design,
I fail to see a strong advantage a different constraint could yield.
On the cost side, using theme-specification would require to drop some of the features of our theme and require breaking changes.
The benefit isn't obvious, but it's something to consider.
Regarding styled-system. I think that we should re-evaluate if we still need @material-ui/system.
Material Design
✅ Checklist
- [Checkbox] Make color="primary" the default ([Checkbox] Make color="primary" default #26002)
- [Paper] Dark mode brighening based on elevation Support dark mode brighening based on elevation #18309 ([Paper] Support dark mode brightening based on elevation #25522)
- [Snackbar] Dark mode color [Snackbar] Shouldn't be light in dark mode #24438
- [Tabs] Improve color management [Tabs] Improve color management #24286
- [Switch] Make color="primary" the default (BC: [Switch] Make color primary default #26182)
- [Radio] Make color="primary" the default (BC [Radio] Make color primary default #26180)
- [Tabs] Remove min-width media query [Tabs] Remove min-width media query #15824 (BC: [Tabs] Update
min
&max
width and removeminWidth
media query #26458) - [Select] Update to match the specification [Select] Follow material design guidelines #18493 (BC: [Select] Open popup below button #26200)
- [Dialog] Flatten DialogTitle DOM structure [Dialog] Flatten DialogTitle DOM structure #19696 (BC: [Dialog] Flatten DialogTitle DOM structure, remove
disableTypography
#26323) -
[Button] Reduce the duration of the transition from 250ms to 200ms [website] Add Join Us block #24521 (comment)I don't think this is worth doing now - edited by @siriwatknp -
[Autocomplete] Consistency with select [Select] Consistency with Autocomplete #18136[move to v5.1] - [AppBar] Improve the design [AppBar] Make dark by default for dark themes #18308 (BC: [AppBar] Fix background color on dark mode #26545)
- [Checkbox][Switch] Remove dependency on IconButton Can't override IconButton styles in theme without affecting Checkbox and Switch #21503 (BC: [SwitchBase] Replace IconButton with ButtonBase #26460)
- [docs] Use the default theme [docs] Sync default theme with the theme used by the documentation #22112, Dark mode not applying to textfield or buttons #21040 (comment)
- [theme] Dark mode colors Update dark theme primary and secondary colors #18378
-
Material Design states Implement theme level states design tokens #10870deferred @siriwatknp -
[Tabs] Update to match the specification [Tabs] Update to match the specification #15324deferred (can be workaround by css) @siriwatknp - [theme] Improve the breakpoints values [theme] Improve the breakpoints values #21902
- [Menu] Remove MenuItem dependency on ListItem [Menu] Remove MenuItem dependency on ListItem #21587
- [Slider] Update to match the spec [Slider] Update to match the specification #20153
- [IconButton] Update default size and add
large
[IconButton] Improve size values #24045 -
[Button] Update to match the spec [ButtonBase] Inconsistent ripple style with the material specs #19664deferred @siriwatknp
Lab to core components
I think that we can aim to move the following components from the lab to the core:
✅ Components
- Alert ([Alert] Move from lab to core #22651)
- Autocomplete ([Autocomplete] Move from lab to core #22715)
- AvatarGroup [AvatarGroup] Move to the core #18869 ([AvatarGroup] Move from lab to core #23121)
- Pagination ([Pagination] Move from lab to core #22848)
- Rating ([Rating] Move from lab to core #22725)
- Skeleton ([Skeleton] Move from lab to core #22740)
- SpeedDial (finally!) ([SpeedDial] Move from lab to core #22743)
- Toggle Button ([ToggleButton] Move from lab to core #22784)
The only component I have would propose to handle later on is the TreeView.
We still have a couple of important features to implement, and might need to change the API to ship these features. Once we do, we'll start to get more adoption, so the more likely it is that developers will uncover root issues.
Supported browsers
While we plan to keep IE 11 support until v6,
We will look into proposing different proposing entry points #18447.
and if we can drop older browsers' versions #15496.
Deprecations
✅ List of breaking changes we can introduce with a deprecation during v4.
-
Drop createStyles (see [RFC] Material-UI v5 🚀 #20012 (comment)) -
[Portal] Remove PortaldisablePortal
prop. Maybe we can implement the logic at the Portal component consumer level. [Portal] Support any children node #18692 (comment) - [theme] Remove
theme.mixins.gutters
. I don't believe we document them, nor are they used. (BC: [theme] Remove theme.mixins.gutters #22109, Dep: [theme] Deprecate theme.mixins.gutters #22245) - [theme] Rename theme
type
->mode
. While the spec use "schema", saying "dark mode" seems to be more common, e.g https://css-tricks.com/dark-modes-with-css/. (BC: [theme] Renametype
tomode
#22687, "Dep": [theme] Fix Hidden breakpoints issues and updates the migration guide #22702 –adaptV4Theme()
) - [theme] Rename color helpers [colorManipulator][docs] Document the color helpers #13039 (comment). (BC: [theme] Rename fade to alpha #22834, Dep: [theme] Deprecate
fade
color utility in favor ofalpha
#22837) - [test] Remove enzyme test helpers. They are legacy. It's also a good opportunity to upgrade the documentation [test] Improve the guide documentation page #17070. (BC: [core] Remove /test-utils #21855, [docs] Update testing guide #21863, Dep: [test] Deprecate /test-utils #24074)
- Remove the onX* transition props from Dialog, Snackbar, Menu & Popover, Improve transition documentation #17047 (comment).
(Snackbar BC: [Snackbar] Remove transition onX props #22107, Dep: [Snackbar] Deprecate transition onX props #22206; Popover BC: [Popover] Remove transition onX props #22184, Dep: [Popover] Deprecate transition onX props #22202; Dialog BC: [Dialog] Remove transition onX props #22113, Dep: [Dialog] Deprecate the transition onX props #22114; Menu BC: [Menu] Remove transition onX props #22212, Dep: [Menu] Deprecate transition onX props #22213) - Remove RootRef, it relies on
ReactDOM.findDOMNode(component)
that is already deprecated. (BC: [RootRef] Remove component #21974, Dep: [RootRef] Deprecate component #24075) - [icons] Change default
fontSize
prop's value: default -> medium, for consistency with the other components [Icon] Change default fontSize name #14993. (BC: [Icon][SvgIcon] Change default fontSize from default to medium #23950, Dep: [Icons] deprecatedefault
value forfontSize
in favor ofmedium
#23951) - [Accordion] Normalize focusVisible logic (BC: [Accordion] Normalize focusVisible logic #22567, Dep: [Accordion] Deprecate classes.focused #24083)
- [Avatar] Rename variant circle -> circular for consistency [RFC] Renaming API for consistency #21964. (BC: [Avatar] Rename variant circle -> circular for consistency #22015, Dep: [Avatar] Add circular variant #22090)
- [Badge] Rename overlap circle -> circular and rectangle -> rectangular for consistency [RFC] Renaming API for consistency #21964. (BC: [Badge] Rename overlap circle -> circular and rectangle -> rectangular for consistency #22050, Dep: [Badge] Add overlap circular and rectangular #22076)
- [CircularProgress] Remove one variant. Kill the current
determinate
variant, renamestatic
=>determinate
. [Button] Add loading support #7223 (comment). (BC: [CircularProgress] Remove static variant, simplify determinate #22060, Dep: [CircularProgress] Backport simplified determinate style & deprecate static #22094) - [Collapse] Add orientation and horizontal support (BC: [Collapse] Add orientation and horizontal support #20619, Dep: [Collapse] Deprecate collapsedHeight #24079)
- [Dialog] Remove withMobileDialog. [Dialog] Prepare deprecation of withMobileDialog #14992. We have already removed it from the documentation. (BC: [withMobileDialog] Remove HOC #23202, Dep: [Dialog] Add deprecation warning for withMobileDialog #23570)
- [Dialog][Modal] Remove disableBackdropClick (BC: [Dialog][Modal] Remove disableBackdropClick #23607, Dep: [Modal][Dialog] Deprecate duplicate props with onChange #24081)
- [Fab] Rename Fab round -> circular for consistency [RFC] Renaming API for consistency #21964. (BC: [Fab] Rename round -> circular for consistency #21903, Dep: [Fab] Deprecate variant="round" #24080)
- [Grid] Rename prop justify -> justifyContent to match system API. (BC: [Grid] Rename justify prop to justifyContent #21845, Dep: [Grid] Add deprecation for justify prop rename #24078)
- [GridList] Rename component to ImageList as more intuitive and better match the wording of the Material Design spec [GridList] Deprecate, rename ImageList #14994. (BC: [GridList] Rename to ImageList #22311, Dep: [GridList] Rename to ImageList & add deprecation warnings #22363)
- [GridList] Rename Tile to Item (BC: [ImageList] Rename Tile to Item #22385, Dep: [GridList] Rename to ImageList & add deprecation warnings #22363)
- [GridList] Refactor using CSS grid & React context (BC: [ImageList] Refactor using CSS grid & React context #22395, Dep: [GridList] Rename to ImageList & add deprecation warnings #22363)
- [GridList] Rename
spacing
prop togap
to align with the CSS attribute. (BC: [ImageList] Refactor using CSS grid & React context #22395, Dep: [GridList] Rename to ImageList & add deprecation warnings #22363) - [GridList] Rename the GridList
cellHeight
prop torowHeight
. (BC: [ImageList] Refactor using CSS grid & React context #22395, Dep: [GridList] Rename to ImageList & add deprecation warnings #22363) - [GridList] Rename the GridListItemBar
titlePosition
prop toposition
. (BC: [ImageList] Refactor using CSS grid & React context #22395, Dep: [GridList] Rename to ImageList & add deprecation warnings #22363) - [Modal] Add support for onKeyDown and remove onEscapeKeyDown (BC: [Modal] Add support for onKeyDown and remove onEscapeKeyDown #23571, Dep: [Modal][Dialog] Deprecate duplicate props with onChange #24081)
- [Portal] Remove onRendered -> ref. context: [Modal] Refactor tests to remove internal accesses #16262 (comment). (BC: [core] Remove onRendered from Modal and Portal #22464, Dep: [Modal][Portal] Deprecate onRendered #24082)
- [TextareaAutosize] Rename rowsMax -> maxRows for consistency, (BC: [TextareaAutosize] Rename rowsMax->maxRows & rowsMin->minRows #21873, Dep: [TextareaAutosize] Deprecate rowsMax->maxRows & rowsMin->minRows #23530)
- [Table] Rename onChangeRowsPerPage -> onRowsPerPageChange, onChangePage -> onPageChange for consistency. It's a good opportunity to mention this API design choice in the documentation: https://jaketrent.com/post/naming-event-handlers-react/#more-complicated-naming; (BC: [Table] Rename onChangeRowsPerPage, onChangePage #22900, Dep: [Table] Add deprecation for renamed TablePagination props #23789)
- [theme] Remove the
fade
color helper [colorManipulator][docs] Document the color helpers #13039. (BC: [theme] Remove fade color helper #25895) - [Button] Remove the
buttonRef
prop. (BC: [ButtonBase] Remove buttonRef prop #25896, Dep: [ButtonBase] Add warning for buttonRef removal #25897) - [Popover] Remove
getContentAnchorEl
prop. This method was present to implement a macOS native select like experience. It complicates the implementation of the Popover and could prevent us from moving [Select][material-ui] Don't lock the body scroll and make it non-modal select #17353 forward. - [TextField] The
position
prop should be required inInputAdornment
. (BC: [TextField] Make theposition
prop required in InputAdornment #25891, Dep: [TextField] AddisRequired
to position prop in InputAdornment #25912) - [Button] Change LoadingButton prop pending to loading [Button] Change LoadingButton prop pending to loading #21593 (BC: [Button] Rename
pending
prop toloading
in LoadingButton #25874) - [SwitchBase] Remove second onChange argument: event.target.checked is enough. (BC: [Checkbox][Switch] Remove checked argument from onChange #25871)
- [theme] Remove the exported theme.typography.round helper. (BC: [theme] Remove theme.typography.round helper #25914, Dep: [theme] Add warning for theme.typography.round deprecation #25916)
-
[theme] Remove legacy v4 deprecationObject.defineProperty(spacing, 'unit', {
- ?[theme] Replace
theme.direction === 'rtl'
->theme.isRtl
. - [Table] Rename
padding="default"
->padding="normal"
(BC: [Table] Rename padding="default" to padding="normal" #25924, Dep: [Table] Deprecate padding="default" #25990) - [theme] Remove
function width(key) { return values[key]; }
, it's useless. (BC: [theme] Remove theme.breakpoints.width helper #25918, Dep: [theme] Add warning for theme.breakpoints.width deprecation #25993) - [theme] Rename createMuiTheme -> createTheme to match ThemeProvider's theme prop. (BC: [theme] Rename
createMuiTheme
tocreateTheme
#25992, Dep: [theme] DeprecatecreateMuiTheme
#26004) -
?[theme] Flatten colors to support CSS variables as theme option Support CSS variables as theme option #12827later
For a list of committed breaking changes and associated deprecations, see: #22074
Breaking changes
Unlike the previous section, these are breaking changes we can't gracefully warn against.
-
? [AppBar] Change default position from fixed to static. What's the most frequent AppBar position? -
? Rotate 180° icons to only include one? Involve: TablePagination, Pagination or DatePicker. -
[Slider] Fix the class names naming.track
andrail
means the same thing. -
[Container] Revisit max-width values to be more useful [theme] Improve the breakpoints values #21902
-
[core] Only support node >= 10 [core] Use node 10 in every CI/CD pipeline #19301 (comment) ([core] Ship modern bundle #22814)
-
[theme] Remove dead
palette.text.hint
key -
[theme] Always return value with 'px' unit in the spacing function breaking change enhancement Always return value with 'px' unit in the spacing function #16205 ([theme] Always return default spacing value with px units #22552)
-
[theme] Breakpoints down use interval. Same as https://github.com/ionic-team/ionic/blob/master/BREAKING.md#display-classe [Breakpoints] functions down() and between() adds +1 to index #13448 ([theme] Improve breakpoints definitions #22695)
-
[Chip] Change variant default value [Chip] variant default value #18914 ([Chip] Rename
default
variant tofilled
#22683) -
[Divider] Use border instead of block content ([Divider] Use border instead of background color #18965)
-
[Pagination] Rename round -> circular for consistency [RFC] Renaming API for consistency #21964. ([Pagination] Rename round -> circular for consistency #22009)
-
[Popper] Figure out what we do with popper.js, we have 4 options upgrade, remove it, rewrite it, fork it Popper changed home #19358 ([Popper] Upgrade to popper.js to v2 #21761)
-
[Skeleton] Rename variant circle -> circular and rect -> rectangular for consistency [RFC] Renaming API for consistency #21964. ([Skeleton] Rename variant circle -> circular and rect -> rectangular for consistency #22053)
-
[Slider] Custom tooltip ignores valueLabelFormat and valueLabelDisplay [Slider] Custom tooltip ignores valueLabelFormat and valueLabelDisplay #17905.
-
[Snackbar] Change default position. Change the default position of the snackbar on desktop to bottom left. This will better be aligned to the behavior of material.io, Gmail, Google Keep, notistack, etc. ([Snackbar] Change the default position on desktop #21980)
-
[Stepper] Remove Paper component [Stepper] Remove Paper component #18423 ([Stepper] Remove Paper and built-in padding #22564)
-
[Textfield] Change the default variant -> outlined. Per https://medium.com/@brianisrighthere/material-studies-text-fields-f029b3b38020. ([TextField] Change default variant from standard to outlined #23503)
-
[CssBaseline] Apply body2 -> body1 Applying body2 styling to the body element causes weird behavior that can't be overriden #17100. ([CssBaseline] Change body font size to body1 (1rem) #24018)
-
[types] Remove deprecated
SimplifiedPropsOf
/Simplify
types. [core] Remove deprecated SimplifiedPropsOf/Simplify types #24750 -
[typescript] Only support TypeScript 3.8 and onwards. Omit was added in 3.5, can be removed from @material-ui/types. -
[Select] Change the default variat as TextField [Select] Improve description on how it extends the Input components #24180 (comment). [Select][FormControl] Make outlined variant the default one #24895
-
[Box] Remove the
clone
prop [system] Remove Box clone prop #18496 (BC [Box] Remove theclone
prop #26031) -
[core] Remove deprecated
innerRef
prop, forwardRef do the job now. (BC [core] Remove deprecatedinnerRef
prop #26028) -
[Select] Remove labelWidth prop [Select] Remove labelWidth prop #22799 (BC: [Select] Remove
labelWidth
prop #26026) -
[Hidden] Remove component [Hidden] Remove component #19704. The CSS API can be replaced with the Box, the JS API can be replaced with useBreakpoint or useMediaQuery. (BC: [Hidden] Remove component #26135)
-
Remove withWidth, replace with useBreakpoint() [withWidth] Remove the API #17350. (BC: [withWidth] Remove API #26136)
-
[theme] Remove MuiThemeProvider alias. ThemeProvider is enough. https://github.com/mui-org/material-ui/pull/22791/files#r499154080 (BC: [theme] Remove
MuiThemeProvider
alias #26171) -
[Autocomplete] Rename the reasons for consistancy.
'create-option'
is not OK.
It should be camelCase. (BC: [Autocomplete] Rename values of the reason argument #26172) -
[Select] Replace with [SelectField][material-next] Introduce new component #21782 (PR [SelectField] new SelectField component #26221)Do in the lab instead -
[Autocomplete] Polish the pseudo-classes customization API [Autocomplete] can't change option highlight color #19692 (BC: [Autocomplete] Apply
.Mui-focused
instead ofdata-focus
on the focused option #26181) -
[Grid] Remove the type exports, developers don't need them. Export useful developer Typescript types #19572 (comment) (BC: [Grid] Remove unnecessary type exports #26187)
https://github.com/mui-org/material-ui/blob/9f3c45b1f7fbb7c2095b61c30a3e0659f21dd5cf/packages/material-ui/src/Grid/Grid.d.ts#L8 -
[Select] CSS API's 'selectMenu' maps to the same element as 'select' [SelectMenu] CSS API's 'selectMenu' maps to the same element as 'select' #11646. (BC: [Select][NativeSelect] Polish CSS classes #26186)
-
[Autocomplete]
getOptionSelected
is confusing, rename tooptionEqualValue
[Autocomplete] Rename getOptionSelected to optionEqualValue #24855 (BC: [Autocomplete] RenamegetOptionSelected
toisOptionEqualToValue
#26173) -
[core] Normalize file location. Module not found @material-ui/core/ThemeProvider when minimizing bundle size in create react app #23208 (BC: [core] Move
StyledEngineProvider
to@material-ui/core/styles
#26265) -
Improve the color prop handling [RFC] color prop API #13028[move to v5.1] -
[List] Improve
<ListItem button>
[List] Improve ListItemSecondaryAction handling #13597 (PR: [List] extract button from ListItem to ListItemButton #26446) -
Check if Button > span still required. (PR: [Button] Remove label span #26666, [IconButton] Remove label span #26801)
-
[CssBaseline] Improve CSS reset, can we leverage any of https://hankchizljaw.com/wrote/a-modern-css-reset/, https://github.com/sindresorhus/modern-normalize/blob/master/modern-normalize.cssdeferred @siriwatknp. -
Remove wrapper in
BottomNavigationAction
-
ref attribute is not the root element [Switch] ref attribute is not the root element #19613[move to v5.x]
Timing
I think that we can try the following:
- Deprecation preparation. (starts now)
- Create the
next
branch, publish the next versions under https://next.material-ui.com/ and the next npm tag. (April?). Stop all efforts on the v4.x version. Put the master branch (v4.x) in a low maintenance mode, only handle security fixes. - Work on the above items, in whatever order is simpler, keep the same release schedule, once a week, with alpha first.
- Once we have handled all the breaking changes and confidence with the architectural choices move to a beta stage. Once we are confident with the implemented features, start release candidates.
Current progress 109/109
Array.from(document.querySelectorAll('.contains-task-list')[2].children)
.concat(Array.from(document.querySelectorAll('.contains-task-list')[3].children))
.concat(Array.from(document.querySelectorAll('.contains-task-list')[1].children))
.concat(Array.from(document.querySelectorAll('.contains-task-list')[0].children))
.reduce((acc, item) => {
if (item.querySelector('input[type="checkbox"]:checked')) {
acc.done += 1;
}
acc.total += 1;
return acc;
}, { total: 0, done: 0 });