Skip to content

Commit

Permalink
feat(components): split post-collapsible and post-accordion-item (#2379)
Browse files Browse the repository at this point in the history
Co-authored-by: Loïc Fürhoff <[email protected]>
Co-authored-by: Philipp Gfeller <[email protected]>
  • Loading branch information
3 people authored Jan 9, 2024
1 parent 56a62a5 commit 80594fd
Show file tree
Hide file tree
Showing 23 changed files with 392 additions and 301 deletions.
6 changes: 6 additions & 0 deletions .changeset/flat-parents-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@swisspost/design-system-components': patch
'@swisspost/design-system-styles': patch
---

Update the background color of accordion to be white on any background color other than white. The accordion background remains gray on white backgrounds.
5 changes: 5 additions & 0 deletions .changeset/perfect-lamps-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': patch
---

Added a payload to the `collapseChange` event of the `post-collapsible` component. This payload is a boolean: `true` if the collapsible was opened, `false` if it was closed.
6 changes: 6 additions & 0 deletions .changeset/swift-humans-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@swisspost/design-system-components': major
'@swisspost/design-system-documentation': patch
---

Restricted the post-collapsible component to the collapse behaviour only and created a post-accordion-item to use as children for the post-accordion component.
5 changes: 5 additions & 0 deletions .changeset/tasty-planes-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': patch
---

Updated the post-accordion background to be white on light and gray backgrounds.
22 changes: 11 additions & 11 deletions packages/components/src/animations/collapse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ const collapseDuration = 350;
const collapseEasing = 'ease';
const collapsedKeyframe: Keyframe = { height: '0', overflow: 'hidden' };

const animationOptions: KeyframeAnimationOptions = {
duration: collapseDuration,
easing: collapseEasing,
fill: 'forwards',
};

export const collapse = (el: HTMLElement): Animation => {
const { height } = window.getComputedStyle(el);
const expandedKeyframe: Keyframe = { height };
const expandedKeyframe: Keyframe = { height: window.getComputedStyle(el).height };

return el.animate(
[expandedKeyframe, collapsedKeyframe],
{ duration: collapseDuration, easing: collapseEasing, fill: 'forwards' },
);
return el.animate([expandedKeyframe, collapsedKeyframe], animationOptions);
};

export const expand = (el: HTMLElement): Animation => {
const expandedKeyframe: Keyframe = { height: `${el.scrollHeight}px` };
const expandedKeyframe: Keyframe = { height: `${el.scrollHeight}px`, offset: 1 };
const finalKeyframe: Keyframe = { height: 'auto' };

return el.animate(
[collapsedKeyframe, expandedKeyframe],
{ duration: collapseDuration, easing: collapseEasing, fill: 'forwards' },
);
return el.animate([collapsedKeyframe, expandedKeyframe, finalKeyframe], animationOptions);
};
61 changes: 43 additions & 18 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,45 @@
* It contains typing information for all components that exist in this project.
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { HeadingLevel } from "./components/post-accordion-item/heading-levels";
import { AlertType } from "./components/post-alert/alert-types";
import { HeadingLevel } from "./components/post-collapsible/heading-levels";
import { Placement } from "@floating-ui/dom";
export { HeadingLevel } from "./components/post-accordion-item/heading-levels";
export { AlertType } from "./components/post-alert/alert-types";
export { HeadingLevel } from "./components/post-collapsible/heading-levels";
export { Placement } from "@floating-ui/dom";
export namespace Components {
interface PostAccordion {
/**
* Collapses all `post-collapsible` children.
* Collapses all `post-accordion-item`.
*/
"collapseAll": () => Promise<void>;
/**
* Expands all `post-collapsible` children. If `close-others` is `true` and all items are closed, it will open the first one. Otherwise, it will keep the opened one.
* Expands all `post-accordion-item`. If `close-others` is `true` and all items are closed, it will open the first one. Otherwise, it will keep the opened one.
*/
"expandAll": () => Promise<void>;
/**
* If `true`, multiple `post-collapsible` can be open at the same time.
* If `true`, multiple `post-accordion-item` can be open at the same time.
*/
"multiple": boolean;
/**
* Toggles the `post-collapsible` children with the given id.
* Toggles the `post-accordion-item` with the given id.
*/
"toggle": (id: string) => Promise<void>;
}
interface PostAccordionItem {
/**
* If `true`, the element is initially collapsed otherwise it is displayed.
*/
"collapsed"?: boolean;
/**
* Defines the hierarchical level of the accordion item header within the headings structure.
*/
"headingLevel"?: HeadingLevel;
/**
* Triggers the collapse programmatically.
*/
"toggle": (force?: boolean) => Promise<boolean>;
}
interface PostAlert {
/**
* Triggers alert dismissal programmatically (same as clicking on the close button (×)).
Expand Down Expand Up @@ -61,10 +75,6 @@ export namespace Components {
* If `true`, the element is initially collapsed otherwise it is displayed.
*/
"collapsed"?: boolean;
/**
* Defines the hierarchical level of the collapsible header within the headings structure.
*/
"headingLevel"?: HeadingLevel;
/**
* Triggers the collapse programmatically. If there is a collapsing transition running already, it will be reversed.
*/
Expand Down Expand Up @@ -224,6 +234,12 @@ declare global {
prototype: HTMLPostAccordionElement;
new (): HTMLPostAccordionElement;
};
interface HTMLPostAccordionItemElement extends Components.PostAccordionItem, HTMLStencilElement {
}
var HTMLPostAccordionItemElement: {
prototype: HTMLPostAccordionItemElement;
new (): HTMLPostAccordionItemElement;
};
interface HTMLPostAlertElementEventMap {
"dismissed": void;
}
Expand All @@ -242,7 +258,7 @@ declare global {
new (): HTMLPostAlertElement;
};
interface HTMLPostCollapsibleElementEventMap {
"collapseChange": void;
"collapseChange": boolean;
}
interface HTMLPostCollapsibleElement extends Components.PostCollapsible, HTMLStencilElement {
addEventListener<K extends keyof HTMLPostCollapsibleElementEventMap>(type: K, listener: (this: HTMLPostCollapsibleElement, ev: PostCollapsibleCustomEvent<HTMLPostCollapsibleElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -327,6 +343,7 @@ declare global {
};
interface HTMLElementTagNameMap {
"post-accordion": HTMLPostAccordionElement;
"post-accordion-item": HTMLPostAccordionItemElement;
"post-alert": HTMLPostAlertElement;
"post-collapsible": HTMLPostCollapsibleElement;
"post-icon": HTMLPostIconElement;
Expand All @@ -341,10 +358,20 @@ declare global {
declare namespace LocalJSX {
interface PostAccordion {
/**
* If `true`, multiple `post-collapsible` can be open at the same time.
* If `true`, multiple `post-accordion-item` can be open at the same time.
*/
"multiple"?: boolean;
}
interface PostAccordionItem {
/**
* If `true`, the element is initially collapsed otherwise it is displayed.
*/
"collapsed"?: boolean;
/**
* Defines the hierarchical level of the accordion item header within the headings structure.
*/
"headingLevel"?: HeadingLevel;
}
interface PostAlert {
/**
* The label to use for the close button of a dismissible alert.
Expand Down Expand Up @@ -377,13 +404,9 @@ declare namespace LocalJSX {
*/
"collapsed"?: boolean;
/**
* Defines the hierarchical level of the collapsible header within the headings structure.
*/
"headingLevel"?: HeadingLevel;
/**
* An event emitted when the collapse element is shown or hidden, before the transition. It has no payload.
* An event emitted when the collapse element is shown or hidden, before the transition. The event payload is a boolean: `true` if the collapsible was opened, `false` if it was closed.
*/
"onCollapseChange"?: (event: PostCollapsibleCustomEvent<void>) => void;
"onCollapseChange"?: (event: PostCollapsibleCustomEvent<boolean>) => void;
}
/**
* @class PostIcon - representing a stencil component
Expand Down Expand Up @@ -476,6 +499,7 @@ declare namespace LocalJSX {
}
interface IntrinsicElements {
"post-accordion": PostAccordion;
"post-accordion-item": PostAccordionItem;
"post-alert": PostAlert;
"post-collapsible": PostCollapsible;
"post-icon": PostIcon;
Expand All @@ -492,6 +516,7 @@ declare module "@stencil/core" {
export namespace JSX {
interface IntrinsicElements {
"post-accordion": LocalJSX.PostAccordion & JSXBase.HTMLAttributes<HTMLPostAccordionElement>;
"post-accordion-item": LocalJSX.PostAccordionItem & JSXBase.HTMLAttributes<HTMLPostAccordionItemElement>;
"post-alert": LocalJSX.PostAlert & JSXBase.HTMLAttributes<HTMLPostAlertElement>;
"post-collapsible": LocalJSX.PostCollapsible & JSXBase.HTMLAttributes<HTMLPostCollapsibleElement>;
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@use '@swisspost/design-system-styles/components/accordion';
@use '@swisspost/design-system-styles/mixins/accordion' as accordion-mx;

:host {
display: block;
}

.accordion-button {
cursor: pointer;

> ::slotted(.text-truncate) {
display: block;
}
}

post-accordion-item::part(accordion-item) {
@include accordion-mx.background-color;

post-accordion-item + & {
border-block-start: 0!important;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Component, Element, h, Host, Listen, Method, Prop, State, Watch } from '@stencil/core';
import { version } from '../../../package.json';
import { checkEmptyOrOneOf } from '../../utils';
import { HEADING_LEVELS, HeadingLevel } from './heading-levels';

@Component({
tag: 'post-accordion-item',
styleUrl: 'post-accordion-item.scss',
shadow: true,
})
export class PostAccordionItem {
private collapsible: HTMLPostCollapsibleElement;

@Element() host: HTMLPostAccordionItemElement;

@State() id: string;
@State() isOpen: boolean;

/**
* If `true`, the element is initially collapsed otherwise it is displayed.
*/
@Prop() readonly collapsed?: boolean = false;

/**
* Defines the hierarchical level of the accordion item header within the headings structure.
*/
@Prop() readonly headingLevel?: HeadingLevel = 2;

@Watch('headingLevel')
validateHeadingLevel(newValue = this.headingLevel) {
checkEmptyOrOneOf(
newValue,
HEADING_LEVELS,
'The `headingLevel` property of the `post-accordion-item` must be a number between 1 and 6.',
);
}

connectedCallback() {
this.validateHeadingLevel();
}

componentWillLoad() {
this.isOpen = !this.collapsed;
this.id = this.host.id || `a${crypto.randomUUID()}`;
}

@Listen('collapseChange')
onCollapseChange(event: CustomEvent<boolean>): void {
this.isOpen = event.detail;
}

/**
* Triggers the collapse programmatically.
*/
@Method()
async toggle(force?: boolean): Promise<boolean> {
return this.collapsible.toggle(force);
}

render() {
const HeadingTag = `h${this.headingLevel ?? 2}`;

return (
<Host id={this.id} data-version={version}>
<div part="accordion-item" class="accordion-item">
<HeadingTag class="accordion-header" id={`${this.id}--header`}>
<button
aria-controls={`${this.id}--collapse`}
aria-expanded={`${this.isOpen}`}
class={`accordion-button${this.isOpen ? '' : ' collapsed'}`}
onClick={() => this.toggle()}
type="button"
>
<slot name="header" />
</button>
</HeadingTag>

<post-collapsible collapsed={this.collapsed} ref={el => (this.collapsible = el)}>
<div class="accordion-body">
<slot />
</div>
</post-collapsible>
</div>
</Host>
);
}
}
57 changes: 57 additions & 0 deletions packages/components/src/components/post-accordion-item/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# post-accordion-item



<!-- Auto Generated Below -->


## Properties

| Property | Attribute | Description | Type | Default |
| -------------- | --------------- | ------------------------------------------------------------------------------------------ | ---------------------------- | ------- |
| `collapsed` | `collapsed` | If `true`, the element is initially collapsed otherwise it is displayed. | `boolean` | `false` |
| `headingLevel` | `heading-level` | Defines the hierarchical level of the accordion item header within the headings structure. | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | `2` |


## Methods

### `toggle(force?: boolean) => Promise<boolean>`

Triggers the collapse programmatically.

#### Parameters

| Name | Type | Description |
| ------- | --------- | ----------- |
| `force` | `boolean` | |

#### Returns

Type: `Promise<boolean>`




## Shadow Parts

| Part | Description |
| ------------------ | ----------- |
| `"accordion-item"` | |


## Dependencies

### Depends on

- [post-collapsible](../post-collapsible)

### Graph
```mermaid
graph TD;
post-accordion-item --> post-collapsible
style post-accordion-item fill:#f9f,stroke:#333,stroke-width:4px
```

----------------------------------------------

*Built with [StencilJS](https://stenciljs.com/)*
Loading

0 comments on commit 80594fd

Please sign in to comment.