From dce3f504d9158611414d389884c8142af1f8d504 Mon Sep 17 00:00:00 2001 From: yinon Date: Sun, 27 Dec 2020 21:36:50 +0200 Subject: [PATCH] feat(list): list expansion panel (#518) * feat(list): list expansion panel expansion panel to support expand & collapse list items * consumer vs component implementation * encapsulated list expansion panel * a better story * initial passing test * dep-check fix * extract expansion panel base class * fix correct deps * functional story * higher coverage * 90%+ coverage * vwc-icon reference * style update * removed list items typography handling * expand micro interaction * list readme update Co-authored-by: Yuri Guller --- __snapshots__/list expansion panel.md | 14 ++ components/expansion-panel/package.json | 32 ++++ .../src/vwc-expansion-panel-base.ts | 57 ++++++ components/expansion-panel/tsconfig.json | 12 ++ components/list/package.json | 2 + components/list/readme.md | 178 +++++++++++++----- components/list/src/vwc-check-list-item.scss | 10 +- .../list/src/vwc-list-expansion-panel.scss | 41 ++++ .../list/src/vwc-list-expansion-panel.ts | 88 +++++++++ components/list/src/vwc-list-item.scss | 16 +- components/list/src/vwc-list.scss | 12 +- .../stories/list-expansion-panel.stories.js | 60 ++++++ components/list/test/list-check-item.test.js | 45 ++--- .../test/list-item-expansion-panel.test.js | 106 +++++++++++ components/list/test/list-item.test.js | 23 +-- components/list/test/list-radio-item.test.js | 45 ++--- components/list/tsconfig.json | 13 +- tsconfig.json | 1 + 18 files changed, 632 insertions(+), 123 deletions(-) create mode 100644 __snapshots__/list expansion panel.md create mode 100644 components/expansion-panel/package.json create mode 100644 components/expansion-panel/src/vwc-expansion-panel-base.ts create mode 100644 components/expansion-panel/tsconfig.json create mode 100644 components/list/src/vwc-list-expansion-panel.scss create mode 100644 components/list/src/vwc-list-expansion-panel.ts create mode 100644 components/list/stories/list-expansion-panel.stories.js create mode 100644 components/list/test/list-item-expansion-panel.test.js diff --git a/__snapshots__/list expansion panel.md b/__snapshots__/list expansion panel.md new file mode 100644 index 000000000..aac4f6e20 --- /dev/null +++ b/__snapshots__/list expansion panel.md @@ -0,0 +1,14 @@ +# `list expansion panel` + +#### `should have the expected custom element's internal contents` + +```html + + +
+ + +
+ +``` + diff --git a/components/expansion-panel/package.json b/components/expansion-panel/package.json new file mode 100644 index 000000000..ea0002782 --- /dev/null +++ b/components/expansion-panel/package.json @@ -0,0 +1,32 @@ +{ + "name": "@vonage/vwc-expansion-panel", + "version": "0.17.2-pre.1", + "description": "> TODO: description", + "author": "yinonov ", + "homepage": "https://github.com/Vonage/vivid/tree/master/components/expansion-panel#readme", + "license": "ISC", + "main": "vwc-expansion-panel.js", + "module": "vwc-expansion-panel.js", + "files": [ + "src", + "*.js", + "*.ts", + "*.map" + ], + "repository": { + "type": "git", + "url": "https://github.com/vonage/vivid.git", + "directory": "components/expansion-panel" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/Vonage/vivid/issues" + }, + "dependencies": { + "@material/mwc-base": "^0.20.0", + "lit-element": "^2.4.0", + "tslib": "^2.0.3" + } +} diff --git a/components/expansion-panel/src/vwc-expansion-panel-base.ts b/components/expansion-panel/src/vwc-expansion-panel-base.ts new file mode 100644 index 000000000..c4008e34c --- /dev/null +++ b/components/expansion-panel/src/vwc-expansion-panel-base.ts @@ -0,0 +1,57 @@ +import { LitElement, property } from 'lit-element'; +import { observer } from '@material/mwc-base/observer'; + +export abstract class VWCExpansionPanelBase extends LitElement { + @property({ type: Boolean, reflect: true }) + @observer(function ( + this: VWCExpansionPanelBase, + isOpen: boolean, + wasOpen: boolean + ) { + if (isOpen) { + this.show(); + // wasOpen helps with first render (when it is `undefined`) perf + } else if (wasOpen !== undefined) { + this.close(); + } + + this.openChanged(isOpen); + }) + open = false; + + /** + * Invoked when the element open state is updated. + * + * Expressions inside this method will trigger upon open state change + * + * @param _isOpen Boolean of open state + */ protected openChanged( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _isOpen: boolean + // eslint-disable-next-line @typescript-eslint/no-empty-function + ): void {} + + close(): void { + this.open = false; + this.notifyClose(); + } + + show(): void { + this.open = true; + this.notifyOpen(); + } + + notifyClose(): void { + const init: CustomEventInit = { bubbles: true, composed: true }; + const ev = new CustomEvent('closed', init); + this.open = false; + this.dispatchEvent(ev); + } + + notifyOpen(): void { + const init: CustomEventInit = { bubbles: true, composed: true }; + const ev = new CustomEvent('opened', init); + this.open = true; + this.dispatchEvent(ev); + } +} diff --git a/components/expansion-panel/tsconfig.json b/components/expansion-panel/tsconfig.json new file mode 100644 index 000000000..2a0bc443d --- /dev/null +++ b/components/expansion-panel/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true, + "rootDir": "src", + "outDir": ".", + "tsBuildInfoFile": ".tsbuildinfo" + }, + "include": ["src/*.ts"], + "exclude": ["src/test/*.ts"], + "references": [] +} diff --git a/components/list/package.json b/components/list/package.json index 0feb2fd90..6ded502e4 100644 --- a/components/list/package.json +++ b/components/list/package.json @@ -26,6 +26,8 @@ "dependencies": { "@material/mwc-list": "^0.20.0", "@vonage/vvd-core": "^0.17.2", + "@vonage/vwc-icon": "^0.17.2", + "@vonage/vwc-expansion-panel": "^0.17.2-pre.1", "@vonage/vvd-style-coupling": "^0.17.2", "lit-element": "^2.4.0", "tslib": "^2.0.3" diff --git a/components/list/readme.md b/components/list/readme.md index b49cc874f..4d2a7db4e 100644 --- a/components/list/readme.md +++ b/components/list/readme.md @@ -1,34 +1,81 @@ +This component is an extension of [](https://github.com/material-components/material-components-web-components/tree/master/packages/list) + +## Properties + +| Property | Modifiers | Type | +| ------------------ | --------- | ------------------------- | +| `activated` | | `boolean` | +| `disabled` | | `boolean` | +| `graphic` | | `GraphicType` | +| `group` | | `string \| null` | +| `hasMeta` | | `boolean` | +| `left` | | `boolean` | +| `multipleGraphics` | | `boolean` | +| `noninteractive` | | `boolean` | +| `ripple` | | `Promise` | +| `selected` | | `boolean` | +| `tabindex` | | `number` | +| `text` | readonly | `string` | +| `twoline` | | `boolean` | +| `value` | | `string` | + +## Events + +| Event | Type | +| -------------------- | ----------------------- | +| `list-item-rendered` | | +| `request-selected` | `RequestSelectedDetail` | + +# vwc-list-expansion-panel + +This component support expand-collapse list + +## Properties + +| Property | Type | +| -------------------- | ------------------------------------ | +| `headerListItemIcon` | `VWCIcon \| undefined` | +| `headerNodes` | `HTMLElement[] \| null \| undefined` | +| `open` | `boolean` | + +## Methods + +| Method | Type | Description | +| ------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `close` | `(): void` | | +| `notifyClose` | `(): void` | | +| `notifyOpen` | `(): void` | | +| `openChanged` | `(isOpen: boolean): void` | Invoked when the element open state is updated.

Expressions inside this method will trigger upon open state change

**\_isOpen**: Boolean of open state | +| `show` | `(): void` | | + # vwc-list-item This component is an extension of [](https://github.com/material-components/material-components-web-components/tree/master/packages/list) ## Properties -| Property | Modifiers | Type | -|---------------------------|-----------|-------------------------------------------| -| `activated` | | `boolean` | -| `disabled` | | `boolean` | -| `floatingLabelFoundation` | | `MDCFloatingLabelFoundation \| undefined` | -| `graphic` | | `GraphicType` | -| `group` | | `string \| null` | -| `hasMeta` | | `boolean` | -| `lineRippleFoundation` | | `MDCLineRippleFoundation \| undefined` | -| `multipleGraphics` | | `boolean` | -| `noninteractive` | | `boolean` | -| `ripple` | | `Promise` | -| `selected` | | `boolean` | -| `tabindex` | | `number` | -| `text` | readonly | `string` | -| `twoline` | | `boolean` | -| `value` | | `string` | +| Property | Modifiers | Type | +| ------------------ | --------- | ------------------------- | +| `activated` | | `boolean` | +| `disabled` | | `boolean` | +| `graphic` | | `GraphicType` | +| `group` | | `string \| null` | +| `hasMeta` | | `boolean` | +| `multipleGraphics` | | `boolean` | +| `noninteractive` | | `boolean` | +| `ripple` | | `Promise` | +| `selected` | | `boolean` | +| `tabindex` | | `number` | +| `text` | readonly | `string` | +| `twoline` | | `boolean` | +| `value` | | `string` | ## Events -| Event | Description | -|----------------------|-------------------------| +| Event | Type | +| -------------------- | ----------------------- | | `list-item-rendered` | | -| `request-selected` | {RequestSelectedDetail} | - +| `request-selected` | `RequestSelectedDetail` | # vwc-list @@ -36,39 +83,72 @@ This component is an extension of [](https://github.com/material-compo ## Properties -| Property | Modifiers | Type | -|---------------------------|-----------|------------------------------------------------| -| `activatable` | | `boolean` | -| `floatingLabelFoundation` | | `MDCFloatingLabelFoundation \| undefined` | -| `index` | readonly | `MWCListIndex` | -| `innerAriaLabel` | | `string \| null` | -| `innerRole` | | `string \| null` | -| `itemRoles` | | `string \| null` | -| `items` | readonly | `ListItemBase[]` | -| `layout` | | `(updateItems?: boolean \| undefined) => void` | -| `lineRippleFoundation` | | `MDCLineRippleFoundation \| undefined` | -| `multi` | | `boolean` | -| `noninteractive` | | `boolean` | -| `rootTabbable` | | `boolean` | -| `selected` | readonly | `ListItemBase \| ListItemBase[] \| null` | -| `wrapFocus` | | `boolean` | +| Property | Modifiers | Type | +| ----------------- | --------- | ----------------------------------------------------------- | +| `activatable` | | `boolean` | +| `debouncedLayout` | | `(updateItems?: boolean \| undefined) => void \| undefined` | +| `emptyMessage` | | `string \| undefined` | +| `index` | readonly | `MWCListIndex` | +| `innerAriaLabel` | | `string \| null` | +| `innerRole` | | `string \| null` | +| `itemRoles` | | `string \| null` | +| `items` | readonly | `ListItemBase[]` | +| `itemsReady` | | `Promise` | +| `layout` | | `object` | +| `multi` | | `boolean` | +| `noninteractive` | | `boolean` | +| `rootTabbable` | | `boolean` | +| `selected` | readonly | `ListItemBase \| ListItemBase[] \| null` | +| `wrapFocus` | | `boolean` | ## Methods -| Method | Type | -|-----------------------|--------------------------------------------------| -| `blur` | `(): void` | -| `focus` | `(): void` | -| `focusItemAtIndex` | `(index: number): void` | -| `getFocusedItemIndex` | `(): number` | -| `layout` | `(updateItems?: boolean \| undefined): void` | -| `select` | `(index: MWCListIndex): void` | +| Method | Type | +| --------------------- | ----------------------------------------------------- | +| `blur` | `(): void` | +| `click` | `(): void` | +| `focus` | `(): void` | +| `focusItemAtIndex` | `(index: number): void` | +| `getFocusedItemIndex` | `(): number` | +| `layout` | `(updateItems?: boolean \| undefined): void` | +| `renderPlaceholder` | `(): TemplateResult \| null` | +| `select` | `(index: MWCListIndex): void` | | `toggle` | `(index: number, force?: boolean \| undefined): void` | ## Events -| Event | Description | -|-----------------|------------------| -| `action` | {ActionDetail} | +| Event | Type | +| --------------- | ---------------- | +| `action` | `ActionDetail` | | `items-updated` | | -| `selected` | {SelectedDetail} | +| `selected` | `SelectedDetail` | + +# vwc-radio-list-item + +This component is an extension of [](https://github.com/material-components/material-components-web-components/tree/master/packages/list) + +## Properties + +| Property | Modifiers | Type | +| ------------------ | --------- | ------------------------- | +| `activated` | | `boolean` | +| `disabled` | | `boolean` | +| `graphic` | | `GraphicType` | +| `group` | | `string \| null` | +| `hasMeta` | | `boolean` | +| `left` | | `boolean` | +| `multipleGraphics` | | `boolean` | +| `noninteractive` | | `boolean` | +| `ripple` | | `Promise` | +| `selected` | | `boolean` | +| `tabindex` | | `number` | +| `text` | readonly | `string` | +| `twoline` | | `boolean` | +| `value` | | `string` | + +## Events + +| Event | Type | +| -------------------- | ----------------------- | +| `list-item-rendered` | | +| `request-selected` | `RequestSelectedDetail` | diff --git a/components/list/src/vwc-check-list-item.scss b/components/list/src/vwc-check-list-item.scss index 2185f19d7..8ba426d4f 100644 --- a/components/list/src/vwc-check-list-item.scss +++ b/components/list/src/vwc-check-list-item.scss @@ -1,11 +1,11 @@ -@use '@vonage/vvd-typography/scss/typography' as typography; +// @use '@vonage/vvd-typography/scss/typography' as typography; -:host{ - @include typography.typography-cat-shorthand('body-2'); -} +// :host{ +// @include typography.typography-cat-shorthand('body-2'); +// } :host(:not([left])) > .mdc-list-item__meta { // TODO: add list-coupling variables (like --mdc-list-item-meta-size) width: 22px; height: 22px; -} \ No newline at end of file +} diff --git a/components/list/src/vwc-list-expansion-panel.scss b/components/list/src/vwc-list-expansion-panel.scss new file mode 100644 index 000000000..7a40e4d31 --- /dev/null +++ b/components/list/src/vwc-list-expansion-panel.scss @@ -0,0 +1,41 @@ +@use '@vonage/vvd-design-tokens/build/scss/semantic-variables/scheme-variables'; + +$indent: 44px; + +.body { + margin-inline-start: $indent; + position: relative; + &::before { + content: ''; + block-size: 100%; + border-inline-start: 1px solid + var(#{scheme-variables.$vvd-color-contrast-faint}); + position: absolute; + left: $indent / -2; + } + :host(:not([open])) & { + display: none; + } + + @media (prefers-reduced-motion: no-preference) { + :host([open]) & { + animation: fade-in-left 0.4s cubic-bezier(0.39, 0.575, 0.565, 1) both; + } + } +} + +/** + * ---------------------------------------- + * animation fade-in-left + * ---------------------------------------- + */ +@keyframes fade-in-left { + 0% { + transform: translateX(-10px); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} diff --git a/components/list/src/vwc-list-expansion-panel.ts b/components/list/src/vwc-list-expansion-panel.ts new file mode 100644 index 000000000..8b06a82a7 --- /dev/null +++ b/components/list/src/vwc-list-expansion-panel.ts @@ -0,0 +1,88 @@ +import '@vonage/vwc-icon'; +import { + customElement, + html, + PropertyValues, + queryAssignedNodes, + TemplateResult, +} from 'lit-element'; +import { style } from './vwc-list-expansion-panel.css'; +import { ListItemBase } from '@material/mwc-list/mwc-list-item-base'; +import { VWCExpansionPanelBase } from '@vonage/vwc-expansion-panel/vwc-expansion-panel-base'; + +import { VWCIcon } from '@vonage/vwc-icon'; + +declare global { + interface HTMLElementTagNameMap { + 'vwc-list-expansion-panel': VWCListExpansionPanel; + } +} + +/** + * This component support expand-collapse list + */ +@customElement('vwc-list-expansion-panel') +export class VWCListExpansionPanel extends VWCExpansionPanelBase { + static styles = style; + + headerListItemIcon?: VWCIcon; + + // @property({ type: Boolean }) quick = false; // TODO add animation + + @queryAssignedNodes('header', true, 'vwc-list-item') + headerNodes?: HTMLElement[] | null; + + firstUpdated(changedProperties: PropertyValues): void { + super.firstUpdated(changedProperties); + const headerListItem = getHeaderListItem(this.headerNodes); + this.headerListItemIcon = getHeaderListItemIcon(headerListItem); + + headerListItem.addEventListener('request-selected', () => { + this.open = !this.open; + }); + } + + openChanged(isOpen: boolean): void { + super.openChanged(isOpen); + (this.headerListItemIcon as Element).setAttribute( + 'type', + isOpen ? 'up' : 'down' + ); + } + + render(): TemplateResult { + return html` +
`; + } +} + +/// UTIL FNS +function assert(condition: any, msg?: string): asserts condition { + if (!condition) { + throw new Error(msg); + } +} + +function getHeaderListItem(headerNodes: unknown) { + assert(Array.isArray(headerNodes), `Not an array: ${headerNodes}`); + assert(headerNodes.length > 0, `is empty: ${headerNodes}`); + const [headerListItem] = headerNodes; + assert( + headerListItem instanceof ListItemBase, + `Not a list item: ${headerListItem}` + ); + return headerListItem; +} +function mountIcon(headerListItem: ListItemBase) { + const icon = document.createElement('vwc-icon'); + icon.setAttribute('slot', 'meta'); + headerListItem.appendChild(icon); + headerListItem.setAttribute('hasMeta', ''); // side effect setting attribute to match icon usage + return icon; +} + +function getHeaderListItemIcon(headerListItem: ListItemBase) { + let icon = headerListItem.querySelector('vwc-icon[slot="meta"]'); + icon ||= mountIcon(headerListItem); + return icon as VWCIcon; +} diff --git a/components/list/src/vwc-list-item.scss b/components/list/src/vwc-list-item.scss index a328ad59c..69c82e197 100644 --- a/components/list/src/vwc-list-item.scss +++ b/components/list/src/vwc-list-item.scss @@ -1,5 +1,15 @@ -@use '@vonage/vvd-typography/scss/typography' as typography; +@use '@vonage/vvd-design-tokens/build/scss/semantic-variables/scheme-variables'; +// @use '@vonage/vvd-typography/scss/typography' as typography; :host { - @include typography.typography-cat-shorthand('body-2'); -} \ No newline at end of file + // @include typography.typography-cat-shorthand('body-2'); + // ! typography here is defined by its context + $gutter: 12px; + border-radius: 6px; + --mdc-list-side-padding: #{$gutter}; + --mdc-list-item-graphic-margin: #{$gutter}; + --mdc-list-item-graphic-size: 20px; + --mdc-theme-text-icon-on-background: var( + #{scheme-variables.$vvd-color-on-base} + ); +} diff --git a/components/list/src/vwc-list.scss b/components/list/src/vwc-list.scss index b980cafc6..e4df5ebe8 100644 --- a/components/list/src/vwc-list.scss +++ b/components/list/src/vwc-list.scss @@ -1,11 +1,15 @@ @use '@vonage/vvd-typography/scss/typography' as typography; -@use '@vonage/vvd-design-tokens/build/scss/semantic-variables/_scheme-variables' as scheme-variables; +@use '@vonage/vvd-design-tokens/build/scss/semantic-variables/scheme-variables'; :host { - @include typography.typography-cat-shorthand('body-1'); + @include typography.typography-cat-shorthand('body-2'); --mdc-list-item-meta-size: 16px; --mdc-ripple-color: var(#{scheme-variables.$vvd-color-on-base}); - --mdc-theme-text-hint-on-background: var(#{scheme-variables.$vvd-color-contrast-tinted}); - --mdc-theme-text-secondary-on-background: var(#{scheme-variables.$vvd-color-contrast-tinted}); + --mdc-theme-text-hint-on-background: var( + #{scheme-variables.$vvd-color-contrast-tinted} + ); + --mdc-theme-text-secondary-on-background: var( + #{scheme-variables.$vvd-color-contrast-tinted} + ); } diff --git a/components/list/stories/list-expansion-panel.stories.js b/components/list/stories/list-expansion-panel.stories.js new file mode 100644 index 000000000..088dbfaa5 --- /dev/null +++ b/components/list/stories/list-expansion-panel.stories.js @@ -0,0 +1,60 @@ +import '@vonage/vwc-list/vwc-list.js'; +import '@vonage/vwc-list/vwc-list-item.js'; +import '@vonage/vwc-list/vwc-list-expansion-panel.js'; +import '@vonage/vwc-icon'; +import { html } from 'lit-element'; +import { argTypes } from './arg-types-list-item.js'; +import { styleMap } from 'lit-html/directives/style-map'; + +export default { + title: 'Components/Atoms/List expansion panel', + component: 'vwc-list-expansion-panel', + argTypes +} + +const listStyles = { + 'inline-size': '240px', +}; + +const Template = () => html` + + + + Parent 1 + + + + + Parent 2 + + + Child 1 + + + Child 2 + + + + + + Parent 3 + + + Child 1 + + + + Child 2 + + + Grand child 1 + + + Grand child 2 + + + + +`; + +export const ExpansionPanel = Template.bind({}); diff --git a/components/list/test/list-check-item.test.js b/components/list/test/list-check-item.test.js index b5cba45cc..6c44d2f4a 100644 --- a/components/list/test/list-check-item.test.js +++ b/components/list/test/list-check-item.test.js @@ -42,29 +42,30 @@ describe('check list item', () => { }); }); - describe('typography', function () { - it(`should have set typography correct (normal)`, async function () { - const actualElements = addElements( - textToDomToParent(`<${VWC_CHECK_LIST_ITEM}>Item 1`) - ); - await waitNextTask(); - const listItem = actualElements[0]; - expect(listItem).to.exist; - assertComputedStyle(listItem, await getTypographyStyle('body-2')); - }); + // ! typography is defined by context + // describe('typography', function () { + // it(`should have set typography correct (normal)`, async function () { + // const actualElements = addElements( + // textToDomToParent(`<${VWC_CHECK_LIST_ITEM}>Item 1`) + // ); + // await waitNextTask(); + // const listItem = actualElements[0]; + // expect(listItem).to.exist; + // assertComputedStyle(listItem, await getTypographyStyle('body-2')); + // }); - it(`should have set typography correct (left, selected)`, async function () { - const actualElements = addElements( - textToDomToParent( - `<${VWC_CHECK_LIST_ITEM} left selected>Item 1` - ) - ); - await waitNextTask(); - const listItem = actualElements[0]; - expect(listItem).to.exist; - assertComputedStyle(listItem, await getTypographyStyle('body-2')); - }); - }); + // it(`should have set typography correct (left, selected)`, async function () { + // const actualElements = addElements( + // textToDomToParent( + // `<${VWC_CHECK_LIST_ITEM} left selected>Item 1` + // ) + // ); + // await waitNextTask(); + // const listItem = actualElements[0]; + // expect(listItem).to.exist; + // assertComputedStyle(listItem, await getTypographyStyle('body-2')); + // }); + // }); describe('general styling', async () => { it('should have correct dimensions', async () => { diff --git a/components/list/test/list-item-expansion-panel.test.js b/components/list/test/list-item-expansion-panel.test.js new file mode 100644 index 000000000..59bafa5ab --- /dev/null +++ b/components/list/test/list-item-expansion-panel.test.js @@ -0,0 +1,106 @@ +import '@vonage/vwc-list/vwc-list-expansion-panel'; +import { chaiDomDiff } from '@open-wc/semantic-dom-diff'; +import { + textToDomToParent, + waitNextTask, + isolatedElementsCreation, +} from '../../../test/test-helpers.js'; + +chai.use(chaiDomDiff); + +const VWC_LIST_EXPANSION_PANEL = 'vwc-list-expansion-panel'; + +describe('list expansion panel', () => { + let addElements = isolatedElementsCreation(); + + it('should be defined as a custom element', () => { + assert.exists( + customElements.get( + VWC_LIST_EXPANSION_PANEL, + `${VWC_LIST_EXPANSION_PANEL} element is not defined` + ) + ); + }); + + it(`should have the expected custom element's internal contents`, async () => { + addElements = textToDomToParent( + `<${VWC_LIST_EXPANSION_PANEL}>` + ); + const actualElement = addElements[0]; + await waitNextTask(); + expect(actualElement.shadowRoot.innerHTML).to.equalSnapshot(); + }); + + it('should have the expected slotted contents', async () => { + addElements = textToDomToParent( + `<${VWC_LIST_EXPANSION_PANEL}> + + + Header list item + + ` + ); + const actualElement = addElements[0]; + await waitNextTask(); + expect(actualElement.headerNodes.length).to.equal(1); + }); + + it('should be initially closed', async () => { + addElements = textToDomToParent( + `<${VWC_LIST_EXPANSION_PANEL}> + ` + ); + const actualElement = addElements[0]; + await waitNextTask(); + expect(actualElement.open).to.equal(false); + }); + + it('should be initially open', async () => { + addElements = textToDomToParent( + `<${VWC_LIST_EXPANSION_PANEL} open> + ` + ); + const actualElement = addElements[0]; + await waitNextTask(); + expect(actualElement.open).to.equal(true); + }); + + describe('styles', () => { + it(`should toggle content's "display" according to relevant "open" state`, async () => { + addElements = textToDomToParent( + `<${VWC_LIST_EXPANSION_PANEL}> + ` + ); + const actualElement = addElements[0]; + await waitNextTask(); + const { shadowRoot } = actualElement; + const body = shadowRoot.querySelector('.body'); + expect(getComputedStyle(body).display).to.equal('none'); + + actualElement.show(); + await waitNextTask(); + expect(getComputedStyle(body).display).to.equal('block'); + + actualElement.close(); + await waitNextTask(); + expect(getComputedStyle(body).display).to.equal('none'); + }); + + it('should apply correct styles', async () => { + addElements = textToDomToParent( + `<${VWC_LIST_EXPANSION_PANEL}> + ` + ); + const actualElement = addElements[0]; + await waitNextTask(); + const { shadowRoot } = actualElement; + const body = shadowRoot.querySelector('.body'); + expect(getComputedStyle(body)['margin-inline-start']).to.equal('44px'); + expect(getComputedStyle(body).position).to.equal('relative'); + expect(getComputedStyle(body, '::before').content).to.equal('""'); + expect(getComputedStyle(body, '::before')['block-size']).to.equal('100%'); + expect(getComputedStyle(body, '::before').position).to.equal('absolute'); + expect(getComputedStyle(body, '::before').left).to.equal('-22px'); + }); + }); +}); diff --git a/components/list/test/list-item.test.js b/components/list/test/list-item.test.js index fe5567aa3..c9225e943 100644 --- a/components/list/test/list-item.test.js +++ b/components/list/test/list-item.test.js @@ -38,17 +38,18 @@ describe('list item', () => { }); }); - describe('typography', () => { - it(`should have set typography correct`, async () => { - const actualElements = addElement( - textToDomToParent(`<${VWC_LIST_ITEM}>Item 1`) - ); - await waitNextTask(); - const listItem = actualElements[0]; - expect(listItem).to.exist; - assertComputedStyle(listItem, await getTypographyStyle('body-2')); - }); - }); + // ! typography is defined by context + // describe('typography', () => { + // it(`should have set typography correct`, async () => { + // const actualElements = addElement( + // textToDomToParent(`<${VWC_LIST_ITEM}>Item 1`) + // ); + // await waitNextTask(); + // const listItem = actualElements[0]; + // expect(listItem).to.exist; + // assertComputedStyle(listItem, await getTypographyStyle('body-2')); + // }); + // }); describe('general styling', async () => { it('should have correct dimensions', async () => { diff --git a/components/list/test/list-radio-item.test.js b/components/list/test/list-radio-item.test.js index b55c2846f..36d7ef706 100644 --- a/components/list/test/list-radio-item.test.js +++ b/components/list/test/list-radio-item.test.js @@ -42,29 +42,30 @@ describe('radio list item', () => { }); }); - describe('typography', function () { - it(`should have set typography correct (normal)`, async function () { - const actualElements = addElements( - textToDomToParent(`<${VWC_RADIO_LIST_ITEM}>Item 1`) - ); - await waitNextTask(); - const listItem = actualElements[0]; - expect(listItem).to.exist; - assertComputedStyle(listItem, await getTypographyStyle('body-2')); - }); + // ! typography is defined by context + // describe('typography', function () { + // it(`should have set typography correct (normal)`, async function () { + // const actualElements = addElements( + // textToDomToParent(`<${VWC_RADIO_LIST_ITEM}>Item 1`) + // ); + // await waitNextTask(); + // const listItem = actualElements[0]; + // expect(listItem).to.exist; + // assertComputedStyle(listItem, await getTypographyStyle('body-2')); + // }); - it(`should have typography correct (selected)`, async function () { - const actualElements = addElements( - textToDomToParent( - `<${VWC_RADIO_LIST_ITEM} selected>Item 1` - ) - ); - await waitNextTask(); - const listItem = actualElements[0]; - expect(listItem).to.exist; - assertComputedStyle(listItem, await getTypographyStyle('body-2')); - }); - }); + // it(`should have typography correct (selected)`, async function () { + // const actualElements = addElements( + // textToDomToParent( + // `<${VWC_RADIO_LIST_ITEM} selected>Item 1` + // ) + // ); + // await waitNextTask(); + // const listItem = actualElements[0]; + // expect(listItem).to.exist; + // assertComputedStyle(listItem, await getTypographyStyle('body-2')); + // }); + // }); describe('general styling', async () => { it('should have correct dimensions', async () => { diff --git a/components/list/tsconfig.json b/components/list/tsconfig.json index e59dd5e13..666f4a6c1 100644 --- a/components/list/tsconfig.json +++ b/components/list/tsconfig.json @@ -6,18 +6,17 @@ "outDir": ".", "tsBuildInfoFile": ".tsbuildinfo" }, - "include": [ - "src/*.ts" - ], - "exclude": [ - "src/test/*.ts" - ], + "include": ["src/*.ts"], + "exclude": ["src/test/*.ts"], "references": [ { "path": "../../common/core" }, { "path": "../../common/style-coupling" + }, + { + "path": "../../components/expansion-panel" } ] -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 8149d48ee..5a937db28 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -70,6 +70,7 @@ { "path": "components/theme-switch" }, { "path": "components/top-app-bar" }, { "path": "components/top-app-bar-fixed" }, + { "path": "components/expansion-panel" }, { "path": "components/inline" } ] }