diff --git a/packages/terra-button/CHANGELOG.md b/packages/terra-button/CHANGELOG.md index 88d28821c9d..c1a99941cbb 100644 --- a/packages/terra-button/CHANGELOG.md +++ b/packages/terra-button/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +* Changed + * Added support of selection state for Fusion-Button + ## 3.68.2 - (October 3, 2023) * Fixed diff --git a/packages/terra-button/src/Button.jsx b/packages/terra-button/src/Button.jsx index 52ec953fdf0..2667bbc2edf 100644 --- a/packages/terra-button/src/Button.jsx +++ b/packages/terra-button/src/Button.jsx @@ -118,7 +118,7 @@ const defaultProps = { class Button extends React.Component { constructor(props) { super(props); - this.state = { active: false, focused: false }; + this.state = { active: false, focused: false, isSelected: false }; this.handleKeyDown = this.handleKeyDown.bind(this); this.handleKeyUp = this.handleKeyUp.bind(this); this.handleOnBlur = this.handleOnBlur.bind(this); @@ -144,7 +144,7 @@ class Button extends React.Component { } } - handleClick(event) { + handleClick(event, isSelectable) { // See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Button#Clicking_and_focus // Button on Firefox, Safari and IE running on OS X does not receive focus when clicked. // This will put focus on the button when clicked if it is not currently the active element. @@ -155,11 +155,15 @@ class Button extends React.Component { } if (this.props.onClick) { - this.props.onClick(event); + if (isSelectable) { + this.props.onClick(event, this.state.isSelected); + } else { + this.props.onClick(event); + } } } - handleKeyDown(event) { + handleKeyDown(event, isSelectable) { // Add active state to FF browsers if (event.nativeEvent.keyCode === KeyCode.KEY_SPACE) { this.setState({ active: true }); @@ -175,6 +179,9 @@ class Button extends React.Component { // Add focus styles for keyboard navigation if (event.nativeEvent.keyCode === KeyCode.KEY_SPACE || event.nativeEvent.keyCode === KeyCode.KEY_RETURN) { this.setState({ focused: true }); + if (isSelectable) { + this.setState(prevState => ({ isSelected: !prevState.isSelected })); + } } if (this.props.onKeyDown) { @@ -208,10 +215,13 @@ class Button extends React.Component { } } - handleMouseDown(event) { + handleMouseDown(event, isSelectable) { if (this.props.onMouseDown) { this.props.onMouseDown(event); } + if (isSelectable) { + this.setState(prevState => ({ isSelected: !prevState.isSelected })); + } // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus#Notes // If you call HTMLElement.focus() from a mousedown event handler, you must call event.preventDefault() to keep the focus from leaving the HTMLElement. @@ -246,6 +256,9 @@ class Button extends React.Component { const isMac = () => navigator.userAgent.indexOf('Mac') !== -1; const buttonLabelCx = isMac() ? 'button-label-mac' : 'button-label-win'; + // TODO: `isSelectable` prop is used for fusion pass through passivity and should be removed after Fusion Phase2 release. + const { isSelectable } = customProps; + const buttonClasses = classNames( cx([ 'button', @@ -255,6 +268,7 @@ class Button extends React.Component { { compact: isCompact }, { 'is-active': this.state.active && !isDisabled }, { 'is-focused': this.state.focused && !isDisabled }, + { 'is-selected': isSelectable && this.state.isSelected && !isDisabled }, theme.className, ]), customProps.className, @@ -302,6 +316,10 @@ class Button extends React.Component { ariaLabel = (icon && icon.props.a11yLabel) ? icon.props.a11yLabel : ariaLabel || text; } + if (isSelectable) { + customProps['aria-pressed'] = this.state.isSelected; + } + let ComponentType = 'button'; if (href) { ComponentType = 'a'; @@ -317,12 +335,12 @@ class Button extends React.Component { tabIndex={isDisabled ? '-1' : customProps.tabIndex} aria-disabled={isDisabled} aria-label={ariaLabel} - onKeyDown={this.handleKeyDown} + onKeyDown={(event) => { this.handleKeyDown(event, isSelectable); }} onKeyUp={this.handleKeyUp} onBlur={this.handleOnBlur} title={buttonTitle} - onClick={this.handleClick} - onMouseDown={this.handleMouseDown} + onClick={(event) => { this.handleClick(event, isSelectable); }} + onMouseDown={(event) => { this.handleMouseDown(event, isSelectable); }} onFocus={this.handleFocus} href={href} ref={refCallback} diff --git a/packages/terra-button/src/Button.module.scss b/packages/terra-button/src/Button.module.scss index 8469583e890..5b65abd2d3b 100644 --- a/packages/terra-button/src/Button.module.scss +++ b/packages/terra-button/src/Button.module.scss @@ -78,6 +78,34 @@ opacity: var(--terra-button-disabled-opacity, 0.3); pointer-events: none; // prevent pointer interaction for anchor elements } + + &.is-selected.is-focused { + background-color: var(--terra-button-selected-and-focus-background-color, #52585b); + border-color: var(--terra-button-selected-and-focus-border-color, #52585b); + box-shadow: var(--terra-button-selected-and-focus-box-shadow, 0 0 1px 3px rgba(76, 178, 233, 0.5), 0 0 7px 4px rgba(76, 178, 233, 0.35)); + color: var(--terra-button-selected-and-focus-color, #fff); + } + + &.is-selected { + background-color: var(--terra-button-selected-background-color, #52585b); + border-color: var(--terra-button-selected-border-color, #52585b); + box-shadow: var(--terra-button-selected-box-shadow); + color: var(--terra-button-selected-color, #fff); + } + + &.is-selected:active { + background-color: var(--terra-button-selected-and-active-background-color, #52585b); + border-color: var(--terra-button-selected-and-active-border-color, #52585b); + box-shadow: var(--terra-button-selected-and-active-box-shadow); + color: var(--terra-button-selected-and-active-color, #fff); + } + + &.is-selected:hover { + background-color: var(--terra-button-selected-and-hover-background-color, #40474a); + border-color: var(--terra-button-selected-and-hover-border-color, #40474a); + box-shadow: var(--terra-button-selected-and-hover-box-shadow); + color: var(--terra-button-selected-and-hover-color, #fff); + } } .button-label-mac { diff --git a/packages/terra-button/src/clinical-lowlight-theme/Button.module.scss b/packages/terra-button/src/clinical-lowlight-theme/Button.module.scss index 780750b5203..90f855e48af 100644 --- a/packages/terra-button/src/clinical-lowlight-theme/Button.module.scss +++ b/packages/terra-button/src/clinical-lowlight-theme/Button.module.scss @@ -190,5 +190,26 @@ --terra-button-hover-background-color-utility: transparent; --terra-button-hover-border-color-utility: transparent; --terra-button-hover-color-utility: #b2b5b6; + + // isSelected button + --terra-button-selected-background-color: #1a2023; + --terra-button-selected-border-color: #181b1d; + --terra-button-selected-box-shadow: none; + --terra-button-selected-color: #9b9b9b; + + --terra-button-selected-and-focus-background-color: #1a2023; + --terra-button-selected-and-focus-border-color: #181b1d; + --terra-button-selected-and-focus-box-shadow: 0 0 1px 3px rgba(76, 178, 233, 0.5), 0 0 7px 4px rgba(76, 178, 233, 0.35); + --terra-button-selected-and-focus-color: #9b9b9b; + + --terra-button-selected-and-active-background-color: #1a2023; + --terra-button-selected-and-active-border-color: #181b1d; + --terra-button-selected-and-active-box-shadow: none; + --terra-button-selected-and-active-color: #9b9b9b; + + --terra-button-selected-and-hover-background-color: #121517; + --terra-button-selected-and-hover-border-color: #181b1d; + --terra-button-selected-and-hover-box-shadow: none; + --terra-button-selected-and-hover-color: #9b9b9b; } } diff --git a/packages/terra-button/src/orion-fusion-theme/Button.module.scss b/packages/terra-button/src/orion-fusion-theme/Button.module.scss index 300172853cf..9461a961c4b 100644 --- a/packages/terra-button/src/orion-fusion-theme/Button.module.scss +++ b/packages/terra-button/src/orion-fusion-theme/Button.module.scss @@ -190,5 +190,26 @@ --terra-button-hover-background-color-utility: transparent; --terra-button-hover-border-color-utility: transparent; --terra-button-hover-color-utility: #004c76; + + // isSelected button + --terra-button-selected-and-hover-background-color: #52585b; + --terra-button-selected-and-hover-border-color: #6f7477; + --terra-button-selected-and-hover-box-shadow: none; + --terra-button-selected-and-hover-color: #fff; + + --terra-button-selected-and-focus-background-color: #52585b; + --terra-button-selected-and-focus-border-color: #6f7477; + --terra-button-selected-and-focus-box-shadow: 0 0 1px 1px rgba(255, 255, 255, 0.65), 0 0 2px 3px rgba(76, 178, 233, 0.5), 0 0 6px 4px rgba(76, 178, 233, 0.3); + --terra-button-selected-and-focus-color: #fff; + + --terra-button-selected-background-color: #52585b; + --terra-button-selected-border-color: #6f7477; + --terra-button-selected-box-shadow: inset 0 3rem 1.5rem -2rem #434a4d; + --terra-button-selected-color: #fff; + + --terra-button-selected-and-active-background-color: #52585b; + --terra-button-selected-and-active-border-color: #6f7477; + --terra-button-selected-and-active-box-shadow: inset 0 3rem 1.5rem -2rem #434a4d; + --terra-button-selected-and-active-and-color: #fff; } } diff --git a/packages/terra-button/tests/wdio/__snapshots__/reference/clinical-lowlight-theme/en/chrome_tiny/button-spec/selected-button.png b/packages/terra-button/tests/wdio/__snapshots__/reference/clinical-lowlight-theme/en/chrome_tiny/button-spec/selected-button.png new file mode 100644 index 00000000000..ec758c10558 Binary files /dev/null and b/packages/terra-button/tests/wdio/__snapshots__/reference/clinical-lowlight-theme/en/chrome_tiny/button-spec/selected-button.png differ diff --git a/packages/terra-button/tests/wdio/__snapshots__/reference/orion-fusion-theme/en/chrome_tiny/button-spec/selected-button.png b/packages/terra-button/tests/wdio/__snapshots__/reference/orion-fusion-theme/en/chrome_tiny/button-spec/selected-button.png new file mode 100644 index 00000000000..9b3dc58a08e Binary files /dev/null and b/packages/terra-button/tests/wdio/__snapshots__/reference/orion-fusion-theme/en/chrome_tiny/button-spec/selected-button.png differ diff --git a/packages/terra-button/tests/wdio/__snapshots__/reference/terra-default-theme/en/chrome_tiny/button-spec/selected-button.png b/packages/terra-button/tests/wdio/__snapshots__/reference/terra-default-theme/en/chrome_tiny/button-spec/selected-button.png new file mode 100644 index 00000000000..0a225c7cf0e Binary files /dev/null and b/packages/terra-button/tests/wdio/__snapshots__/reference/terra-default-theme/en/chrome_tiny/button-spec/selected-button.png differ diff --git a/packages/terra-button/tests/wdio/button-spec.js b/packages/terra-button/tests/wdio/button-spec.js index 0f861a8ae77..7ee2272428e 100644 --- a/packages/terra-button/tests/wdio/button-spec.js +++ b/packages/terra-button/tests/wdio/button-spec.js @@ -255,4 +255,12 @@ Terra.describeViewports('Button', ['tiny'], () => { Terra.validates.element('programmatic re-enabled -Enabled Button is not focused', { selector: '#root' }); }); }); + + describe('Selectable button', () => { + it('displays selected button', () => { + browser.url('/raw/tests/cerner-terra-core-docs/button/selectable-button'); + $('