From 3e27ea1a0aa528fd26fb021fee947ec04a4f0c6b Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Sun, 17 Dec 2023 00:45:36 -0500 Subject: [PATCH 01/17] [ToggleButtonGroup] Support different elements under ToggleButtonGroup --- .../src/ToggleButton/ToggleButton.js | 13 ++- .../ToggleButtonGroup/ToggleButtonGroup.js | 104 +++++++++--------- .../ToggleButtonGroupContext.ts | 23 ++++ 3 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts diff --git a/packages/mui-material/src/ToggleButton/ToggleButton.js b/packages/mui-material/src/ToggleButton/ToggleButton.js index f99216a2577de3..26866a337c631f 100644 --- a/packages/mui-material/src/ToggleButton/ToggleButton.js +++ b/packages/mui-material/src/ToggleButton/ToggleButton.js @@ -3,6 +3,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; +import { internal_resolveProps as resolveProps } from '@mui/utils'; import { unstable_composeClasses as composeClasses } from '@mui/base/composeClasses'; import { alpha } from '../styles'; import ButtonBase from '../ButtonBase'; @@ -10,6 +11,8 @@ import capitalize from '../utils/capitalize'; import useThemeProps from '../styles/useThemeProps'; import styled from '../styles/styled'; import toggleButtonClasses, { getToggleButtonUtilityClass } from './toggleButtonClasses'; +import ToggleButtonGroupContext from '../ToggleButtonGroup/ToggleButtonGroupContext'; +import isValueSelected from '../ToggleButtonGroup/isValueSelected'; const useUtilityClasses = (ownerState) => { const { classes, fullWidth, selected, disabled, size, color } = ownerState; @@ -108,7 +111,13 @@ const ToggleButtonRoot = styled(ButtonBase, { }); const ToggleButton = React.forwardRef(function ToggleButton(inProps, ref) { - const props = useThemeProps({ props: inProps, name: 'MuiToggleButton' }); + // props priority: `inProps` > `contextProps` > `themeDefaultProps` + const { value: contextValue, ...contextProps } = React.useContext(ToggleButtonGroupContext); + const resolvedProps = resolveProps( + { ...contextProps, selected: isValueSelected(inProps.value, contextValue) }, + inProps, + ); + const props = useThemeProps({ props: resolvedProps, name: 'MuiToggleButton' }); const { children, className, @@ -150,7 +159,7 @@ const ToggleButton = React.forwardRef(function ToggleButton(inProps, ref) { return ( { const { classes, orientation, fullWidth, disabled } = ownerState; @@ -106,31 +105,60 @@ const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup(inProps, r const ownerState = { ...props, disabled, fullWidth, orientation, size }; const classes = useUtilityClasses(ownerState); - const handleChange = (event, buttonValue) => { - if (!onChange) { - return; - } + const handleChange = React.useCallback( + (event, buttonValue) => { + if (!onChange) { + return; + } - const index = value && value.indexOf(buttonValue); - let newValue; + const index = value && value.indexOf(buttonValue); + let newValue; - if (value && index >= 0) { - newValue = value.slice(); - newValue.splice(index, 1); - } else { - newValue = value ? value.concat(buttonValue) : [buttonValue]; - } + if (value && index >= 0) { + newValue = value.slice(); + newValue.splice(index, 1); + } else { + newValue = value ? value.concat(buttonValue) : [buttonValue]; + } - onChange(event, newValue); - }; + onChange(event, newValue); + }, + [onChange, value], + ); - const handleExclusiveChange = (event, buttonValue) => { - if (!onChange) { - return; - } + const handleExclusiveChange = React.useCallback( + (event, buttonValue) => { + if (!onChange) { + return; + } - onChange(event, value === buttonValue ? null : buttonValue); - }; + onChange(event, value === buttonValue ? null : buttonValue); + }, + [onChange, value], + ); + + const context = React.useMemo( + () => ({ + className: classes.grouped, + onChange: exclusive ? handleExclusiveChange : handleChange, + value, + size, + fullWidth, + color, + disabled, + }), + [ + classes.grouped, + exclusive, + handleExclusiveChange, + handleChange, + value, + size, + fullWidth, + color, + disabled, + ], + ); return ( - {React.Children.map(children, (child) => { - if (!React.isValidElement(child)) { - return null; - } - - if (process.env.NODE_ENV !== 'production') { - if (isFragment(child)) { - console.error( - [ - "MUI: The ToggleButtonGroup component doesn't accept a Fragment as a child.", - 'Consider providing an array instead.', - ].join('\n'), - ); - } - } - - return React.cloneElement(child, { - className: clsx(classes.grouped, child.props.className), - onChange: exclusive ? handleExclusiveChange : handleChange, - selected: - child.props.selected === undefined - ? isValueSelected(child.props.value, value) - : child.props.selected, - size: child.props.size || size, - fullWidth, - color: child.props.color || color, - disabled: child.props.disabled || disabled, - }); - })} + + {children} + ); }); diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts new file mode 100644 index 00000000000000..9149f7ed08dc3d --- /dev/null +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts @@ -0,0 +1,23 @@ +import * as React from 'react'; +import type { ToggleButtonGroupProps } from './ToggleButtonGroup'; + +interface IToggleButtonGroupContext { + className?: string; + onChange?: ToggleButtonGroupProps['onChange']; + value?: any; + size?: ToggleButtonGroupProps['size']; + fullWidth?: boolean; + color?: ToggleButtonGroupProps['color']; + disabled?: boolean; +} + +/** + * @ignore - internal component. + */ +const ToggleButtonGroupContext = React.createContext({}); + +if (process.env.NODE_ENV !== 'production') { + ToggleButtonGroupContext.displayName = 'ToggleButtonGroupContext'; +} + +export default ToggleButtonGroupContext; From 75b838727591254ab599ba00d5a9560924f2c1e0 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 28 Dec 2023 11:31:39 -0500 Subject: [PATCH 02/17] Fix styling for varying children --- .../material-ui/api/toggle-button-group.json | 18 ++++ .../toggle-button-group.json | 12 +++ .../src/ToggleButton/ToggleButton.js | 8 +- .../ToggleButtonGroup/ToggleButtonGroup.js | 91 ++++++++++++++----- .../ToggleButtonGroupButtonContext.ts | 16 ++++ .../toggleButtonGroupClasses.ts | 9 ++ 6 files changed, 132 insertions(+), 22 deletions(-) create mode 100644 packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupButtonContext.ts diff --git a/docs/pages/material-ui/api/toggle-button-group.json b/docs/pages/material-ui/api/toggle-button-group.json index e0d7c66bc56cb0..fe15efc9c0d33f 100644 --- a/docs/pages/material-ui/api/toggle-button-group.json +++ b/docs/pages/material-ui/api/toggle-button-group.json @@ -51,6 +51,12 @@ "description": "State class applied to the root element if `disabled={true}`.", "isGlobal": true }, + { + "key": "firstButton", + "className": "MuiToggleButtonGroup-firstButton", + "description": "Styles applied to the first button in the button group.", + "isGlobal": false + }, { "key": "fullWidth", "className": "MuiToggleButtonGroup-fullWidth", @@ -75,6 +81,18 @@ "description": "Styles applied to the children if `orientation=\"vertical\"`.", "isGlobal": false }, + { + "key": "lastButton", + "className": "MuiToggleButtonGroup-lastButton", + "description": "Styles applied to the last button in the button group.", + "isGlobal": false + }, + { + "key": "middleButton", + "className": "MuiToggleButtonGroup-middleButton", + "description": "Styles applied to buttons in the middle of the button group.", + "isGlobal": false + }, { "key": "root", "className": "MuiToggleButtonGroup-root", diff --git a/docs/translations/api-docs/toggle-button-group/toggle-button-group.json b/docs/translations/api-docs/toggle-button-group/toggle-button-group.json index 8768d86fb8b4d3..e85c6633a414c1 100644 --- a/docs/translations/api-docs/toggle-button-group/toggle-button-group.json +++ b/docs/translations/api-docs/toggle-button-group/toggle-button-group.json @@ -37,6 +37,10 @@ "nodeName": "the root element", "conditions": "disabled={true}" }, + "firstButton": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the first button in the button group" + }, "fullWidth": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the root element", @@ -53,6 +57,14 @@ "nodeName": "the children", "conditions": "orientation=\"vertical\"" }, + "lastButton": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the last button in the button group" + }, + "middleButton": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "buttons in the middle of the button group" + }, "root": { "description": "Styles applied to the root element." }, "vertical": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", diff --git a/packages/mui-material/src/ToggleButton/ToggleButton.js b/packages/mui-material/src/ToggleButton/ToggleButton.js index 26866a337c631f..2478a37c354d58 100644 --- a/packages/mui-material/src/ToggleButton/ToggleButton.js +++ b/packages/mui-material/src/ToggleButton/ToggleButton.js @@ -12,6 +12,7 @@ import useThemeProps from '../styles/useThemeProps'; import styled from '../styles/styled'; import toggleButtonClasses, { getToggleButtonUtilityClass } from './toggleButtonClasses'; import ToggleButtonGroupContext from '../ToggleButtonGroup/ToggleButtonGroupContext'; +import ToggleButtonGroupButtonContext from '../ToggleButtonGroup/ToggleButtonGroupButtonContext'; import isValueSelected from '../ToggleButtonGroup/isValueSelected'; const useUtilityClasses = (ownerState) => { @@ -113,6 +114,9 @@ const ToggleButtonRoot = styled(ButtonBase, { const ToggleButton = React.forwardRef(function ToggleButton(inProps, ref) { // props priority: `inProps` > `contextProps` > `themeDefaultProps` const { value: contextValue, ...contextProps } = React.useContext(ToggleButtonGroupContext); + const toggleButtonGroupButtonContextPositionClassName = React.useContext( + ToggleButtonGroupButtonContext, + ); const resolvedProps = resolveProps( { ...contextProps, selected: isValueSelected(inProps.value, contextValue) }, inProps, @@ -157,9 +161,11 @@ const ToggleButton = React.forwardRef(function ToggleButton(inProps, ref) { } }; + const positionClassName = toggleButtonGroupButtonContextPositionClassName || ''; + return ( { const { classes, orientation, fullWidth, disabled } = ownerState; @@ -17,6 +19,9 @@ const useUtilityClasses = (ownerState) => { const slots = { root: ['root', orientation === 'vertical' && 'vertical', fullWidth && 'fullWidth'], grouped: ['grouped', `grouped${capitalize(orientation)}`, disabled && 'disabled'], + firstButton: ['firstButton'], + lastButton: ['lastButton'], + middleButton: ['middleButton'], }; return composeClasses(slots, getToggleButtonGroupUtilityClass, classes); @@ -34,6 +39,15 @@ const ToggleButtonGroupRoot = styled('div', { [`& .${toggleButtonGroupClasses.grouped}`]: styles[`grouped${capitalize(ownerState.orientation)}`], }, + { + [`& .${toggleButtonGroupClasses.firstButton}`]: styles.firstButton, + }, + { + [`& .${toggleButtonGroupClasses.lastButton}`]: styles.lastButton, + }, + { + [`& .${toggleButtonGroupClasses.middleButton}`]: styles.middleButton, + }, styles.root, ownerState.orientation === 'vertical' && styles.vertical, ownerState.fullWidth && styles.fullWidth, @@ -51,16 +65,6 @@ const ToggleButtonGroupRoot = styled('div', { [`& .${toggleButtonGroupClasses.grouped}`]: { ...(ownerState.orientation === 'horizontal' ? { - '&:not(:first-of-type)': { - marginLeft: -1, - borderLeft: '1px solid transparent', - borderTopLeftRadius: 0, - borderBottomLeftRadius: 0, - }, - '&:not(:last-of-type)': { - borderTopRightRadius: 0, - borderBottomRightRadius: 0, - }, [`&.${toggleButtonGroupClasses.selected} + .${toggleButtonGroupClasses.grouped}.${toggleButtonGroupClasses.selected}`]: { borderLeft: 0, @@ -68,16 +72,6 @@ const ToggleButtonGroupRoot = styled('div', { }, } : { - '&:not(:first-of-type)': { - marginTop: -1, - borderTop: '1px solid transparent', - borderTopLeftRadius: 0, - borderTopRightRadius: 0, - }, - '&:not(:last-of-type)': { - borderBottomLeftRadius: 0, - borderBottomRightRadius: 0, - }, [`&.${toggleButtonGroupClasses.selected} + .${toggleButtonGroupClasses.grouped}.${toggleButtonGroupClasses.selected}`]: { borderTop: 0, @@ -85,6 +79,33 @@ const ToggleButtonGroupRoot = styled('div', { }, }), }, + ...(ownerState.orientation === 'horizontal' + ? { + [`& .${toggleButtonGroupClasses.firstButton},& .${toggleButtonGroupClasses.middleButton}`]: + { + borderTopRightRadius: 0, + borderBottomRightRadius: 0, + }, + [`& .${toggleButtonGroupClasses.lastButton},& .${toggleButtonGroupClasses.middleButton}`]: { + marginLeft: -1, + borderLeft: '1px solid transparent', + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + }, + } + : { + [`& .${toggleButtonGroupClasses.firstButton},& .${toggleButtonGroupClasses.middleButton}`]: + { + borderBottomLeftRadius: 0, + borderBottomRightRadius: 0, + }, + [`& .${toggleButtonGroupClasses.lastButton},& .${toggleButtonGroupClasses.middleButton}`]: { + marginTop: -1, + borderTop: '1px solid transparent', + borderTopLeftRadius: 0, + borderTopRightRadius: 0, + }, + }), })); const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup(inProps, ref) { @@ -160,6 +181,25 @@ const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup(inProps, r ], ); + const validChildren = getValidReactChildren(children); + const childrenCount = validChildren.length; + + const getButtonPositionClassName = (index) => { + const isFirstButton = index === 0; + const isLastButton = index === childrenCount - 1; + + if (isFirstButton && isLastButton) { + return ''; + } + if (isFirstButton) { + return classes.firstButton; + } + if (isLastButton) { + return classes.lastButton; + } + return classes.middleButton; + }; + return ( - {children} + {validChildren.map((child, index) => { + return ( + + {child} + + ); + })} ); diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupButtonContext.ts b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupButtonContext.ts new file mode 100644 index 00000000000000..04173b98dbc81a --- /dev/null +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupButtonContext.ts @@ -0,0 +1,16 @@ +import * as React from 'react'; + +type ButtonPositionClassName = string; + +/** + * @ignore - internal component. + */ +const ToggleButtonGroupButtonContext = React.createContext( + undefined, +); + +if (process.env.NODE_ENV !== 'production') { + ToggleButtonGroupButtonContext.displayName = 'ToggleButtonGroupButtonContext'; +} + +export default ToggleButtonGroupButtonContext; diff --git a/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts b/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts index ef4b714f78713e..139e8a220b7e04 100644 --- a/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts +++ b/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts @@ -16,6 +16,12 @@ export interface ToggleButtonGroupClasses { groupedVertical: string; /** Styles applied to the root element if `fullWidth={true}`. */ fullWidth: string; + /** Styles applied to the first button in the button group. */ + firstButton: string; + /** Styles applied to the last button in the button group. */ + lastButton: string; + /** Styles applied to buttons in the middle of the button group. */ + middleButton: string; } export type ToggleButtonGroupClassKey = keyof ToggleButtonGroupClasses; @@ -35,6 +41,9 @@ const toggleButtonGroupClasses: ToggleButtonGroupClasses = generateUtilityClasse 'groupedHorizontal', 'groupedVertical', 'fullWidth', + 'firstButton', + 'lastButton', + 'middleButton', ], ); From 18f06da53e8bbdecca3fe17cce6010bbb1da3b81 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 28 Dec 2023 11:31:46 -0500 Subject: [PATCH 03/17] Add tests --- .../ToggleButtonGroup.test.js | 57 +++++++++++++++++++ .../ToggleButtonGroup/DifferentChildren.js | 46 +++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 test/regressions/fixtures/ToggleButtonGroup/DifferentChildren.js diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.test.js b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.test.js index 5bfca3c6004acb..ff8d7c19461d55 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.test.js +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.test.js @@ -6,6 +6,7 @@ import ToggleButtonGroup, { toggleButtonGroupClasses as classes, } from '@mui/material/ToggleButtonGroup'; import ToggleButton, { toggleButtonClasses } from '@mui/material/ToggleButton'; +import Tooltip from '@mui/material/Tooltip'; describe('', () => { const { render } = createRenderer(); @@ -223,4 +224,60 @@ describe('', () => { expect(buttonGroup).to.have.class(classes.fullWidth); expect(button).to.have.class(toggleButtonClasses.fullWidth); }); + + describe('position classes', () => { + it('correctly applies position classes to buttons', () => { + render( + + + One + + + + + Two + + + + + + + Three + + + + , + ); + + const firstButton = screen.getAllByRole('button')[0]; + const middleButton = screen.getAllByRole('button')[1]; + const lastButton = screen.getAllByRole('button')[2]; + + expect(firstButton).to.have.class(classes.firstButton); + expect(firstButton).not.to.have.class(classes.middleButton); + expect(firstButton).not.to.have.class(classes.lastButton); + + expect(middleButton).to.have.class(classes.middleButton); + expect(middleButton).not.to.have.class(classes.firstButton); + expect(middleButton).not.to.have.class(classes.lastButton); + + expect(lastButton).to.have.class(classes.lastButton); + expect(lastButton).not.to.have.class(classes.middleButton); + expect(lastButton).not.to.have.class(classes.firstButton); + }); + + it('does not apply any position classes to a single button', () => { + render( + + One + , + ); + + const button = screen.getByRole('button'); + + expect(button).not.to.have.class(classes.firstButton); + expect(button).not.to.have.class(classes.middleButton); + expect(button).not.to.have.class(classes.lastButton); + }); + }); }); diff --git a/test/regressions/fixtures/ToggleButtonGroup/DifferentChildren.js b/test/regressions/fixtures/ToggleButtonGroup/DifferentChildren.js new file mode 100644 index 00000000000000..8d4e2813ed4b6d --- /dev/null +++ b/test/regressions/fixtures/ToggleButtonGroup/DifferentChildren.js @@ -0,0 +1,46 @@ +import * as React from 'react'; +import ToggleButton from '@mui/material/ToggleButton'; +import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; +import Stack from '@mui/material/Stack'; +import Tooltip from '@mui/material/Tooltip'; + +export default function DifferentChildren() { + const falsyCondition = 1 === 2; + + return ( + + {/* With tooltip */} + + + One + + + + + Two + + + + + + + Three + + + + + + {/* Single button */} + + One + + + {/* Conditional elements */} + + One + Two + {falsyCondition ? Three : undefined} + + + ); +} From 4a7617dbc48aac3776388d489fa4dab01bf93758 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 28 Dec 2023 11:59:38 -0500 Subject: [PATCH 04/17] Update docs example --- .../toggle-button/CustomizedDividers.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.tsx b/docs/data/material/components/toggle-button/CustomizedDividers.tsx index 92dd37287a2798..f330729f08177f 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.tsx +++ b/docs/data/material/components/toggle-button/CustomizedDividers.tsx @@ -21,12 +21,15 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ '&.Mui-disabled': { border: 0, }, - '&:not(:first-of-type)': { - borderRadius: theme.shape.borderRadius, - }, - '&:first-of-type': { - borderRadius: theme.shape.borderRadius, - }, + }, + '& .MuiToggleButtonGroup-firstButton': { + borderRadius: theme.shape.borderRadius, + }, + '& .MuiToggleButtonGroup-middleButton': { + borderRadius: theme.shape.borderRadius, + }, + '& .MuiToggleButtonGroup-lastButton': { + borderRadius: theme.shape.borderRadius, }, })); From bc6deec0f2bd8f7f7a17a0d1d60131d6f40ec4c8 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 28 Dec 2023 12:12:42 -0500 Subject: [PATCH 05/17] Update transpiled docs example --- .../toggle-button/CustomizedDividers.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.js b/docs/data/material/components/toggle-button/CustomizedDividers.js index e4e7a4cc074706..d3e8d0d56bca10 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.js +++ b/docs/data/material/components/toggle-button/CustomizedDividers.js @@ -21,12 +21,15 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ '&.Mui-disabled': { border: 0, }, - '&:not(:first-of-type)': { - borderRadius: theme.shape.borderRadius, - }, - '&:first-of-type': { - borderRadius: theme.shape.borderRadius, - }, + }, + '& .MuiToggleButtonGroup-firstButton': { + borderRadius: theme.shape.borderRadius, + }, + '& .MuiToggleButtonGroup-middleButton': { + borderRadius: theme.shape.borderRadius, + }, + '& .MuiToggleButtonGroup-lastButton': { + borderRadius: theme.shape.borderRadius, }, })); From faf3243c3a9c59bcca18e09dfe86c7fb3fa7e774 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 4 Jan 2024 20:55:57 -0500 Subject: [PATCH 06/17] Override border when button is disabled --- .../src/ToggleButtonGroup/ToggleButtonGroup.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js index bb294788320365..5345a020395d98 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js @@ -12,6 +12,7 @@ import toggleButtonGroupClasses, { } from './toggleButtonGroupClasses'; import ToggleButtonGroupContext from './ToggleButtonGroupContext'; import ToggleButtonGroupButtonContext from './ToggleButtonGroupButtonContext'; +import toggleButtonClasses from '../ToggleButton/toggleButtonClasses'; const useUtilityClasses = (ownerState) => { const { classes, orientation, fullWidth, disabled } = ownerState; @@ -106,6 +107,19 @@ const ToggleButtonGroupRoot = styled('div', { borderTopRightRadius: 0, }, }), + ...(ownerState.orientation === 'horizontal' + ? { + [`& .${toggleButtonGroupClasses.lastButton}.${toggleButtonClasses.disabled},& .${toggleButtonGroupClasses.middleButton}.${toggleButtonClasses.disabled}`]: + { + borderLeft: '1px solid transparent', + }, + } + : { + [`& .${toggleButtonGroupClasses.lastButton}.${toggleButtonClasses.disabled},& .${toggleButtonGroupClasses.middleButton}.${toggleButtonClasses.disabled}`]: + { + borderTop: '1px solid transparent', + }, + }), })); const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup(inProps, ref) { From abf0c384a2871c8a97bba38dc970d8425616a0fb Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 4 Jan 2024 21:28:53 -0500 Subject: [PATCH 07/17] Update CustomizedDividers --- .../components/toggle-button/CustomizedDividers.js | 10 +++++----- .../components/toggle-button/CustomizedDividers.tsx | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.js b/docs/data/material/components/toggle-button/CustomizedDividers.js index d3e8d0d56bca10..3429e209ac11bf 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.js +++ b/docs/data/material/components/toggle-button/CustomizedDividers.js @@ -18,18 +18,18 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ '& .MuiToggleButtonGroup-grouped': { margin: theme.spacing(0.5), border: 0, + borderRadius: theme.shape.borderRadius, '&.Mui-disabled': { border: 0, }, }, - '& .MuiToggleButtonGroup-firstButton': { - borderRadius: theme.shape.borderRadius, - }, '& .MuiToggleButtonGroup-middleButton': { - borderRadius: theme.shape.borderRadius, + marginLeft: -1, + borderLeft: '1px solid transparent', }, '& .MuiToggleButtonGroup-lastButton': { - borderRadius: theme.shape.borderRadius, + marginLeft: -1, + borderLeft: '1px solid transparent', }, })); diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.tsx b/docs/data/material/components/toggle-button/CustomizedDividers.tsx index f330729f08177f..8f9fc30c2ecc63 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.tsx +++ b/docs/data/material/components/toggle-button/CustomizedDividers.tsx @@ -18,18 +18,18 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ '& .MuiToggleButtonGroup-grouped': { margin: theme.spacing(0.5), border: 0, + borderRadius: theme.shape.borderRadius, '&.Mui-disabled': { border: 0, }, }, - '& .MuiToggleButtonGroup-firstButton': { - borderRadius: theme.shape.borderRadius, - }, '& .MuiToggleButtonGroup-middleButton': { - borderRadius: theme.shape.borderRadius, + marginLeft: -1, + borderLeft: '1px solid transparent', }, '& .MuiToggleButtonGroup-lastButton': { - borderRadius: theme.shape.borderRadius, + marginLeft: -1, + borderLeft: '1px solid transparent', }, })); From 6b8356c9f32e99e4216f719183bb7edd2a96b9b4 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:07:01 -0500 Subject: [PATCH 08/17] Update packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts Co-authored-by: Zeeshan Tamboli Signed-off-by: Nathan Bierema --- .../src/ToggleButtonGroup/ToggleButtonGroupContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts index 9149f7ed08dc3d..20d3173bebb87d 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts @@ -4,7 +4,7 @@ import type { ToggleButtonGroupProps } from './ToggleButtonGroup'; interface IToggleButtonGroupContext { className?: string; onChange?: ToggleButtonGroupProps['onChange']; - value?: any; + value?: ToggleButtonGroupProps['value']; size?: ToggleButtonGroupProps['size']; fullWidth?: boolean; color?: ToggleButtonGroupProps['color']; From 50318f815eec8a98c5f0601204d4c6ef7b1bb821 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:08:46 -0500 Subject: [PATCH 09/17] Update docs/data/material/components/toggle-button/CustomizedDividers.tsx Co-authored-by: Zeeshan Tamboli Signed-off-by: Nathan Bierema --- .../material/components/toggle-button/CustomizedDividers.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.tsx b/docs/data/material/components/toggle-button/CustomizedDividers.tsx index 8f9fc30c2ecc63..427bff6f3416a1 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.tsx +++ b/docs/data/material/components/toggle-button/CustomizedDividers.tsx @@ -23,13 +23,10 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ border: 0, }, }, - '& .MuiToggleButtonGroup-middleButton': { + '& .MuiToggleButtonGroup-middleButton,& .MuiToggleButtonGroup-lastButton': { marginLeft: -1, borderLeft: '1px solid transparent', }, - '& .MuiToggleButtonGroup-lastButton': { - marginLeft: -1, - borderLeft: '1px solid transparent', }, })); From 5ddd8c554a7a3a6e6ae8cfa5ebd14a53cd8adaa8 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:21:58 -0500 Subject: [PATCH 10/17] Update packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts Co-authored-by: Zeeshan Tamboli Signed-off-by: Nathan Bierema --- .../src/ToggleButtonGroup/ToggleButtonGroupContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts index 20d3173bebb87d..e2192c955cb2f5 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts @@ -6,7 +6,7 @@ interface IToggleButtonGroupContext { onChange?: ToggleButtonGroupProps['onChange']; value?: ToggleButtonGroupProps['value']; size?: ToggleButtonGroupProps['size']; - fullWidth?: boolean; + fullWidth?: ToggleButtonGroupProps['fullWidth']; color?: ToggleButtonGroupProps['color']; disabled?: boolean; } From 94b6178ae044bd5045b692026104f0a90ea56aa3 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:22:21 -0500 Subject: [PATCH 11/17] Update packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts Co-authored-by: Zeeshan Tamboli Signed-off-by: Nathan Bierema --- .../src/ToggleButtonGroup/ToggleButtonGroupContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts index e2192c955cb2f5..bc9d9f356f8d1e 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts @@ -8,7 +8,7 @@ interface IToggleButtonGroupContext { size?: ToggleButtonGroupProps['size']; fullWidth?: ToggleButtonGroupProps['fullWidth']; color?: ToggleButtonGroupProps['color']; - disabled?: boolean; + disabled?: ToggleButtonGroupProps['disabled']; } /** From f5ae99fda4f1007ed7bebeed4640a63ac8b059bd Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:23:00 -0500 Subject: [PATCH 12/17] Update packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts Co-authored-by: Zeeshan Tamboli Signed-off-by: Nathan Bierema --- .../src/ToggleButtonGroup/toggleButtonGroupClasses.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts b/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts index 1d521155d8d6aa..75cf854a4d59fc 100644 --- a/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts +++ b/packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupClasses.ts @@ -16,11 +16,11 @@ export interface ToggleButtonGroupClasses { groupedVertical: string; /** Styles applied to the root element if `fullWidth={true}`. */ fullWidth: string; - /** Styles applied to the first button in the button group. */ + /** Styles applied to the first button in the toggle button group. */ firstButton: string; - /** Styles applied to the last button in the button group. */ + /** Styles applied to the last button in the toggle button group. */ lastButton: string; - /** Styles applied to buttons in the middle of the button group. */ + /** Styles applied to buttons in the middle of the toggle button group. */ middleButton: string; } From dcb82cd82b52342d4c088da16a1ca206afb21410 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:37:54 -0500 Subject: [PATCH 13/17] Address PR review comments --- .../components/toggle-button/CustomizedDividers.js | 6 +----- .../components/toggle-button/CustomizedDividers.tsx | 1 - .../src/ButtonGroup/ButtonGroupContext.ts | 4 ++-- .../src/ToggleButtonGroup/ToggleButtonGroup.js | 11 +++++++++++ .../ToggleButtonGroupButtonContext.ts | 8 ++++---- .../src/ToggleButtonGroup/ToggleButtonGroupContext.ts | 4 ++-- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.js b/docs/data/material/components/toggle-button/CustomizedDividers.js index 3429e209ac11bf..498c9162b6687c 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.js +++ b/docs/data/material/components/toggle-button/CustomizedDividers.js @@ -23,11 +23,7 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ border: 0, }, }, - '& .MuiToggleButtonGroup-middleButton': { - marginLeft: -1, - borderLeft: '1px solid transparent', - }, - '& .MuiToggleButtonGroup-lastButton': { + '& .MuiToggleButtonGroup-middleButton,& .MuiToggleButtonGroup-lastButton': { marginLeft: -1, borderLeft: '1px solid transparent', }, diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.tsx b/docs/data/material/components/toggle-button/CustomizedDividers.tsx index 427bff6f3416a1..1687912eb3d0be 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.tsx +++ b/docs/data/material/components/toggle-button/CustomizedDividers.tsx @@ -27,7 +27,6 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ marginLeft: -1, borderLeft: '1px solid transparent', }, - }, })); export default function CustomizedDividers() { diff --git a/packages/mui-material/src/ButtonGroup/ButtonGroupContext.ts b/packages/mui-material/src/ButtonGroup/ButtonGroupContext.ts index 63352996156cc5..d336154db99963 100644 --- a/packages/mui-material/src/ButtonGroup/ButtonGroupContext.ts +++ b/packages/mui-material/src/ButtonGroup/ButtonGroupContext.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import type { ButtonGroupProps } from './ButtonGroup'; -interface IButtonGroupContext { +interface ButtonGroupContextType { className?: string; color?: ButtonGroupProps['color']; disabled?: boolean; @@ -16,7 +16,7 @@ interface IButtonGroupContext { /** * @ignore - internal component. */ -const ButtonGroupContext = React.createContext({}); +const ButtonGroupContext = React.createContext({}); if (process.env.NODE_ENV !== 'production') { ButtonGroupContext.displayName = 'ButtonGroupContext'; diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js index 75475e0550650c..24ad5cbdc31b5f 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js @@ -224,6 +224,17 @@ const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup(inProps, r > {validChildren.map((child, index) => { + if (process.env.NODE_ENV !== 'production') { + if (isFragment(child)) { + console.error( + [ + "MUI: The ToggleButtonGroup component doesn't accept a Fragment as a child.", + 'Consider providing an array instead.', + ].join('\n'), + ); + } + } + return ( ( - undefined, -); +const ToggleButtonGroupButtonContext = React.createContext< + ToggleButtonPositionClassName | undefined +>(undefined); if (process.env.NODE_ENV !== 'production') { ToggleButtonGroupButtonContext.displayName = 'ToggleButtonGroupButtonContext'; diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts index bc9d9f356f8d1e..88c3153db2be8c 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupContext.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import type { ToggleButtonGroupProps } from './ToggleButtonGroup'; -interface IToggleButtonGroupContext { +interface ToggleButtonGroupContextType { className?: string; onChange?: ToggleButtonGroupProps['onChange']; value?: ToggleButtonGroupProps['value']; @@ -14,7 +14,7 @@ interface IToggleButtonGroupContext { /** * @ignore - internal component. */ -const ToggleButtonGroupContext = React.createContext({}); +const ToggleButtonGroupContext = React.createContext({}); if (process.env.NODE_ENV !== 'production') { ToggleButtonGroupContext.displayName = 'ToggleButtonGroupContext'; From 768dc26d637e5bd1b4773b3c95cea6e25eb4da78 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:47:14 -0500 Subject: [PATCH 14/17] Add back missing import --- packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js index 24ad5cbdc31b5f..d6be6dcd4bd2d8 100644 --- a/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js +++ b/packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import { isFragment } from 'react-is'; import PropTypes from 'prop-types'; import clsx from 'clsx'; import { unstable_composeClasses as composeClasses } from '@mui/base/composeClasses'; From 542270527a8efc9cbcf0acf1bd16bf865d7afd4b Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 09:53:10 -0500 Subject: [PATCH 15/17] Update toggle-button-group.json --- docs/pages/material-ui/api/toggle-button-group.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pages/material-ui/api/toggle-button-group.json b/docs/pages/material-ui/api/toggle-button-group.json index fe15efc9c0d33f..e3d1c10eefb45c 100644 --- a/docs/pages/material-ui/api/toggle-button-group.json +++ b/docs/pages/material-ui/api/toggle-button-group.json @@ -54,7 +54,7 @@ { "key": "firstButton", "className": "MuiToggleButtonGroup-firstButton", - "description": "Styles applied to the first button in the button group.", + "description": "Styles applied to the first button in the toggle button group.", "isGlobal": false }, { @@ -84,13 +84,13 @@ { "key": "lastButton", "className": "MuiToggleButtonGroup-lastButton", - "description": "Styles applied to the last button in the button group.", + "description": "Styles applied to the last button in the toggle button group.", "isGlobal": false }, { "key": "middleButton", "className": "MuiToggleButtonGroup-middleButton", - "description": "Styles applied to buttons in the middle of the button group.", + "description": "Styles applied to buttons in the middle of the toggle button group.", "isGlobal": false }, { From e7f43992edc31a2c61b2386656af8c0c9239b46f Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Fri, 5 Jan 2024 10:06:39 -0500 Subject: [PATCH 16/17] Update other toggle-button-group.json --- .../api-docs/toggle-button-group/toggle-button-group.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/translations/api-docs/toggle-button-group/toggle-button-group.json b/docs/translations/api-docs/toggle-button-group/toggle-button-group.json index e85c6633a414c1..21eccbcd92b660 100644 --- a/docs/translations/api-docs/toggle-button-group/toggle-button-group.json +++ b/docs/translations/api-docs/toggle-button-group/toggle-button-group.json @@ -39,7 +39,7 @@ }, "firstButton": { "description": "Styles applied to {{nodeName}}.", - "nodeName": "the first button in the button group" + "nodeName": "the first button in the toggle button group" }, "fullWidth": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", @@ -59,11 +59,11 @@ }, "lastButton": { "description": "Styles applied to {{nodeName}}.", - "nodeName": "the last button in the button group" + "nodeName": "the last button in the toggle button group" }, "middleButton": { "description": "Styles applied to {{nodeName}}.", - "nodeName": "buttons in the middle of the button group" + "nodeName": "buttons in the middle of the toggle button group" }, "root": { "description": "Styles applied to the root element." }, "vertical": { From e80dd978f2020bfdd39eb8e0b40e4065c441f3cd Mon Sep 17 00:00:00 2001 From: ZeeshanTamboli Date: Sat, 6 Jan 2024 12:30:28 +0530 Subject: [PATCH 17/17] use toggleButtonGroupClasses instead of hardcoding classNames --- .../toggle-button/CustomizedDividers.js | 17 ++++++++++------- .../toggle-button/CustomizedDividers.tsx | 17 ++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.js b/docs/data/material/components/toggle-button/CustomizedDividers.js index 498c9162b6687c..1c7063d44caaaa 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.js +++ b/docs/data/material/components/toggle-button/CustomizedDividers.js @@ -12,21 +12,24 @@ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import Divider from '@mui/material/Divider'; import Paper from '@mui/material/Paper'; import ToggleButton from '@mui/material/ToggleButton'; -import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; +import ToggleButtonGroup, { + toggleButtonGroupClasses, +} from '@mui/material/ToggleButtonGroup'; const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ - '& .MuiToggleButtonGroup-grouped': { + [`& .${toggleButtonGroupClasses.grouped}`]: { margin: theme.spacing(0.5), border: 0, borderRadius: theme.shape.borderRadius, - '&.Mui-disabled': { + [`&.${toggleButtonGroupClasses.disabled}`]: { border: 0, }, }, - '& .MuiToggleButtonGroup-middleButton,& .MuiToggleButtonGroup-lastButton': { - marginLeft: -1, - borderLeft: '1px solid transparent', - }, + [`& .${toggleButtonGroupClasses.middleButton},& .${toggleButtonGroupClasses.lastButton}`]: + { + marginLeft: -1, + borderLeft: '1px solid transparent', + }, })); export default function CustomizedDividers() { diff --git a/docs/data/material/components/toggle-button/CustomizedDividers.tsx b/docs/data/material/components/toggle-button/CustomizedDividers.tsx index 1687912eb3d0be..63e67aaedbe755 100644 --- a/docs/data/material/components/toggle-button/CustomizedDividers.tsx +++ b/docs/data/material/components/toggle-button/CustomizedDividers.tsx @@ -12,21 +12,24 @@ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import Divider from '@mui/material/Divider'; import Paper from '@mui/material/Paper'; import ToggleButton from '@mui/material/ToggleButton'; -import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; +import ToggleButtonGroup, { + toggleButtonGroupClasses, +} from '@mui/material/ToggleButtonGroup'; const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ - '& .MuiToggleButtonGroup-grouped': { + [`& .${toggleButtonGroupClasses.grouped}`]: { margin: theme.spacing(0.5), border: 0, borderRadius: theme.shape.borderRadius, - '&.Mui-disabled': { + [`&.${toggleButtonGroupClasses.disabled}`]: { border: 0, }, }, - '& .MuiToggleButtonGroup-middleButton,& .MuiToggleButtonGroup-lastButton': { - marginLeft: -1, - borderLeft: '1px solid transparent', - }, + [`& .${toggleButtonGroupClasses.middleButton},& .${toggleButtonGroupClasses.lastButton}`]: + { + marginLeft: -1, + borderLeft: '1px solid transparent', + }, })); export default function CustomizedDividers() {