Skip to content

Commit

Permalink
[Button] Implement inclusive disabled state
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Aug 13, 2021
1 parent 3758446 commit b89ea22
Show file tree
Hide file tree
Showing 20 changed files with 150 additions and 46 deletions.
1 change: 1 addition & 0 deletions docs/pages/api-docs/button-base.json
Expand Up @@ -10,6 +10,7 @@
"disableTouchRipple": { "type": { "name": "bool" } },
"focusRipple": { "type": { "name": "bool" } },
"focusVisibleClassName": { "type": { "name": "string" } },
"inclusiveDisabled": { "type": { "name": "bool" }, "default": "disabled" },
"LinkComponent": { "type": { "name": "elementType" }, "default": "'a'" },
"onFocusVisible": { "type": { "name": "func" } },
"sx": { "type": { "name": "object" } },
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/api-docs/button.json
Expand Up @@ -17,6 +17,7 @@
"endIcon": { "type": { "name": "node" } },
"fullWidth": { "type": { "name": "bool" } },
"href": { "type": { "name": "string" } },
"inclusiveDisabled": { "type": { "name": "bool" }, "default": "disabled" },
"size": {
"type": {
"name": "union",
Expand Down Expand Up @@ -53,6 +54,7 @@
"disableElevation",
"focusVisible",
"disabled",
"inclusiveDisabled",
"colorInherit",
"textSizeSmall",
"textSizeMedium",
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/api-docs/icon-button.json
Expand Up @@ -19,6 +19,7 @@
},
"default": "false"
},
"inclusiveDisabled": { "type": { "name": "bool" }, "default": "disabled" },
"size": {
"type": {
"name": "union",
Expand All @@ -38,6 +39,7 @@
"colorPrimary",
"colorSecondary",
"disabled",
"inclusiveDisabled",
"sizeSmall",
"sizeMedium",
"sizeLarge"
Expand Down
1 change: 1 addition & 0 deletions docs/pages/api-docs/loading-button.json
Expand Up @@ -36,6 +36,7 @@
"disableElevation",
"focusVisible",
"disabled",
"inclusiveDisabled",
"colorInherit",
"textSizeSmall",
"textSizeMedium",
Expand Down
68 changes: 36 additions & 32 deletions docs/src/modules/components/DemoToolbar.js
Expand Up @@ -506,38 +506,42 @@ export default function DemoToolbar(props) {
<CodeIcon fontSize="small" />
</IconButton>
</DemoTooltip>
{demoOptions.hideEditButton ? null : (
<React.Fragment>
<DemoTooltip title={t('codesandbox')} placement="bottom">
<IconButton
size="large"
data-ga-event-category="demo"
data-ga-event-label={demoOptions.demo}
data-ga-event-action="codesandbox"
onClick={handleCodeSandboxClick}
{...getControlProps(3)}
>
<SvgIcon fontSize="small" viewBox="0 0 1024 1024">
<path d="M755 140.3l0.5-0.3h0.3L512 0 268.3 140h-0.3l0.8 0.4L68.6 256v512L512 1024l443.4-256V256L755 140.3z m-30 506.4v171.2L548 920.1V534.7L883.4 341v215.7l-158.4 90z m-584.4-90.6V340.8L476 534.4v385.7L300 818.5V646.7l-159.4-90.6zM511.7 280l171.1-98.3 166.3 96-336.9 194.5-337-194.6 165.7-95.7L511.7 280z" />
</SvgIcon>
</IconButton>
</DemoTooltip>
<DemoTooltip title={t('stackblitz')} placement="bottom">
<IconButton
size="large"
data-ga-event-category="demo"
data-ga-event-label={demoOptions.demo}
data-ga-event-action="stackblitz"
onClick={handleStackBlitzClick}
{...getControlProps(4)}
>
<SvgIcon fontSize="small" viewBox="0 0 19 28">
<path d="M8.13378 16.1087H0L14.8696 0L10.8662 11.1522L19 11.1522L4.13043 27.2609L8.13378 16.1087Z" />
</SvgIcon>
</IconButton>
</DemoTooltip>
</React.Fragment>
)}
<DemoTooltip
title={demoOptions.hideEditButton ? t('codesandboxDisabled') : t('codesandbox')}
placement="bottom"
>
<IconButton
size="large"
data-ga-event-category="demo"
data-ga-event-label={demoOptions.demo}
data-ga-event-action="codesandbox"
inclusiveDisabled={demoOptions.hideEditButton}
onClick={handleCodeSandboxClick}
{...getControlProps(3)}
>
<SvgIcon fontSize="small" viewBox="0 0 1024 1024">
<path d="M755 140.3l0.5-0.3h0.3L512 0 268.3 140h-0.3l0.8 0.4L68.6 256v512L512 1024l443.4-256V256L755 140.3z m-30 506.4v171.2L548 920.1V534.7L883.4 341v215.7l-158.4 90z m-584.4-90.6V340.8L476 534.4v385.7L300 818.5V646.7l-159.4-90.6zM511.7 280l171.1-98.3 166.3 96-336.9 194.5-337-194.6 165.7-95.7L511.7 280z" />
</SvgIcon>
</IconButton>
</DemoTooltip>
<DemoTooltip
title={demoOptions.hideEditButton ? t('stackblitzDisabled') : t('stackblitz')}
placement="bottom"
>
<IconButton
size="large"
data-ga-event-category="demo"
data-ga-event-label={demoOptions.demo}
data-ga-event-action="stackblitz"
inclusiveDisabled={demoOptions.hideEditButton}
onClick={handleStackBlitzClick}
{...getControlProps(4)}
>
<SvgIcon fontSize="small" viewBox="0 0 19 28">
<path d="M8.13378 16.1087H0L14.8696 0L10.8662 11.1522L19 11.1522L4.13043 27.2609L8.13378 16.1087Z" />
</SvgIcon>
</IconButton>
</DemoTooltip>
<DemoTooltip title={t('copySource')} placement="bottom">
<IconButton
size="large"
Expand Down
1 change: 1 addition & 0 deletions docs/translations/api-docs/button-base/button-base.json
Expand Up @@ -11,6 +11,7 @@
"disableTouchRipple": "If <code>true</code>, the touch ripple effect is disabled.",
"focusRipple": "If <code>true</code>, the base button will have a keyboard focus ripple.",
"focusVisibleClassName": "This prop can help identify which element has keyboard focus. The class name will be applied when the element gains the focus through keyboard interaction. It&#39;s a polyfill for the <a href=\"https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo\">CSS :focus-visible selector</a>. The rationale for using this feature <a href=\"https://github.com/WICG/focus-visible/blob/master/explainer.md\">is explained here</a>. A <a href=\"https://github.com/WICG/focus-visible\">polyfill can be used</a> to apply a <code>focus-visible</code> class to other components if needed.",
"inclusiveDisabled": "If <code>true</code>, the component is disabled but allows cursor interactions such as mouse hover (for tooltips) and focus.",
"LinkComponent": "The component used to render a link when the <code>href</code> prop is provided.",
"onFocusVisible": "Callback fired when the component is focused with a keyboard. We trigger a <code>onFocus</code> callback too.",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/the-sx-prop/\">`sx` page</a> for more details.",
Expand Down
6 changes: 6 additions & 0 deletions docs/translations/api-docs/button/button.json
Expand Up @@ -12,6 +12,7 @@
"endIcon": "Element placed after the children.",
"fullWidth": "If <code>true</code>, the button will take up the full width of its container.",
"href": "The URL to link to when the button is clicked. If defined, an <code>a</code> element will be used as the root node.",
"inclusiveDisabled": "If <code>true</code>, the component is disabled but allows cursor interactions such as mouse hover (for tooltips) and focus.",
"size": "The size of the component. <code>small</code> is equivalent to the dense button styling.",
"startIcon": "Element placed before the children.",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/the-sx-prop/\">`sx` page</a> for more details.",
Expand Down Expand Up @@ -94,6 +95,11 @@
"nodeName": "the root element",
"conditions": "<code>disabled={true}</code>"
},
"inclusiveDisabled": {
"description": "State class applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
"conditions": "<code>inclusiveDisabled={true}</code>"
},
"colorInherit": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
Expand Down
6 changes: 6 additions & 0 deletions docs/translations/api-docs/icon-button/icon-button.json
Expand Up @@ -8,6 +8,7 @@
"disableFocusRipple": "If <code>true</code>, the keyboard focus ripple is disabled.",
"disableRipple": "If <code>true</code>, the ripple effect is disabled.<br>⚠️ Without a ripple there is no styling for :focus-visible by default. Be sure to highlight the element by applying separate styles with the <code>.Mui-focusVisible</code> class.",
"edge": "If given, uses a negative margin to counteract the padding on one side (this is often helpful for aligning the left or right side of the icon with content above or below, without ruining the border size and shape).",
"inclusiveDisabled": "If <code>true</code>, the component is disabled but allows cursor interactions such as mouse hover (for tooltips) and focus.",
"size": "The size of the component. <code>small</code> is equivalent to the dense button styling.",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/the-sx-prop/\">`sx` page</a> for more details."
},
Expand Down Expand Up @@ -43,6 +44,11 @@
"nodeName": "the root element",
"conditions": "<code>disabled={true}</code>"
},
"inclusiveDisabled": {
"description": "State class applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
"conditions": "<code>disabled={true}</code>"
},
"sizeSmall": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
Expand Down
5 changes: 5 additions & 0 deletions docs/translations/api-docs/loading-button/loading-button.json
Expand Up @@ -86,6 +86,11 @@
"nodeName": "the root element",
"conditions": "<code>disabled={true}</code>"
},
"inclusiveDisabled": {
"description": "State class applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
"conditions": "<code>inclusiveDisabled={true}</code>"
},
"colorInherit": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
Expand Down
2 changes: 2 additions & 0 deletions docs/translations/translations.json
Expand Up @@ -48,6 +48,7 @@
"clickToCopy": "Click to copy",
"close": "Close",
"codesandbox": "Edit in CodeSandbox",
"codesandboxDisabled": "CodeSandbox not supported by this demo",
"copied": "Copied",
"copiedSource": "The source code has been copied to your clipboard.",
"copiedSourceLink": "Link to the source code has been copied to your clipboard.",
Expand Down Expand Up @@ -134,6 +135,7 @@
"sourceCode": "Source code",
"spacingUnit": "Spacing unit",
"stackblitz": "Edit in StackBlitz",
"stackblitzDisabled": "StackBlitz not supported by this demo",
"stars": "GitHub stars",
"stickyFooterDescr": "Attach a footer to the bottom of the viewport when page content is short.",
"stickyFooterTitle": "Sticky footer",
Expand Down
6 changes: 6 additions & 0 deletions framer/Material-UI.framerfx/code/Button.tsx
Expand Up @@ -9,6 +9,7 @@ interface Props {
endIcon: string;
fullWidth: boolean;
href?: string;
inclusiveDisabled: boolean;
startIcon: string;
startIconTheme: 'Filled' | 'Outlined' | 'Rounded' | 'TwoTone' | 'Sharp';
endIconTheme: 'Filled' | 'Outlined' | 'Rounded' | 'TwoTone' | 'Sharp';
Expand Down Expand Up @@ -48,6 +49,7 @@ Button.defaultProps = {
disableElevation: false,
endIcon: undefined,
fullWidth: false,
inclusiveDisabled: disabled,
startIcon: undefined,
startIconTheme: 'Filled' as 'Filled',
endIconTheme: 'Filled' as 'Filled',
Expand Down Expand Up @@ -78,6 +80,10 @@ addPropertyControls(Button, {
type: ControlType.String,
title: 'Href',
},
inclusiveDisabled: {
type: ControlType.Boolean,
title: 'Inclusive disabled',
},
startIcon: {
type: ControlType.String,
title: 'Start icon',
Expand Down
6 changes: 6 additions & 0 deletions framer/Material-UI.framerfx/code/IconButton.tsx
Expand Up @@ -6,6 +6,7 @@ import { Icon } from './Icon';

interface Props extends MuiIconButtonProps {
disabled: boolean;
inclusiveDisabled: boolean;
icon: string;
iconTheme: 'Filled' | 'Outlined' | 'Rounded' | 'TwoTone' | 'Sharp';
badgeContent: string;
Expand All @@ -30,6 +31,7 @@ export function IconButton(props: Props): JSX.Element {

IconButton.defaultProps = {
disabled: false,
inclusiveDisabled: disabled,
icon: 'favorite',
iconTheme: 'Filled' as 'Filled',
badgeContent: '',
Expand All @@ -43,6 +45,10 @@ addPropertyControls(IconButton, {
type: ControlType.Boolean,
title: 'Disabled',
},
inclusiveDisabled: {
type: ControlType.Boolean,
title: 'Inclusive disabled',
},
icon: {
type: ControlType.String,
title: 'Icon',
Expand Down
5 changes: 5 additions & 0 deletions packages/material-ui/src/Button/Button.d.ts
Expand Up @@ -62,6 +62,11 @@ export type ButtonTypeMap<
* If defined, an `a` element will be used as the root node.
*/
href?: string;
/**
* If `true`, the component is disabled but allows cursor interactions such as mouse hover (for tooltips) and focus.
* @default disabled
*/
inclusiveDisabled?: boolean;
/**
* The size of the component.
* `small` is equivalent to the dense button styling.
Expand Down
14 changes: 12 additions & 2 deletions packages/material-ui/src/Button/Button.js
Expand Up @@ -84,7 +84,7 @@ const ButtonRoot = styled(ButtonBase, {
duration: theme.transitions.duration.short,
},
),
'&:hover': {
'&:hover': !styleProps.inclusiveDisabled && {
textDecoration: 'none',
backgroundColor: alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity),
// Reset on touch devices, it doesn't add specificity
Expand Down Expand Up @@ -142,7 +142,7 @@ const ButtonRoot = styled(ButtonBase, {
boxShadow: theme.shadows[6],
}),
},
[`&.${buttonClasses.disabled}`]: {
[`&.${buttonClasses.disabled}, &.${buttonClasses.inclusiveDisabled}`]: {
color: theme.palette.action.disabled,
...(styleProps.variant === 'outlined' && {
border: `1px solid ${theme.palette.action.disabledBackground}`,
Expand All @@ -157,6 +157,9 @@ const ButtonRoot = styled(ButtonBase, {
backgroundColor: theme.palette.action.disabledBackground,
}),
},
[`&.${buttonClasses.inclusiveDisabled}`]: {
cursor: 'not-allowed',
},
...(styleProps.variant === 'text' && {
padding: '6px 8px',
}),
Expand Down Expand Up @@ -289,6 +292,7 @@ const Button = React.forwardRef(function Button(inProps, ref) {
endIcon: endIconProp,
focusVisibleClassName,
fullWidth = false,
inclusiveDisabled = disabled,
size = 'medium',
startIcon: startIconProp,
type,
Expand Down Expand Up @@ -330,6 +334,7 @@ const Button = React.forwardRef(function Button(inProps, ref) {
disabled={disabled}
focusRipple={!disableFocusRipple}
focusVisibleClassName={clsx(classes.focusVisible, focusVisibleClassName)}
inclusiveDisabled={inclusiveDisabled}
ref={ref}
type={type}
{...other}
Expand Down Expand Up @@ -409,6 +414,11 @@ Button.propTypes /* remove-proptypes */ = {
* If defined, an `a` element will be used as the root node.
*/
href: PropTypes.string,
/**
* If `true`, the component is disabled but allows cursor interactions such as mouse hover (for tooltips) and focus.
* @default disabled
*/
inclusiveDisabled: PropTypes.bool,
/**
* The size of the component.
* `small` is equivalent to the dense button styling.
Expand Down
3 changes: 3 additions & 0 deletions packages/material-ui/src/Button/buttonClasses.ts
Expand Up @@ -33,6 +33,8 @@ export interface ButtonClasses {
focusVisible: string;
/** State class applied to the root element if `disabled={true}`. */
disabled: string;
/** State class applied to the root element if `inclusiveDisabled={true}`. */
inclusiveDisabled: string;
/** Styles applied to the root element if `color="inherit"`. */
colorInherit: string;
/** Styles applied to the root element if `size="small"` and `variant="text"`. */
Expand Down Expand Up @@ -96,6 +98,7 @@ const buttonClasses: ButtonClasses = generateUtilityClasses('MuiButton', [
'disableElevation',
'focusVisible',
'disabled',
'inclusiveDisabled',
'colorInherit',
'textSizeSmall',
'textSizeMedium',
Expand Down
5 changes: 5 additions & 0 deletions packages/material-ui/src/ButtonBase/ButtonBase.d.ts
Expand Up @@ -31,6 +31,11 @@ export interface ButtonBaseTypeMap<P = {}, D extends React.ElementType = 'button
* @default false
*/
disabled?: boolean;
/**
* If `true`, the component is disabled but allows cursor interactions such as mouse hover (for tooltips) and focus.
* @default disabled
*/
inclusiveDisabled?: boolean;
/**
* If `true`, the ripple effect is disabled.
*
Expand Down

0 comments on commit b89ea22

Please sign in to comment.