Skip to content

Commit

Permalink
fix: button interaction, stories
Browse files Browse the repository at this point in the history
  • Loading branch information
DavideMininni-Fincons committed Mar 21, 2024
1 parent ed2b24b commit 3e5be5a
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,22 @@ const negative: InputType = {
},
};

const disabled: InputType = {
control: {
type: 'boolean',
},
};

const defaultArgTypes: ArgTypes = {
numberOfButtons,
negative,
disabled,
};

const defaultArgs: Args = {
numberOfButtons: 1,
negative: false,
disabled: false,
};

const Template = ({ numberOfButtons, ...args }: Args): TemplateResult => html`
Expand Down Expand Up @@ -70,6 +78,12 @@ export const Negative: StoryObj = {
args: { ...defaultArgs, negative: true },
};

export const Disabled: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, disabled: true },
};

export const Multiple: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { withActions } from '@storybook/addon-actions/decorator';
import { userEvent, within } from '@storybook/test';
import type { InputType } from '@storybook/types';
import type {
Args,
Expand All @@ -8,16 +9,21 @@ import type {
StoryContext,
StoryObj,
} from '@storybook/web-components';
import isChromatic from 'chromatic';
import { html, nothing, type TemplateResult } from 'lit';
import { repeat } from 'lit/directives/repeat.js';
import { styleMap } from 'lit/directives/style-map.js';
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';

import { waitForComponentsReady } from '../../../storybook/testing/wait-for-components-ready';
import { waitForStablePosition } from '../../../storybook/testing/wait-for-stable-position';
import type { SbbAutocompleteGridButtonElement } from '../autocomplete-grid-button';
import { SbbAutocompleteGridOptionElement } from '../autocomplete-grid-option';

import { SbbAutocompleteGridElement } from './autocomplete-grid';
import readme from './readme.md?raw';

import '../autocomplete-grid-row';
import '../autocomplete-grid-optgroup';
import '../autocomplete-grid-actions';
import '../autocomplete-grid-button';
import '../../form-field';
Expand All @@ -33,6 +39,66 @@ const wrapperStyle = (context: StoryContext): Record<string, string> => ({
'background-color': context.args.negative ? 'var(--sbb-color-black)' : 'var(--sbb-color-white)',
});

const textBlockStyle: Readonly<StyleInfo> = {
position: 'relative',
marginBlockStart: '1rem',
padding: '1rem',
backgroundColor: 'var(--sbb-color-milk)',
border: 'var(--sbb-border-width-1x) solid var(--sbb-color-cloud)',
borderRadius: 'var(--sbb-border-radius-4x)',
zIndex: '100',
};

const codeStyle: Readonly<StyleInfo> = {
padding: 'var(--sbb-spacing-fixed-1x) var(--sbb-spacing-fixed-2x)',
borderRadius: 'var(--sbb-border-radius-4x)',
backgroundColor: 'var(--sbb-color-smoke-alpha-20)',
};

const textBlock = (): TemplateResult => html`
<div style=${styleMap(textBlockStyle)}>
This text block has a <code style=${styleMap(codeStyle)}>z-index</code> greater than the form
field, but it must always be covered by the autocomplete overlay.
</div>
`;

const aboveDecorator: Decorator = (story) => html`
<div
style=${styleMap({
height: '100%',
display: 'flex',
'align-items': 'end',
})}
>
${story()}
</div>
`;

const scrollDecorator: Decorator = (story) => html`
<div
style=${styleMap({
height: '175%',
display: 'flex',
'align-items': 'center',
})}
>
${story()}
</div>
`;

// Story interaction executed after the story renders
const playStory = async ({ canvasElement }: StoryContext): Promise<void> => {
const canvas = within(canvasElement);

await waitForComponentsReady(() =>
canvas.getByTestId('form-field').shadowRoot!.querySelector('div.sbb-form-field__space-wrapper'),
);

await waitForStablePosition(() => canvas.getByTestId('autocomplete-input'));
await userEvent.type(canvas.getByTestId('autocomplete-input'), 'Opt');
await new Promise((resolve) => setTimeout(resolve, 2000));
};

const negative: InputType = {
control: {
type: 'boolean',
Expand Down Expand Up @@ -123,6 +189,15 @@ const buttonIconName: InputType = {
},
};

const disableGroup: InputType = {
control: {
type: 'boolean',
},
table: {
category: 'Option group',
},
};

const defaultArgTypes: ArgTypes = {
// Form field args
negative,
Expand All @@ -145,6 +220,13 @@ const defaultArgTypes: ArgTypes = {
buttonIconName,
};

const withGroupsArgTypes: ArgTypes = {
...defaultArgTypes,

// Option group args
disableGroup,
};

const defaultArgs: Args = {
// Form field args
negative: false,
Expand All @@ -167,6 +249,13 @@ const defaultArgs: Args = {
buttonIconName: 'pen-small',
};

const withGroupsDefaultArgs: Args = {
...defaultArgs,

// Option group args
disableGroup: false,
};

const createRows1 = (
optionIconName: string,
buttonIconName: string,
Expand Down Expand Up @@ -222,30 +311,40 @@ const createRows2 = (buttonIconName: string, disableOption: boolean): TemplateRe
)}
`;

const textBlockStyle: Args = {
position: 'relative',
marginBlockStart: '1rem',
padding: '1rem',
backgroundColor: 'var(--sbb-color-milk)',
border: 'var(--sbb-border-width-1x) solid var(--sbb-color-cloud)',
borderRadius: 'var(--sbb-border-radius-4x)',
zIndex: '100',
};

