Skip to content

Commit

Permalink
fix(action-group): separate first selection management from later sel…
Browse files Browse the repository at this point in the history
…ection management
  • Loading branch information
Westbrook committed Aug 14, 2023
1 parent d5b011f commit 783b206
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 19 deletions.
50 changes: 33 additions & 17 deletions packages/action-group/src/ActionGroup.ts
Expand Up @@ -18,7 +18,10 @@ import {
SpectrumElement,
TemplateResult,
} from '@spectrum-web-components/base';
import { property } from '@spectrum-web-components/base/src/decorators.js';
import {
property,
query,
} from '@spectrum-web-components/base/src/decorators.js';
import type { ActionButton } from '@spectrum-web-components/action-button';
import { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';
import { MutationController } from '@lit-labs/observers/mutation-controller.js';
Expand All @@ -40,9 +43,10 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
return [styles];
}

public set buttons(tabs: ActionButton[]) {
if (tabs === this.buttons) return;
this._buttons = tabs;
public set buttons(buttons: ActionButton[]) {
/* c8 ignore next 1 */
if (buttons === this.buttons) return;
this._buttons = buttons;
this.rovingTabindexController.clearElementCache();
}

Expand All @@ -65,6 +69,7 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
callback: () => {
this.manageButtons();
},
skipInitial: true,
});
}

Expand Down Expand Up @@ -128,6 +133,9 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
return this._selected;
}

@query('slot')
slotElement!: HTMLSlotElement;

private dispatchChange(old: string[]): void {
const applyDefault = this.dispatchEvent(
new Event('change', {
Expand All @@ -146,6 +154,7 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
}

private setSelected(selected: string[], announce?: boolean): void {
/* c8 ignore next 1 */
if (selected === this.selected) return;

const old = this.selected;
Expand All @@ -167,7 +176,7 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
el.selected = false;
el.tabIndex = -1;
el.setAttribute(
!this.selects ? 'aria-pressed' : 'aria-checked',
this.selects ? 'aria-checked' : /* c8 ignore */ 'aria-pressed',
'false'
);
});
Expand Down Expand Up @@ -363,17 +372,21 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
if (this.static || changes?.get('static')) {
button.static = this.static;
}
button.selected = this.selected.includes(button.value);
if (this.selects || !this.hasManaged) {
button.selected = this.selected.includes(button.value);
}
if (this.size) {
button.size = this.size;
}
});
}

private hasManaged = false;

private manageButtons = (): void => {
const slot = this.shadowRoot.querySelector('slot');
if (!slot) return;
const assignedElements = slot.assignedElements({ flatten: true });
const assignedElements = this.slotElement.assignedElements({
flatten: true,
});
const buttons = assignedElements.reduce((acc: unknown[], el) => {
if (el.matches(this._buttonSelector)) {
acc.push(el);
Expand All @@ -386,15 +399,18 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
return acc;
}, []);
this.buttons = buttons as ActionButton[];
// <selected> element merges selected so following paradigm here
const currentlySelectedButtons: string[] = [];
this.buttons.forEach((button: ActionButton) => {
if (button.selected) {
currentlySelectedButtons.push(button.value);
}
});
this.setSelected(this.selected.concat(currentlySelectedButtons));
if (this.selects || !this.hasManaged) {
// <select> element merges selected so following paradigm here
const currentlySelectedButtons: string[] = [];
this.buttons.forEach((button: ActionButton) => {
if (button.selected) {
currentlySelectedButtons.push(button.value);
}
});
this.setSelected(this.selected.concat(currentlySelectedButtons));
}
this.manageChildren();
this.manageSelects();
this.hasManaged = true;
};
}
196 changes: 195 additions & 1 deletion packages/action-group/stories/action-group-tooltip.stories.ts
Expand Up @@ -10,7 +10,12 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

import { html, TemplateResult } from '@spectrum-web-components/base';
import {
html,
SpectrumElement,
TemplateResult,
} from '@spectrum-web-components/base';
import { state } from '@spectrum-web-components/base/src/decorators.js';
import { spreadProps } from '../../../test/lit-helpers.js';

import '@spectrum-web-components/action-group/sp-action-group.js';
Expand Down Expand Up @@ -217,3 +222,192 @@ vertical.args = {
vertical: true,
selects: undefined,
};

class ActionGroupTooltips extends SpectrumElement {
@state()
alignment = 'left';

protected override render(): TemplateResult {
return html`
<sp-action-group quiet>
<sp-action-button
quiet
value="left"
?selected=${this.alignment === 'left'}
@click=${() => {
this.alignment = 'left';
}}
>
<sp-icon slot="icon">
<svg
role="img"
fill="currentColor"
viewBox="0 0 18 18"
id="STextAlignLeft18N-icon"
width="18"
height="18"
aria-hidden="true"
focusable="false"
>
<rect
fill-rule="evenodd"
x="2"
y="14"
width="12"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="2"
y="2"
width="15"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="2"
y="6"
width="12"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="2"
y="10"
width="15"
height="2"
rx="0.5"
></rect>
</svg>
</sp-icon>
<sp-tooltip self-managed placement="bottom" offset="0">
Left align
</sp-tooltip>
</sp-action-button>
<sp-action-button
quiet
value="center"
?selected=${this.alignment === 'center'}
@click=${() => {
this.alignment = 'center';
}}
>
<sp-icon slot="icon">
<svg
role="img"
fill="currentColor"
viewBox="0 0 18 18"
id="STextAlignCenter18N-icon"
width="18"
height="18"
aria-hidden="true"
focusable="false"
>
<rect
fill-rule="evenodd"
x="4"
y="14"
width="10"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="1"
y="10"
width="16"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="1"
y="2"
width="16"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="4"
y="6"
width="10"
height="2"
rx="0.5"
></rect>
</svg>
</sp-icon>
<sp-tooltip self-managed placement="bottom" offset="0">
Center align
</sp-tooltip>
</sp-action-button>
<sp-action-button
quiet
value="right"
?selected=${this.alignment === 'right'}
@click=${() => {
this.alignment = 'right';
}}
>
<sp-icon slot="icon">
<svg
role="img"
fill="currentColor"
viewBox="0 0 18 18"
id="STextAlignRight18N-icon"
width="18"
height="18"
aria-hidden="true"
focusable="false"
>
<rect
fill-rule="evenodd"
x="4"
y="14"
width="12"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="1"
y="2"
width="15"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="4"
y="6"
width="12"
height="2"
rx="0.5"
></rect>
<rect
fill-rule="evenodd"
x="1"
y="10"
width="15"
height="2"
rx="0.5"
></rect>
</svg>
</sp-icon>
<sp-tooltip self-managed placement="bottom" offset="0">
Right align
</sp-tooltip>
</sp-action-button>
</sp-action-group>
`;
}
}

customElements.define('action-group-tooltips', ActionGroupTooltips);

export const controlled = (): TemplateResult => html`
<action-group-tooltips></action-group-tooltips>
`;
1 change: 1 addition & 0 deletions packages/action-group/stories/action-group.stories.ts
Expand Up @@ -153,6 +153,7 @@ function displaySelectionState(): void {
selectedDiv.textContent = `Selected: ${JSON.stringify(group.selected)}`;
}
}

export const Default = (args: Properties): TemplateResult =>
renderButtons(args);

Expand Down

0 comments on commit 783b206

Please sign in to comment.