From 84c2fef72cb8be6d77ce62c21ed6d9d0d866d849 Mon Sep 17 00:00:00 2001 From: Westbrook Johnson Date: Tue, 13 Feb 2024 18:02:41 -0500 Subject: [PATCH] fix(picker): correct implementation of "disabled", expand stories and documentation (#4040) * fix(picker): correct implementation of "disabled", expand stories and documentation * ci: update golden images cache --- .circleci/config.yml | 2 +- packages/picker/src/Picker.ts | 4 ++ packages/picker/src/picker.css | 4 ++ packages/picker/stories/args.ts | 66 ++++++++++++++++++++++ packages/picker/stories/picker.stories.ts | 69 ++++------------------- packages/picker/stories/template.ts | 53 +++++++++++++++++ packages/picker/test/index.ts | 55 ++++++++++++++++++ 7 files changed, 195 insertions(+), 58 deletions(-) create mode 100644 packages/picker/stories/args.ts create mode 100644 packages/picker/stories/template.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 1cd92d42c5..e7ae5989d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 544d1b8027472155a6a451074fdbf96a5b4bf304 + default: 5699acc2aef2078431a090a1efb53ab84c4ecb98 wireit_cache_name: type: string default: wireit diff --git a/packages/picker/src/Picker.ts b/packages/picker/src/Picker.ts index 06d76cc67a..1cad5f4c2e 100644 --- a/packages/picker/src/Picker.ts +++ b/packages/picker/src/Picker.ts @@ -148,6 +148,10 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) { } public forceFocusVisible(): void { + if (this.disabled) { + return; + } + this.focused = true; } diff --git a/packages/picker/src/picker.css b/packages/picker/src/picker.css index e7ebb371f9..43818e8b34 100644 --- a/packages/picker/src/picker.css +++ b/packages/picker/src/picker.css @@ -36,6 +36,10 @@ governing permissions and limitations under the License. min-width: 0; } +:host([disabled]) { + pointer-events: none; +} + #button { width: 100%; min-width: 100%; diff --git a/packages/picker/stories/args.ts b/packages/picker/stories/args.ts new file mode 100644 index 0000000000..8ff6b5f76d --- /dev/null +++ b/packages/picker/stories/args.ts @@ -0,0 +1,66 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +export const argTypes = { + size: { + name: 'size', + type: { name: 'string', required: false }, + description: 'The size at which to display accordion items.', + table: { + defaultValue: { summary: 'm' }, + }, + control: { + labels: { + s: 'Small', + m: 'Medium', + l: 'Large', + xl: 'Extra large', + }, + type: 'select', + }, + }, + quiet: { + name: 'quiet', + type: { name: 'boolean', required: false }, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: false }, + }, + control: { + type: 'boolean', + }, + }, + disabled: { + name: 'disabled', + type: { name: 'boolean', required: false }, + description: + 'Disable this control. It will not receive focus or events.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: false }, + }, + control: { + type: 'boolean', + }, + }, + invalid: { + name: 'invalid', + type: { name: 'boolean', required: false }, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: false }, + }, + control: { + type: 'boolean', + }, + }, +}; diff --git a/packages/picker/stories/picker.stories.ts b/packages/picker/stories/picker.stories.ts index 5d8b95b619..0a0cd339a8 100644 --- a/packages/picker/stories/picker.stories.ts +++ b/packages/picker/stories/picker.stories.ts @@ -13,7 +13,6 @@ governing permissions and limitations under the License. import { html, TemplateResult } from '@spectrum-web-components/base'; import '@spectrum-web-components/picker/sp-picker.js'; -import { Picker } from '@spectrum-web-components/picker'; import '@spectrum-web-components/menu/sp-menu-item.js'; import '@spectrum-web-components/tooltip/sp-tooltip.js'; import '@spectrum-web-components/icons-workflow/icons/sp-icon-edit.js'; @@ -24,6 +23,8 @@ import '@spectrum-web-components/field-label/sp-field-label.js'; import { spreadProps } from '../../../test/lit-helpers.js'; import { isOverlayOpen } from '../../overlay/stories/index.js'; import '../../overlay/stories/index.js'; +import { handleChange, StoryArgs, Template } from './template.js'; +import { argTypes } from './args.js'; export default { title: 'Picker', @@ -36,30 +37,6 @@ export default { }, argTypes: { onChange: { action: 'change' }, - disabled: { - name: 'disabled', - type: { name: 'boolean', required: false }, - description: - 'Disable this control. It will not receive focus or events.', - table: { - type: { summary: 'boolean' }, - defaultValue: { summary: false }, - }, - control: { - type: 'boolean', - }, - }, - invalid: { - name: 'invalid', - type: { name: 'boolean', required: false }, - table: { - type: { summary: 'boolean' }, - defaultValue: { summary: false }, - }, - control: { - type: 'boolean', - }, - }, open: { name: 'open', type: { name: 'boolean', required: false }, @@ -70,37 +47,10 @@ export default { }, control: 'boolean', }, - quiet: { - name: 'quiet', - type: { name: 'boolean', required: false }, - table: { - type: { summary: 'boolean' }, - defaultValue: { summary: false }, - }, - control: { - type: 'boolean', - }, - }, + ...argTypes, }, }; -interface StoryArgs { - disabled?: boolean; - invalid?: boolean; - open?: boolean; - quiet?: boolean; - showText?: boolean; - onChange?: (val: string) => void; - [prop: string]: unknown; -} - -const handleChange = - ({ onChange }: StoryArgs) => - (event: Event): void => { - const picker = event.target as Picker; - if (onChange) onChange(picker.value); - }; - export const Default = (args: StoryArgs): TemplateResult => { return html` Where do you live? @@ -129,6 +79,11 @@ export const Default = (args: StoryArgs): TemplateResult => { `; }; +export const disabled = (args: StoryArgs): TemplateResult => Template(args); +disabled.args = { + disabled: true, +}; + export const tooltip = (args: StoryArgs): TemplateResult => { const { open, ...rest } = args; return html` @@ -252,7 +207,7 @@ export const icons = (args: StoryArgs): TemplateResult => { Choose an action type... { Choose an action type... { Choose an action type... { Choose an action type... void; + [prop: string]: unknown; +} + +export const handleChange = + ({ onChange }: StoryArgs) => + (event: Event): void => { + const picker = event.target as Picker; + if (onChange) onChange(picker.value); + }; + +export const Template = (args: StoryArgs): TemplateResult => html` + Where do you live? + + Carol Gardens + Cobble Hill + Ft. Greene + Park Slope + Prospect Park + Red Hook + +`; diff --git a/packages/picker/test/index.ts b/packages/picker/test/index.ts index 2a6b3948b5..e0244f52bd 100644 --- a/packages/picker/test/index.ts +++ b/packages/picker/test/index.ts @@ -39,6 +39,7 @@ import { } from '@web/test-runner-commands'; import { Default, + disabled, iconsOnly, noVisibleLabel, slottedLabel, @@ -57,6 +58,7 @@ import '@spectrum-web-components/menu/sp-menu-item.js'; import '@spectrum-web-components/theme/src/themes.js'; import type { Menu } from '@spectrum-web-components/menu'; import { Tooltip } from '@spectrum-web-components/tooltip'; +import { FieldLabel } from '@spectrum-web-components/field-label/src/FieldLabel.js'; export type TestablePicker = { optionsMenu: Menu }; @@ -1774,4 +1776,57 @@ export function runPickerTests(): void { expect(tooltipEl.open).to.be.false; expect(el.open).to.be.false; }); + describe('disabled', function () { + beforeEach(async function () { + const test = await fixture(html` +
${disabled(disabled.args)}
+ `); + this.label = test.querySelector('sp-field-label') as FieldLabel; + this.el = test.querySelector('sp-picker') as Picker; + await elementUpdated(this.elel); + }); + it('does not recieve focus from an ``', async function () { + expect(this.el.disabled).to.be.true; + expect(this.el.focused).to.be.false; + + this.label.click(); + await elementUpdated(this.el); + + expect(this.el.focused).to.be.false; + }); + it('does not open from `click()`', async function () { + expect(this.el.disabled).to.be.true; + expect(this.el.open).to.be.false; + + this.el.click(); + await elementUpdated(this.el); + + expect(this.el.open).to.be.false; + }); + it('does not open from `sendMouse()`', async function () { + expect(this.el.disabled).to.be.true; + expect(this.el.open).to.be.false; + + const boundingRect = this.el.button.getBoundingClientRect(); + + sendMouse({ + steps: [ + { + type: 'click', + position: [ + boundingRect.x + boundingRect.width / 2, + boundingRect.y + boundingRect.height / 2, + ], + }, + ], + }); + // Synthetic delay for "open" but not "sp-open" as it would never come. + await nextFrame(); + await nextFrame(); + await nextFrame(); + await nextFrame(); + + expect(this.el.open).to.be.false; + }); + }); }