Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[material-ui][ToggleButtonGroup] Support different elements under it #40220

Merged
merged 19 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3e27ea1
[ToggleButtonGroup] Support different elements under ToggleButtonGroup
Methuselah96 Dec 17, 2023
75b8387
Fix styling for varying children
Methuselah96 Dec 28, 2023
18f06da
Add tests
Methuselah96 Dec 28, 2023
4a7617d
Update docs example
Methuselah96 Dec 28, 2023
bc6deec
Update transpiled docs example
Methuselah96 Dec 28, 2023
faf3243
Override border when button is disabled
Methuselah96 Jan 5, 2024
abf0c38
Update CustomizedDividers
Methuselah96 Jan 5, 2024
a0b8171
Merge branch 'master' into toggle-button-group-context
ZeeshanTamboli Jan 5, 2024
6b8356c
Update packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupC…
Methuselah96 Jan 5, 2024
50318f8
Update docs/data/material/components/toggle-button/CustomizedDividers…
Methuselah96 Jan 5, 2024
5ddd8c5
Update packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupC…
Methuselah96 Jan 5, 2024
94b6178
Update packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroupC…
Methuselah96 Jan 5, 2024
f5ae99f
Update packages/mui-material/src/ToggleButtonGroup/toggleButtonGroupC…
Methuselah96 Jan 5, 2024
dcb82cd
Address PR review comments
Methuselah96 Jan 5, 2024
768dc26
Add back missing import
Methuselah96 Jan 5, 2024
5422705
Update toggle-button-group.json
Methuselah96 Jan 5, 2024
e7f4399
Update other toggle-button-group.json
Methuselah96 Jan 5, 2024
e80dd97
use toggleButtonGroupClasses instead of hardcoding classNames
ZeeshanTamboli Jan 6, 2024
fe00b4f
Merge branch 'master' into toggle-button-group-context
ZeeshanTamboli Jan 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/mui-material/src/ToggleButton/ToggleButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
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';
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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -150,7 +159,7 @@ const ToggleButton = React.forwardRef(function ToggleButton(inProps, ref) {

return (
<ToggleButtonRoot
className={clsx(classes.root, className)}
className={clsx(contextProps.className, classes.root, className)}
disabled={disabled}
focusRipple={!disableFocusRipple}
ref={ref}
Expand Down
104 changes: 53 additions & 51 deletions packages/mui-material/src/ToggleButtonGroup/ToggleButtonGroup.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
'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';
import styled from '../styles/styled';
import useThemeProps from '../styles/useThemeProps';
import capitalize from '../utils/capitalize';
import isValueSelected from './isValueSelected';
import toggleButtonGroupClasses, {
getToggleButtonGroupUtilityClass,
} from './toggleButtonGroupClasses';
import ToggleButtonGroupContext from './ToggleButtonGroupContext';

const useUtilityClasses = (ownerState) => {
const { classes, orientation, fullWidth, disabled } = ownerState;
Expand Down Expand Up @@ -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 (
<ToggleButtonGroupRoot
Expand All @@ -140,35 +168,9 @@ const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup(inProps, r
ownerState={ownerState}
{...other}
>
{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'),
);
}
}
Methuselah96 marked this conversation as resolved.
Show resolved Hide resolved

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,
});
})}
<ToggleButtonGroupContext.Provider value={context}>
{children}
</ToggleButtonGroupContext.Provider>
</ToggleButtonGroupRoot>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import type { ToggleButtonGroupProps } from './ToggleButtonGroup';

interface IToggleButtonGroupContext {
Methuselah96 marked this conversation as resolved.
Show resolved Hide resolved
className?: string;
onChange?: ToggleButtonGroupProps['onChange'];
value?: any;
Methuselah96 marked this conversation as resolved.
Show resolved Hide resolved
size?: ToggleButtonGroupProps['size'];
fullWidth?: boolean;
Methuselah96 marked this conversation as resolved.
Show resolved Hide resolved
color?: ToggleButtonGroupProps['color'];
disabled?: boolean;
Methuselah96 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @ignore - internal component.
*/
const ToggleButtonGroupContext = React.createContext<IToggleButtonGroupContext>({});

if (process.env.NODE_ENV !== 'production') {
ToggleButtonGroupContext.displayName = 'ToggleButtonGroupContext';
}

export default ToggleButtonGroupContext;
Loading