diff --git a/packages/components/src/components/segment/readme.md b/packages/components/src/components/segment/readme.md index 249d97f3ad..089e5cd0ec 100644 --- a/packages/components/src/components/segment/readme.md +++ b/packages/components/src/components/segment/readme.md @@ -20,7 +20,7 @@ | `position` | `position` | (optional) position within group | `number` | `undefined` | | `segmentId` | `segment-id` | (optional) segment's id | `string` | `'segment-' + i++` | | `selected` | `selected` | (optional) If `true`, the segment is selected | `boolean` | `false` | -| `selectedIndex` | `selected-index` | (optional) the index of the currently selected segment in the segmented-button | `string` | `undefined` | +| `selectedIndex` | `selected-index` | (optional) the index of the currently selected segment in the segmented-button | `number` | `undefined` | | `size` | `size` | (optional) The size of the segment | `"large" \| "medium" \| "small"` | `'small'` | | `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | | `textOnly` | `text-only` | (optional) position within group | `boolean` | `undefined` | diff --git a/packages/components/src/components/segment/segment.tsx b/packages/components/src/components/segment/segment.tsx index 67b45ffa82..29ddffb507 100644 --- a/packages/components/src/components/segment/segment.tsx +++ b/packages/components/src/components/segment/segment.tsx @@ -18,6 +18,7 @@ import { Event, EventEmitter, Method, + Watch, } from '@stencil/core'; import classNames from 'classnames'; import { emitEvent } from '../../utils/utils'; @@ -65,7 +66,7 @@ export class Segment { /** (optional) position within group */ @Prop({ mutable: true }) iconOnly?: boolean; /** (optional) the index of the currently selected segment in the segmented-button */ - @Prop({ mutable: true }) selectedIndex?: string; + @Prop({ mutable: true }) selectedIndex?: number; /** Emitted when button is clicked */ @Event({ eventName: 'scale-click' }) scaleClick!: EventEmitter<{ @@ -80,6 +81,14 @@ export class Segment { private focusableElement: HTMLElement; + @Watch('selected') + selectionChanged() { + emitEvent(this, 'scaleClick', { + id: this.segmentId, + selected: this.selected, + }); + } + @Method() async setFocus() { this.focusableElement.focus(); @@ -150,15 +159,11 @@ export class Segment { } handleClick = (event: MouseEvent) => { - if (parseInt(this.selectedIndex, 10) + 1 === this.position) { + if (this.selectedIndex === this.position) { return; } event.preventDefault(); this.selected = !this.selected; - emitEvent(this, 'scaleClick', { - id: this.segmentId, - selected: this.selected, - }); }; render() { diff --git a/packages/components/src/components/segmented-button/__snapshots__/segmented-button.spec.ts.snap b/packages/components/src/components/segmented-button/__snapshots__/segmented-button.spec.ts.snap index 82e5bc5170..f3cc15e81d 100644 --- a/packages/components/src/components/segmented-button/__snapshots__/segmented-button.spec.ts.snap +++ b/packages/components/src/components/segmented-button/__snapshots__/segmented-button.spec.ts.snap @@ -7,10 +7,10 @@ exports[`SegmentedButton should match selected button snapshot 1`] = ` - + Label - + Label @@ -23,17 +23,17 @@ exports[`SegmentedButton should match standard snapshot 1`] = ` - + Label - + Label - + Label - + Label -`; \ No newline at end of file +`; diff --git a/packages/components/src/components/segmented-button/segmented-button.spec.ts b/packages/components/src/components/segmented-button/segmented-button.spec.ts index aadc728f1e..51392c20e6 100644 --- a/packages/components/src/components/segmented-button/segmented-button.spec.ts +++ b/packages/components/src/components/segmented-button/segmented-button.spec.ts @@ -43,7 +43,7 @@ describe('SegmentedButton', () => { html: ` Label - Label + Label `, }); expect(page.root).toMatchSnapshot(); diff --git a/packages/components/src/components/segmented-button/segmented-button.tsx b/packages/components/src/components/segmented-button/segmented-button.tsx index e32fbc09ef..11982f9805 100644 --- a/packages/components/src/components/segmented-button/segmented-button.tsx +++ b/packages/components/src/components/segmented-button/segmented-button.tsx @@ -15,7 +15,6 @@ import { h, Host, Element, - State, Listen, Event, EventEmitter, @@ -45,8 +44,6 @@ export class SegmentedButton { slottedSegments = 0; @Element() hostElement: HTMLElement; - /** state */ - @State() status: SegmentStatus[] = []; /** (optional) The size of the button */ @Prop() size?: 'small' | 'medium' | 'large' = 'small'; /** (optional) Allow more than one button to be selected */ @@ -79,24 +76,26 @@ export class SegmentedButton { showHelperText = false; @Listen('scaleClick') scaleClickHandler(ev: { detail: { id: string; selected: boolean } }) { - let tempState: SegmentStatus[]; + let tempState = this.getAllSegments().map((segment) => { + return { + id: segment.segmentId, + selected: segment.selected, + }; + }); if (!this.multiSelect) { if (!ev.detail.selected) { - tempState = this.status.map((obj) => + tempState = tempState.map((obj) => ev.detail.id === obj.id ? ev.detail : { ...obj } ); - /* clicked button has now selected state */ } else { - tempState = this.status.map((obj) => + tempState = tempState.map((obj) => ev.detail.id === obj.id ? ev.detail : { ...obj, selected: false } ); } + this.setState(tempState, ev.detail.selected); } else { - tempState = this.status.map((obj) => - ev.detail.id === obj.id ? ev.detail : { ...obj } - ); + this.setState(tempState); } - this.setState(tempState); } @Watch('disabled') @@ -111,10 +110,10 @@ export class SegmentedButton { */ propagatePropsToChildren() { this.getAllSegments().forEach((segment) => { - segment.setAttribute('size', this.size); - segment.setAttribute('selected-index', this.selectedIndex.toString()); + segment.size = this.size; + segment.selectedIndex = this.selectedIndex; if (this.disabled) { - segment.setAttribute('disabled', true && 'disabled'); + segment.disabled = true; } }); } @@ -125,17 +124,13 @@ export class SegmentedButton { this.slottedSegments = segments.length; segments.forEach((segment, i) => { tempState.push({ - id: segment.getAttribute('segment-id') || segment.segmentId, - selected: segment.hasAttribute('selected') || segment.selected, + id: segment.segmentId, + selected: segment.selected, }); - segment.setAttribute('position', `${i + 1}`); - segment.setAttribute( - 'aria-description-translation', - '$position $selected' - ); + segment.position = i; + segment.ariaDescriptionTranslation = '$position $selected'; }); - this.setState(tempState); - this.selectedIndex = this.getSelectedIndex(); + this.setState(tempState, false); this.showHelperText = this.shouldShowHelperText(); } componentDidLoad() { @@ -153,15 +148,11 @@ export class SegmentedButton { } componentWillUpdate() { - this.selectedIndex = this.getSelectedIndex(); this.showHelperText = this.shouldShowHelperText(); } shouldShowHelperText() { let showHelperText = false; - if ( - this.invalid && - this.status.filter((e) => e.selected === true).length <= 0 - ) { + if (this.invalid && this.selectedIndex < 0) { showHelperText = true; } return showHelperText; @@ -176,12 +167,13 @@ export class SegmentedButton { const selectedIndex = allSegments.findIndex( (el: HTMLScaleSegmentElement) => el.selected === true ); - return selectedIndex; + // we need to return -2 if no segment is selected + return selectedIndex >= 0 ? selectedIndex : -2; } } getAdjacentSiblings = (tempState, i) => { - let adjacentSiblings = ''; + let adjacentSiblings = null; if (i !== 0 && tempState[i].selected && tempState[i - 1].selected) { adjacentSiblings = 'left'; } @@ -226,22 +218,18 @@ export class SegmentedButton { return tempWidth; } - setState(tempState: SegmentStatus[]) { + setState(tempState: SegmentStatus[], handleEvent: boolean = true) { const segments = Array.from( this.hostElement.querySelectorAll('scale-segment') ); segments.forEach((segment, i) => { - segment.setAttribute( - 'adjacent-siblings', - this.getAdjacentSiblings(tempState, i) - ); - segment.setAttribute( - 'selected', - tempState[i].selected ? 'true' : 'false' - ); + segment.adjacentSiblings = this.getAdjacentSiblings(tempState, i); + segment.selected = tempState[i].selected; }); - this.status = tempState; - emitEvent(this, 'scaleChange', this.status); + this.selectedIndex = this.getSelectedIndex(); + if (handleEvent) { + emitEvent(this, 'scaleChange', { segments }); + } } getAllSegments() {