Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Accordion): use CSS logical properties instead of physical values #1130

Merged
merged 7 commits into from
Jul 18, 2024
16 changes: 16 additions & 0 deletions packages/beeq/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ export namespace Components {
* If true accordion is expanded
*/
"expanded": boolean;
/**
* Animation is set through JS when the browser does not support CSS calc-size() If true, the accordion animation, will be disabled. No animation will be applied.
*/
"noAnimation": boolean;
/**
* If true accordion expand icon is rotate 180deg when expanded
*/
Expand All @@ -99,6 +103,10 @@ export namespace Components {
* If true multiple accordions can be expanded at the same time
*/
"multiple": boolean;
/**
* Animation is set through JS when the browser does not support CSS calc-size() If true, the accordion animation, will be disabled. No animation will be applied.
*/
"noAnimation": boolean;
/**
* The size of accordion to be applied to all accordions
*/
Expand Down Expand Up @@ -2270,6 +2278,10 @@ declare namespace LocalJSX {
* If true accordion is expanded
*/
"expanded"?: boolean;
/**
* Animation is set through JS when the browser does not support CSS calc-size() If true, the accordion animation, will be disabled. No animation will be applied.
*/
"noAnimation"?: boolean;
/**
* Handler to be called after the accordion is closed
*/
Expand Down Expand Up @@ -2317,6 +2329,10 @@ declare namespace LocalJSX {
* If true multiple accordions can be expanded at the same time
*/
"multiple"?: boolean;
/**
* Animation is set through JS when the browser does not support CSS calc-size() If true, the accordion animation, will be disabled. No animation will be applied.
*/
"noAnimation"?: boolean;
/**
* The size of accordion to be applied to all accordions
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Args, Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit-html';
import { ifDefined } from 'lit-html/directives/if-defined.js';

import mdx from '../../accordion/_storybook/bq-accordion.mdx';
import { ACCORDION_APPEARANCE, ACCORDION_SIZE } from '../../accordion/bq-accordion.types';
Expand All @@ -15,13 +16,15 @@ const meta: Meta = {
argTypes: {
appearance: { control: 'select', options: [...ACCORDION_APPEARANCE] },
'expand-all': { control: 'boolean' },
'no-animation': { control: 'boolean' },
multiple: { control: 'boolean' },
size: { control: 'select', options: [...ACCORDION_SIZE] },
text: { control: 'text', table: { disable: true } },
},
args: {
appearance: 'filled',
'expand-all': false,
'no-animation': false,
multiple: false,
size: 'medium',
text: 'Header',
Expand All @@ -34,10 +37,11 @@ type Story = StoryObj;
export const Group: Story = {
render: (args: Args) => html`
<bq-accordion-group
appearance=${ifDefined(args.appearance)}
?expand-all=${args['expand-all']}
?no-animation=${args['no-animation']}
?multiple=${args.multiple}
size=${args.size}
appearance=${args.appearance}
size=${ifDefined(args.size)}
>
<bq-accordion size=${args.size}>
<span slot="header">${args.text}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,30 @@ export class BqAccordionGroup {
// Public Property API
// ========================

/** The appearance style of accordion to be applied to all accordions */
@Prop({ reflect: true, mutable: true }) appearance: TAccordionAppearance = 'filled';

/** If true all accordions are expanded */
@Prop({ reflect: true }) expandAll: boolean;

/**
* Animation is set through JS when the browser does not support CSS calc-size()
* If true, the accordion animation, will be disabled. No animation will be applied.
*/
@Prop({ reflect: true }) noAnimation: boolean = false;

/** If true multiple accordions can be expanded at the same time */
@Prop({ reflect: true }) multiple: boolean = false;

/** The appearance style of accordion to be applied to all accordions */
@Prop({ reflect: true, mutable: true }) appearance: TAccordionAppearance = 'filled';

/** The size of accordion to be applied to all accordions */
@Prop({ reflect: true, mutable: true }) size: TAccordionSize = 'medium';

// Prop lifecycle events
// =======================

@Watch('expandAll')
@Watch('appearance')
@Watch('expandAll')
@Watch('noAnimation')
@Watch('size')
checkPropValues() {
this.bqAccordionElements.forEach((bqAccordionElement) => {
Expand All @@ -52,6 +59,7 @@ export class BqAccordionGroup {
bqAccordionElement.expanded = this.expandAll;
}
bqAccordionElement.appearance = this.appearance;
bqAccordionElement.noAnimation = this.noAnimation;
bqAccordionElement.size = this.size;
});
}
Expand Down
13 changes: 7 additions & 6 deletions packages/beeq/src/components/accordion-group/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@

## Properties

| Property | Attribute | Description | Type | Default |
| ------------ | ------------ | ----------------------------------------------------------------- | --------------------- | ----------- |
| `appearance` | `appearance` | The appearance style of accordion to be applied to all accordions | `"filled" \| "ghost"` | `'filled'` |
| `expandAll` | `expand-all` | If true all accordions are expanded | `boolean` | `undefined` |
| `multiple` | `multiple` | If true multiple accordions can be expanded at the same time | `boolean` | `false` |
| `size` | `size` | The size of accordion to be applied to all accordions | `"medium" \| "small"` | `'medium'` |
| Property | Attribute | Description | Type | Default |
| ------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----------- |
| `appearance` | `appearance` | The appearance style of accordion to be applied to all accordions | `"filled" \| "ghost"` | `'filled'` |
| `expandAll` | `expand-all` | If true all accordions are expanded | `boolean` | `undefined` |
| `multiple` | `multiple` | If true multiple accordions can be expanded at the same time | `boolean` | `false` |
| `noAnimation` | `no-animation` | Animation is set through JS when the browser does not support CSS calc-size() If true, the accordion animation, will be disabled. No animation will be applied. | `boolean` | `false` |
| `size` | `size` | The size of accordion to be applied to all accordions | `"medium" \| "small"` | `'medium'` |


## Shadow Parts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ const meta: Meta = {
appearance: { control: 'select', options: [...ACCORDION_APPEARANCE] },
disabled: { control: 'boolean' },
expanded: { control: 'boolean' },
'no-animation': { control: 'boolean' },
rotate: { control: 'boolean' },
size: { control: 'select', options: [...ACCORDION_SIZE] },
// Event handlers
bqBlur: { action: 'bqBlur' },
bqFocus: { action: 'bqFocus' },
bqClick: { action: 'bqClick' },
bqOpen: { action: 'bqOpen' },
bqAfterOpen: { action: 'bqAfterOpen' },
bqClose: { action: 'bqClose' },
Expand All @@ -33,6 +35,7 @@ const meta: Meta = {
appearance: 'filled',
disabled: false,
expanded: false,
'no-animation': false,
rotate: false,
size: 'medium',
// Not part of the component
Expand All @@ -48,10 +51,12 @@ const Template = (args: Args) => html`
appearance=${args.appearance}
?disabled=${args.disabled}
?expanded=${args.expanded}
?no-animation=${args['no-animation']}
?rotate=${args.rotate}
size=${args.size}
@bqBlur=${args.bqBlur}
@bqFocus=${args.bqFocus}
@bqClick=${args.bqClick}
@bqOpen=${args.bqOpen}
@bqAfterOpen=${args.bqAfterOpen}
@bqClose=${args.bqClose}
Expand Down
50 changes: 42 additions & 8 deletions packages/beeq/src/components/accordion/bq-accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export class BqAccordion {
/** If true accordion is expanded */
@Prop({ reflect: true, mutable: true }) expanded: boolean = false;

/**
* Animation is set through JS when the browser does not support CSS calc-size()
* If true, the accordion animation, will be disabled. No animation will be applied.
*/
@Prop({ reflect: true }) noAnimation: boolean = false;

/** If true accordion expand icon is rotate 180deg when expanded */
@Prop({ reflect: true }) rotate: boolean = false;

Expand All @@ -67,15 +73,20 @@ export class BqAccordion {

@Watch('expanded')
handleExpandedChange() {
if (!this.accordion) return;

const event = this.expanded ? this.bqOpen.emit(this.el) : this.bqClose.emit(this.el);
if (event.defaultPrevented) {
this.expanded = !this.expanded;
return;
}

this.expanded ? this.accordion.open() : this.accordion.close();
this.expanded ? this.accordion?.open() : this.accordion?.close();
if (!this.isCssCalcSizeSupported) return;

// NOTE: This is a workaround to trigger the transitionEnd event
// when the open/close animation is handled via CSS instead of JS
setTimeout(() => {
this.el.dispatchEvent(new CustomEvent('accordionTransitionEnd', { bubbles: false, composed: true }));
}, 200);
}

@Watch('disabled')
Expand All @@ -85,6 +96,17 @@ export class BqAccordion {
this.expanded = false;
}

@Watch('noAnimation')
handleJsAnimation() {
if (this.isCssCalcSizeSupported) return;

console.warn(
`[bq-accordion] calc-size() is not supported and animation will be set through JS
For vertical layout, consider using the 'noAnimation' prop ('no-animation' attribute) to disable it`,
);
this.accordion = !this.noAnimation ? new Accordion(this.detailsElem) : null;
}

// Events section
// Requires JSDocs for public API documentation
// ==============================================
Expand Down Expand Up @@ -119,7 +141,7 @@ export class BqAccordion {
}

componentDidLoad() {
this.accordion = new Accordion(this.detailsElem);
this.handleJsAnimation();
this.handleExpandedChange();
}

Expand All @@ -128,6 +150,7 @@ export class BqAccordion {

@Listen('accordionTransitionEnd')
onAccordionTransitionEnd(event: CustomEvent) {
event.stopPropagation();
if (event.target !== this.el) return;

this.expanded ? this.bqAfterOpen.emit(this.el) : this.bqAfterClose.emit(this.el);
Expand All @@ -144,13 +167,14 @@ export class BqAccordion {
// Internal business logic.
// These methods cannot be called from the host element.
// =======================================================

private handleClick = (event: MouseEvent) => {
event.preventDefault();

if (this.disabled) return;

this.expanded = !this.expanded;
this.bqClick.emit(this.el);
this.expanded = !this.expanded;
};

private handleFocus = () => {
Expand All @@ -175,24 +199,34 @@ export class BqAccordion {
return this.expanded && !this.disabled;
}

private get isCssCalcSizeSupported() {
return window.CSS?.supports('(block-size: calc-size(auto))');
}

// render() function
// Always the last one in the class.
// ===================================

render() {
return (
<details
class={{ [`bq-accordion overflow-hidden ${this.size} ${this.appearance}`]: true, disabled: this.disabled }}
class={{
[`bq-accordion overflow-hidden ${this.size} ${this.appearance}`]: true,
'no-animation': this.noAnimation,
disabled: this.disabled,
}}
ref={(detailsElem: HTMLDetailsElement) => (this.detailsElem = detailsElem)}
open={this.open}
part="base"
>
<summary
class="bq-accordion__header"
onClick={this.handleClick}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
aria-expanded={this.open}
aria-expanded={this.expanded}
aria-disabled={this.disabled}
aria-controls="bq-accordion__body"
tabindex={this.disabled ? -1 : 0}
part="header"
>
Expand Down Expand Up @@ -232,7 +266,7 @@ export class BqAccordion {
</slot>
</div>
</summary>
<div class="bq-accordion__body overflow-hidden" part="panel">
Cata1989 marked this conversation as resolved.
Show resolved Hide resolved
<div id="bq-accordion__body" class="bq-accordion__body overflow-hidden" part="panel">
<slot />
</div>
</details>
Expand Down
2 changes: 1 addition & 1 deletion packages/beeq/src/components/accordion/helper/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class Accordion {
private isClosing: boolean;
private isExpanding: boolean;
private animationOptions = {
duration: 300,
duration: 200,
easing: 'ease-in-out',
};

Expand Down
15 changes: 8 additions & 7 deletions packages/beeq/src/components/accordion/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

## Properties

| Property | Attribute | Description | Type | Default |
| ------------ | ------------ | ------------------------------------------------------------ | --------------------- | ---------- |
| `appearance` | `appearance` | The appearance style of accordion | `"filled" \| "ghost"` | `'filled'` |
| `disabled` | `disabled` | If true accordion is disabled | `boolean` | `false` |
| `expanded` | `expanded` | If true accordion is expanded | `boolean` | `false` |
| `rotate` | `rotate` | If true accordion expand icon is rotate 180deg when expanded | `boolean` | `false` |
| `size` | `size` | The size of accordion | `"medium" \| "small"` | `'medium'` |
| Property | Attribute | Description | Type | Default |
| ------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ---------- |
| `appearance` | `appearance` | The appearance style of accordion | `"filled" \| "ghost"` | `'filled'` |
| `disabled` | `disabled` | If true accordion is disabled | `boolean` | `false` |
| `expanded` | `expanded` | If true accordion is expanded | `boolean` | `false` |
| `noAnimation` | `no-animation` | Animation is set through JS when the browser does not support CSS calc-size() If true, the accordion animation, will be disabled. No animation will be applied. | `boolean` | `false` |
| `rotate` | `rotate` | If true accordion expand icon is rotate 180deg when expanded | `boolean` | `false` |
| `size` | `size` | The size of accordion | `"medium" \| "small"` | `'medium'` |


## Events
Expand Down
Loading