Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
[terra-button] Allow programmatic toggle of selectable button (#3955)
Browse files Browse the repository at this point in the history
Co-authored-by: Sugan G <[email protected]>
  • Loading branch information
sugan2416 and Sugan G authored Oct 31, 2023
1 parent 376977c commit bc5cf44
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 35 deletions.
3 changes: 3 additions & 0 deletions packages/terra-button/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Changed
* Added support to programmatically set selection state for Fusion-Button

## 3.69.0 - (October 23, 2023)

* Changed
Expand Down
34 changes: 12 additions & 22 deletions packages/terra-button/src/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const defaultProps = {
class Button extends React.Component {
constructor(props) {
super(props);
this.state = { active: false, focused: false, isSelected: false };
this.state = { active: false, focused: false };
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.handleOnBlur = this.handleOnBlur.bind(this);
Expand All @@ -144,7 +144,7 @@ class Button extends React.Component {
}
}

handleClick(event, isSelectable) {
handleClick(event) {
// 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.
Expand All @@ -155,15 +155,11 @@ class Button extends React.Component {
}

if (this.props.onClick) {
if (isSelectable) {
this.props.onClick(event, this.state.isSelected);
} else {
this.props.onClick(event);
}
this.props.onClick(event);
}
}

handleKeyDown(event, isSelectable) {
handleKeyDown(event) {
// Add active state to FF browsers
if (event.nativeEvent.keyCode === KeyCode.KEY_SPACE) {
this.setState({ active: true });
Expand All @@ -179,9 +175,6 @@ 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) {
Expand Down Expand Up @@ -215,13 +208,10 @@ class Button extends React.Component {
}
}

handleMouseDown(event, isSelectable) {
handleMouseDown(event) {
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.
Expand Down Expand Up @@ -256,8 +246,8 @@ 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;
// TODO: `isSelectable` and `isSelected` prop is used for fusion pass through passivity and should be removed after Fusion Phase2 release.
const { isSelectable, isSelected } = customProps;

const buttonClasses = classNames(
cx([
Expand All @@ -268,7 +258,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 },
{ 'is-selected': isSelectable && isSelected && !isDisabled },
theme.className,
]),
customProps.className,
Expand Down Expand Up @@ -317,7 +307,7 @@ class Button extends React.Component {
}

if (isSelectable) {
customProps['aria-pressed'] = this.state.isSelected;
customProps['aria-pressed'] = isSelected;
}

let ComponentType = 'button';
Expand All @@ -335,12 +325,12 @@ class Button extends React.Component {
tabIndex={isDisabled ? '-1' : customProps.tabIndex}
aria-disabled={isDisabled}
aria-label={ariaLabel}
onKeyDown={(event) => { this.handleKeyDown(event, isSelectable); }}
onKeyDown={(event) => { this.handleKeyDown(event); }}
onKeyUp={this.handleKeyUp}
onBlur={this.handleOnBlur}
title={buttonTitle}
onClick={(event) => { this.handleClick(event, isSelectable); }}
onMouseDown={(event) => { this.handleMouseDown(event, isSelectable); }}
onClick={(event) => { this.handleClick(event); }}
onMouseDown={(event) => { this.handleMouseDown(event); }}
onFocus={this.handleFocus}
href={href}
ref={refCallback}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/terra-button/tests/wdio/button-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ Terra.describeViewports('Button', ['tiny'], () => {
describe('Selectable button', () => {
it('displays selected button', () => {
browser.url('/raw/tests/cerner-terra-core-docs/button/selectable-button');
$('<button>').click();
$('#button1').click();
Terra.validates.element('selected-button');
});
});
Expand Down
3 changes: 3 additions & 0 deletions packages/terra-core-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Updated
* Updated example for selection state of Fusion-Button in `terra-button`.

## 1.47.0 - (October 26, 2023)

* Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import React, { useState } from 'react';
import React, { useState, useRef } from 'react';
import Button from 'terra-button';
import classNames from 'classnames/bind';
import styles from './ButtonTestCommon.module.scss';

const cx = classNames.bind(styles);

const SelectableButton = () => {
const [text, setText] = useState('Unselected');

const handleSelection = (event, toggledState) => {
if (toggledState) {
setText('Selected');
} else {
setText('Unselected');
}
};
const [isSelected, setIsSelected] = useState(false);
const button1 = useRef();
const handleSelection = () => { setIsSelected(prevState => !prevState); };

return (
<div>
<p>
Status:
{' '}
{text}
{isSelected ? 'Selected' : 'Unselected'}
</p>
<Button text="Click Me" className={cx('button')} isSelectable onClick={handleSelection} />
<Button id="button1" text="Click Me" className={cx('button')} isSelectable isSelected={isSelected} onClick={handleSelection} refCallback={(ref) => { button1.current = ref; }} />
<br />
<br />
<Button text="Toggle" onClick={() => button1.current.click()} />
</div>
);
};
Expand Down

0 comments on commit bc5cf44

Please sign in to comment.