const codeStyle: Args = {
padding: 'var(--sbb-spacing-fixed-1x) var(--sbb-spacing-fixed-2x)',
borderRadius: 'var(--sbb-border-radius-4x)',
backgroundColor: 'var(--sbb-color-smoke-alpha-20)',
};

const textBlock = (): TemplateResult => html`
<div style=${styleMap(textBlockStyle)}>
This text block has a <code style=${styleMap(codeStyle)}>z-index</code> greater than the form
field, but it must always be covered by the autocomplete overlay.
const Template = (args: Args): TemplateResult => html`
<div>
<sbb-form-field
label="Label"
?negative=${args.negative}
?borderless=${args.borderless}
?floating-label=${args.floatingLabel}
>
<input
placeholder="Placeholder"
data-testid="autocomplete-input"
?disabled=${args.disabled}
?readonly=${args.readonly}
/>
<sbb-autocomplete-grid
?disable-animation=${args.disableAnimation}
?preserve-icon-space=${args.preserveIconSpace}
>
${createRows1(args.optionIconName, args.buttonIconName, args.disableOption)}
${createRows2(args.buttonIconName, args.disableOption)}
</sbb-autocomplete-grid>
</sbb-form-field>
${textBlock()}
<div
id="container"
style=${styleMap({
color: args.negative ? 'var(--sbb-color-white)' : 'var(--sbb-color-black)',
paddingBlock: '1rem',
})}
></div>
</div>
`;

const Template = (args: Args): TemplateResult => html`
const OptionGroupTemplate = (args: Args): TemplateResult => html`
<div>
<sbb-form-field
label="Label"
Expand All @@ -263,8 +362,13 @@ const Template = (args: Args): TemplateResult => html`
?disable-animation=${args.disableAnimation}
?preserve-icon-space=${args.preserveIconSpace}
>
${createRows1(args.optionIconName, args.buttonIconName, args.disableOption)}
${createRows2(args.buttonIconName, args.disableOptio1n)}
<sbb-autocomplete-grid-optgroup label="Group 1" ?disabled=${args.disableGroup}>
${createRows1(args.optionIconName, args.buttonIconName, args.disableOption)}
${createRows2(args.buttonIconName, args.disableOptio1n)}
</sbb-autocomplete-grid-optgroup>
<sbb-autocomplete-grid-optgroup label="Group 2">
${createRows1(args.optionIconName, args.buttonIconName, args.disableOption)}
</sbb-autocomplete-grid-optgroup>
</sbb-autocomplete-grid>
</sbb-form-field>
${textBlock()}
Expand All @@ -278,10 +382,119 @@ const Template = (args: Args): TemplateResult => html`
</div>
`;

export const Default: StoryObj = {
export const Basic: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs },
play: isChromatic() ? playStory : undefined,
};

export const Negative: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, negative: true },
play: isChromatic() ? playStory : undefined,
};

export const Disabled: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, disabled: true },
};

export const Readonly: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, readonly: true },
};

export const NoIcon: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, optionIconName: undefined },
play: isChromatic() ? playStory : undefined,
};

export const NoIconNoIconSpace: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, optionIconName: undefined, preserveIconSpace: false },
play: isChromatic() ? playStory : undefined,
};

export const Borderless: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, borderless: true },
play: isChromatic() ? playStory : undefined,
};

export const BorderlessNegative: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, borderless: true, negative: true },
play: isChromatic() ? playStory : undefined,
};

export const BasicOpenAbove: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs },
decorators: [aboveDecorator],
play: isChromatic() ? playStory : undefined,
};

export const BorderlessOpenAbove: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, borderless: true },
decorators: [aboveDecorator],
play: isChromatic() ? playStory : undefined,
};

export const DisableOption: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, disableOption: true },
play: isChromatic() ? playStory : undefined,
};

export const NegativeDisableOption: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs, negative: true, disableOption: true },
play: isChromatic() ? playStory : undefined,
};

export const WithOptionGroup: StoryObj = {
render: OptionGroupTemplate,
argTypes: withGroupsArgTypes,
args: { ...withGroupsDefaultArgs },
play: isChromatic() ? playStory : undefined,
};

export const WithOptionGroupNegative: StoryObj = {
render: OptionGroupTemplate,
argTypes: withGroupsArgTypes,
args: { ...withGroupsDefaultArgs, negative: true },
play: isChromatic() ? playStory : undefined,
};

export const WithOptionGroupDisabled: StoryObj = {
render: OptionGroupTemplate,
argTypes: withGroupsArgTypes,
args: { ...withGroupsDefaultArgs, disableGroup: true },
play: isChromatic() ? playStory : undefined,
};

export const Scroll: StoryObj = {
render: Template,
argTypes: defaultArgTypes,
args: { ...defaultArgs },
decorators: [scrollDecorator],
parameters: {
chromatic: { disableSnapshot: true },
},
};

const meta: Meta = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
:host {
@include sbb.options-panel-overlay-variables;

--sbb-options-pointer-events: all;
--sbb-options-panel-internal-z-index: var(--sbb-autocomplete-z-index, var(--sbb-overlay-z-index));
}

Expand All @@ -21,6 +22,7 @@
:host(:not([data-state])),
:host([data-state='closed']) {
--sbb-options-panel-visibility: hidden;
--sbb-options-pointer-events: none;
}

:host([data-state='opening']) {
Expand Down Expand Up @@ -129,6 +131,8 @@
@include sbb.scrollbar-rules;
@include sbb.optionsOverlay;

pointer-events: var(--sbb-options-pointer-events);

@include sbb.if-forced-colors {
border: var(--sbb-border-width-1x) solid CanvasText;
border-top: none;
Expand Down

0 comments on commit 3e5be5a

Please sign in to comment.