diff --git a/2nd-gen/packages/core/components/accordion/Accordion.base.ts b/2nd-gen/packages/core/components/accordion/Accordion.base.ts new file mode 100644 index 00000000000..883ad39f1ea --- /dev/null +++ b/2nd-gen/packages/core/components/accordion/Accordion.base.ts @@ -0,0 +1,208 @@ +/** + * Copyright 2026 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. + */ + +import { PropertyValues } from 'lit'; +import { property } from 'lit/decorators.js'; + +import { SpectrumElement } from '@spectrum-web-components/core/element/index.js'; +import { SizedMixin } from '@spectrum-web-components/core/mixins/index.js'; + +import { + ACCORDION_VALID_SIZES, + type AccordionDensity, + type AccordionHeadingLevel, + type AccordionSize, + SWC_ACCORDION_ITEM_TOGGLE_EVENT, +} from './Accordion.types.js'; +import { AccordionItemBase } from './AccordionItem.base.js'; + +/** + * Base class for accordion components. Manages item propagation, heading + * level, density, and the exclusive-open constraint. + * + * @attribute {boolean} allowMultiple - Reflected as `allow-multiple`. When set, + * multiple items may be open at the same time. + * @attribute {number} level - Heading level (2–6) applied to every item header. + * Values outside that range are clamped. + * @attribute {AccordionSize} size - Size applied to all items. + * @attribute {AccordionDensity} density - Vertical spacing between items. + * @attribute {boolean} quiet - Renders the accordion in its quiet visual variant. + * @attribute {boolean} disabled - Disables all items in the accordion. + * + * @slot - One or more `swc-accordion-item` elements. + */ +export abstract class AccordionBase extends SizedMixin(SpectrumElement, { + validSizes: ACCORDION_VALID_SIZES, + defaultSize: 'm', +}) { + // ────────────────── + // PUBLIC API + // ────────────────── + + /** + * When set, multiple items may be open at the same time. By default only + * one item can be open. + */ + @property({ type: Boolean, reflect: true, attribute: 'allow-multiple' }) + public allowMultiple: boolean = false; + + /** + * Heading level applied to every item header (2–6). Defaults to 3. + * Values outside that range are clamped. + */ + @property({ type: Number, reflect: true }) + public level: AccordionHeadingLevel = 3; + + /** + * Size applied to all items. Defaults to `m`. + */ + declare public size: AccordionSize; + + /** + * Controls vertical spacing between items. + * + * @default regular + */ + @property({ type: String, reflect: true }) + public density: AccordionDensity = 'regular'; + + /** + * Renders the accordion in its quiet (no-border) visual variant. + */ + @property({ type: Boolean, reflect: true }) + public quiet: boolean = false; + + /** + * Disables all items in the accordion. Individual items may also be + * disabled independently. + */ + @property({ type: Boolean, reflect: true }) + public disabled: boolean = false; + + // ────────────────────── + // IMPLEMENTATION + // ────────────────────── + + private assignedItems(): AccordionItemBase[] { + const slot = this.renderRoot?.querySelector('slot'); + if (!slot) { + return []; + } + return slot + .assignedElements({ flatten: true }) + .filter((el): el is AccordionItemBase => el instanceof AccordionItemBase); + } + + private closeSiblingsOnOpen = (event: Event): void => { + if (this.disabled) { + event.preventDefault(); + return; + } + if (this.allowMultiple) { + return; + } + const toggling = event.target; + if (!(toggling instanceof AccordionItemBase)) { + return; + } + // Defer until after dispatch returns so that a canceled toggle (where the + // item reverts open back to false) does not incorrectly close siblings. + queueMicrotask(() => { + if (!toggling.open) { + return; + } + for (const item of this.assignedItems()) { + if (item !== toggling) { + item.open = false; + } + } + }); + }; + + protected syncAccordionItems(): void { + for (const item of this.assignedItems()) { + item.setManagedHeading(this.level); + item.size = this.size; + item.setManagedParentDisabled(this.disabled); + } + } + + private enforceExclusiveOpen(): void { + let foundOpen = false; + for (const item of this.assignedItems()) { + if (item.open) { + if (foundOpen) { + item.open = false; + } else { + foundOpen = true; + } + } + } + } + + public override connectedCallback(): void { + super.connectedCallback(); + this.addEventListener( + SWC_ACCORDION_ITEM_TOGGLE_EVENT, + this.closeSiblingsOnOpen + ); + } + + public override disconnectedCallback(): void { + super.disconnectedCallback(); + this.removeEventListener( + SWC_ACCORDION_ITEM_TOGGLE_EVENT, + this.closeSiblingsOnOpen + ); + } + + protected override update(changedProperties: PropertyValues): void { + if (changedProperties.has('level')) { + const clamped = Math.min( + 6, + Math.max(2, this.level) + ) as AccordionHeadingLevel; + if (this.level !== clamped) { + this.level = clamped; + } + } + if ( + changedProperties.has('level') || + changedProperties.has('size') || + changedProperties.has('disabled') + ) { + this.syncAccordionItems(); + } + // changedProperties.get() returns the previous value; this fires only when + // disabled transitions from true → false (re-enable). + if ( + changedProperties.has('disabled') && + changedProperties.get('disabled') === true && + !this.allowMultiple + ) { + this.enforceExclusiveOpen(); + } + super.update(changedProperties); + } + + protected override firstUpdated(changedProperties: PropertyValues): void { + super.firstUpdated(changedProperties); + if (window.__swc?.DEBUG && !this.hasAttribute('density')) { + window.__swc.warn( + this, + `<${this.localName}> should have an explicit "density" attribute set. Defaulting to "regular".`, + 'https://opensource.adobe.com/spectrum-web-components/components/accordion/', + { type: 'api', level: 'low' } + ); + } + } +} diff --git a/2nd-gen/packages/core/components/accordion/Accordion.types.ts b/2nd-gen/packages/core/components/accordion/Accordion.types.ts new file mode 100644 index 00000000000..fbf4da59f9b --- /dev/null +++ b/2nd-gen/packages/core/components/accordion/Accordion.types.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2026 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. + */ + +import type { ElementSize } from '@spectrum-web-components/core/mixins/index.js'; + +export const ACCORDION_VALID_SIZES = [ + 's', + 'm', + 'l', + 'xl', +] as const satisfies readonly ElementSize[]; +export type AccordionSize = (typeof ACCORDION_VALID_SIZES)[number]; + +export const ACCORDION_DENSITIES = ['compact', 'regular', 'spacious'] as const; +export type AccordionDensity = (typeof ACCORDION_DENSITIES)[number]; + +export const ACCORDION_HEADING_LEVELS = [2, 3, 4, 5, 6] as const; +export type AccordionHeadingLevel = (typeof ACCORDION_HEADING_LEVELS)[number]; + +export const SWC_ACCORDION_ITEM_TOGGLE_EVENT = 'swc-accordion-item-toggle'; +export const SWC_ACCORDION_ITEM_OPEN_EVENT = 'swc-open'; +export const SWC_ACCORDION_ITEM_CLOSE_EVENT = 'swc-close'; +export const SWC_ACCORDION_ITEM_AFTER_OPEN_EVENT = 'swc-after-open'; +export const SWC_ACCORDION_ITEM_AFTER_CLOSE_EVENT = 'swc-after-close'; diff --git a/2nd-gen/packages/core/components/accordion/AccordionItem.base.ts b/2nd-gen/packages/core/components/accordion/AccordionItem.base.ts new file mode 100644 index 00000000000..950f61cf9c2 --- /dev/null +++ b/2nd-gen/packages/core/components/accordion/AccordionItem.base.ts @@ -0,0 +1,183 @@ +/** + * Copyright 2026 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. + */ + +import { property, state } from 'lit/decorators.js'; + +import { SpectrumElement } from '@spectrum-web-components/core/element/index.js'; +import { ObserveSlotPresence } from '@spectrum-web-components/core/mixins/observe-slot-presence.js'; + +import { + type AccordionHeadingLevel, + type AccordionSize, + SWC_ACCORDION_ITEM_AFTER_CLOSE_EVENT, + SWC_ACCORDION_ITEM_AFTER_OPEN_EVENT, + SWC_ACCORDION_ITEM_CLOSE_EVENT, + SWC_ACCORDION_ITEM_OPEN_EVENT, + SWC_ACCORDION_ITEM_TOGGLE_EVENT, +} from './Accordion.types.js'; + +/** + * Base class for accordion item components. Manages open/disabled state, + * heading level (set by the parent accordion), and the toggle event. + * + * @attribute {boolean} open - Whether the accordion item panel is expanded. + * @attribute {boolean} disabled - Whether the accordion item is disabled. + * @attribute {AccordionSize} size - Size of the item. Inherited from the parent + * accordion when slotted; controls the chevron icon when used standalone. + * + * @slot label - The heading text for this accordion item. + * @slot actions - Optional actions rendered adjacent to the heading, outside + * the toggle button so they remain independently interactive. + * @slot - The panel content revealed when the item is open. + */ +export abstract class AccordionItemBase extends ObserveSlotPresence( + SpectrumElement, + '[slot="actions"]' +) { + // ────────────────── + // PUBLIC API + // ────────────────── + + /** + * Whether the accordion item panel is expanded. + */ + @property({ type: Boolean, reflect: true }) + public get open(): boolean { + return this._open; + } + + public set open(value: boolean) { + if (this.hasUpdated && !this.mayExpand() && value !== this._open) { + return; + } + if (value === this._open) { + return; + } + const oldValue = this._open; + this._open = value; + if (value) { + this.setAttribute('open', ''); + } else { + this.removeAttribute('open'); + } + this.requestUpdate('open', oldValue); + } + + /** + * Whether the accordion item is disabled. A disabled item keeps its header + * in the tab order but blocks toggling. + */ + @property({ type: Boolean, reflect: true }) + public disabled: boolean = false; + + /** + * The size of the item. Inherited from the parent accordion; controls which + * chevron icon is displayed. Has no effect when the item is used standalone. + */ + @property({ type: String, reflect: true }) + public size?: AccordionSize; + + private _open = false; + + // ────────────────────── + // INTERNAL STATE + // ────────────────────── + + /** + * @internal + * Heading level (2–6) propagated by the parent accordion. Defaults to 3 + * for standalone items. + */ + @state() + protected headingLevel: AccordionHeadingLevel = 3; + + /** + * @internal + * Set by the parent accordion when its own `disabled` is true. Causes the + * item to render as disabled (aria-disabled + inert panel) without clobbering + * the item's own `disabled` property, so the per-item state is preserved + * when the accordion is re-enabled. + */ + @state() + protected parentDisabled: boolean = false; + + // ────────────────────── + // IMPLEMENTATION + // ────────────────────── + + /** + * @internal + * Whether the item may change `open` (expand or collapse). When false, the + * `open` setter and `toggle()` leave state unchanged. + */ + protected mayExpand(): boolean { + return !this.disabled && !this.parentDisabled; + } + + /** + * @internal + * Toggles the item open state. Guards for disabled, flips `open`, dispatches + * the toggle event, and reverts if the event is canceled. On success, dispatches + * `swc-after-open` or `swc-after-close` after the next render cycle. + */ + protected toggle(): void { + if (!this.mayExpand()) { + return; + } + this.open = !this.open; + const toggleEvent = new Event(SWC_ACCORDION_ITEM_TOGGLE_EVENT, { + bubbles: true, + composed: true, + cancelable: true, + }); + if (!this.dispatchEvent(toggleEvent)) { + this.open = !this.open; + return; + } + const isOpen = this.open; + this.dispatchEvent( + new Event( + isOpen ? SWC_ACCORDION_ITEM_OPEN_EVENT : SWC_ACCORDION_ITEM_CLOSE_EVENT, + { + bubbles: true, + composed: true, + } + ) + ); + void this.updateComplete.then(() => { + this.dispatchEvent( + new Event( + isOpen + ? SWC_ACCORDION_ITEM_AFTER_OPEN_EVENT + : SWC_ACCORDION_ITEM_AFTER_CLOSE_EVENT, + { bubbles: true, composed: true } + ) + ); + }); + } + + /** + * @internal + * Synchronizes parent-managed heading level onto the item. + */ + public setManagedHeading(heading: AccordionHeadingLevel): void { + this.headingLevel = heading; + } + + /** + * @internal + * Synchronizes parent-managed disabled state onto the item. + */ + public setManagedParentDisabled(disabled: boolean): void { + this.parentDisabled = disabled; + } +} diff --git a/2nd-gen/packages/core/components/accordion/index.ts b/2nd-gen/packages/core/components/accordion/index.ts new file mode 100644 index 00000000000..058e18a5674 --- /dev/null +++ b/2nd-gen/packages/core/components/accordion/index.ts @@ -0,0 +1,15 @@ +/** + * Copyright 2026 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 * from './Accordion.base.js'; +export * from './AccordionItem.base.js'; +export * from './Accordion.types.js'; diff --git a/2nd-gen/packages/core/package.json b/2nd-gen/packages/core/package.json index 86b4009e996..b4626a67e89 100644 --- a/2nd-gen/packages/core/package.json +++ b/2nd-gen/packages/core/package.json @@ -19,6 +19,10 @@ "types": "./dist/components/alert-banner/index.d.ts", "import": "./dist/components/alert-banner/index.js" }, + "./components/accordion": { + "types": "./dist/components/accordion/index.d.ts", + "import": "./dist/components/accordion/index.js" + }, "./components/asset": { "types": "./dist/components/asset/index.d.ts", "import": "./dist/components/asset/index.js" @@ -148,6 +152,9 @@ "components/alert-banner": [ "dist/components/alert-banner/index.d.ts" ], + "components/accordion": [ + "dist/components/accordion/index.d.ts" + ], "components/asset": [ "dist/components/asset/index.d.ts" ], diff --git a/2nd-gen/packages/swc/.storybook/preview.ts b/2nd-gen/packages/swc/.storybook/preview.ts index 73e4673e0ab..68e75baf54d 100644 --- a/2nd-gen/packages/swc/.storybook/preview.ts +++ b/2nd-gen/packages/swc/.storybook/preview.ts @@ -324,11 +324,7 @@ const preview = { 'Components', [ 'Accordion', - [ - 'Accessibility migration analysis', - 'Migration plan', - 'Rendering and styling migration analysis', - ], + ['Accessibility migration analysis', 'Migration plan'], 'Action button', ['Rendering and styling migration analysis'], 'Action group', diff --git a/2nd-gen/packages/swc/components/accordion/Accordion.ts b/2nd-gen/packages/swc/components/accordion/Accordion.ts new file mode 100644 index 00000000000..92d112150e6 --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/Accordion.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2026 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. + */ + +import { CSSResultArray, html, TemplateResult } from 'lit'; + +import { AccordionBase } from '@spectrum-web-components/core/components/accordion'; + +import styles from './accordion.css'; + +/** + * An accordion component that groups expandable content sections. + * + * @element swc-accordion + * @since 2.0.0 + * + * @example + * + * + * Section heading + * Panel content goes here. + * + * + */ +export class Accordion extends AccordionBase { + public static override get styles(): CSSResultArray { + return [styles]; + } + + protected override render(): TemplateResult { + return html` +
+ +
+ `; + } +} diff --git a/2nd-gen/packages/swc/components/accordion/AccordionItem.ts b/2nd-gen/packages/swc/components/accordion/AccordionItem.ts new file mode 100644 index 00000000000..2979fe29ef6 --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/AccordionItem.ts @@ -0,0 +1,149 @@ +/** + * Copyright 2026 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. + */ + +import { CSSResultArray, html, TemplateResult } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { when } from 'lit/directives/when.js'; +import { html as staticHtml, unsafeStatic } from 'lit/static-html.js'; + +import { AccordionItemBase } from '@spectrum-web-components/core/components/accordion'; + +import '../icon/swc-icon.js'; + +import { Chevron75Icon } from '../icon/elements/Chevron75Icon.js'; +import { Chevron100Icon } from '../icon/elements/Chevron100Icon.js'; +import { Chevron200Icon } from '../icon/elements/Chevron200Icon.js'; +import { Chevron300Icon } from '../icon/elements/Chevron300Icon.js'; + +import styles from './accordion.css'; + +/** + * An accordion item component that wraps a single expandable content section. + * + * @element swc-accordion-item + * @since 2.0.0 + * + * @fires swc-accordion-item-toggle - Dispatched when the item open state is + * toggled. Cancelable; `preventDefault()` reverts the change. + * @fires swc-open - Dispatched when the item begins opening. + * @fires swc-close - Dispatched when the item begins closing. + * @fires swc-after-open - Dispatched after the item has fully opened. + * @fires swc-after-close - Dispatched after the item has fully closed. + * + * @example + * + * Section heading + * Panel content goes here. + * + */ +export class AccordionItem extends AccordionItemBase { + // ────────────────────────────── + // STYLING + // ────────────────────────────── + + public static override get styles(): CSSResultArray { + return [styles]; + } + + // ────────────────────────────── + // DELEGATION + // ────────────────────────────── + + public override focus(options?: FocusOptions): void { + this.shadowRoot?.getElementById('header')?.focus(options); + } + + public override click(): void { + this.shadowRoot?.getElementById('header')?.click(); + } + + // ────────────────────────────── + // RENDERING + // ────────────────────────────── + + private chevronForSize(): TemplateResult { + switch (this.size) { + case 's': + return Chevron75Icon(); + case 'l': + return Chevron200Icon(); + case 'xl': + return Chevron300Icon(); + case 'm': + default: + return Chevron100Icon(); + } + } + + private handleHeaderKeydown(event: Event): void { + if ((event as KeyboardEvent).key === ' ') { + // Space requires preventDefault to suppress page scroll; toggle is then + // called explicitly. Enter is not handled here — the browser's native + // button activation fires a click event, which calls toggle() via the + // @click binding. + event.preventDefault(); + this.toggle(); + } + } + + private renderHeadingWrapper(content: TemplateResult): TemplateResult { + const tag = unsafeStatic(`h${this.headingLevel}`); + return staticHtml`<${tag} class="swc-AccordionItem-heading">${content}`; + } + + protected override render(): TemplateResult { + const button = html` + + `; + return html` +
+ ${this.renderHeadingWrapper(button)} + ${when( + this.slotContentIsPresent, + () => html` +
+ +
+ ` + )} +
+ +
+
+ `; + } +} diff --git a/2nd-gen/packages/swc/components/accordion/accordion.css b/2nd-gen/packages/swc/components/accordion/accordion.css new file mode 100644 index 00000000000..40f33594a28 --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/accordion.css @@ -0,0 +1,13 @@ +/** + * Copyright 2026 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. + */ + +/* S2 token imports and selector definitions land here in Phase 4. */ diff --git a/2nd-gen/packages/swc/components/accordion/index.ts b/2nd-gen/packages/swc/components/accordion/index.ts new file mode 100644 index 00000000000..f8f7131062c --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/index.ts @@ -0,0 +1,14 @@ +/** + * Copyright 2026 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 * from './Accordion.js'; +export * from './AccordionItem.js'; diff --git a/2nd-gen/packages/swc/components/accordion/stories/accordion.stories.ts b/2nd-gen/packages/swc/components/accordion/stories/accordion.stories.ts new file mode 100644 index 00000000000..4284e11925e --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/stories/accordion.stories.ts @@ -0,0 +1,127 @@ +/** + * Copyright 2026 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. + */ + +import { html } from 'lit'; +import type { Meta, StoryObj as Story } from '@storybook/web-components'; +import { getStorybookHelpers } from '@wc-toolkit/storybook-helpers'; + +import '@adobe/spectrum-wc/components/accordion/swc-accordion.js'; +import '@adobe/spectrum-wc/components/accordion/swc-accordion-item.js'; + +import { + ACCORDION_DENSITIES, + ACCORDION_VALID_SIZES, + SWC_ACCORDION_ITEM_TOGGLE_EVENT, +} from '../../../../core/components/accordion/Accordion.types.js'; + +// ──────────────── +// METADATA +// ──────────────── + +const { args, argTypes, template } = getStorybookHelpers('swc-accordion'); + +argTypes.density = { + ...argTypes.density, + control: { type: 'select' }, + options: [...ACCORDION_DENSITIES], + table: { + ...argTypes.density?.table, + category: 'attributes', + defaultValue: { summary: 'regular' }, + }, +}; + +argTypes.size = { + ...argTypes.size, + control: { type: 'select' }, + options: ['', ...ACCORDION_VALID_SIZES], + table: { + ...argTypes.size?.table, + category: 'attributes', + }, +}; + +argTypes.level = { + ...argTypes.level, + control: { type: 'number', min: 2, max: 6 }, + table: { + ...argTypes.level?.table, + category: 'attributes', + defaultValue: { summary: '3' }, + }, +}; + +const defaultItems = html` + + Alchemy + Alchemy is an ancient branch of natural philosophy, a philosophical and + protoscientific tradition that was historically practiced in China, India, + the Muslim world, and Europe. + + + Astrology + Astrology is a range of divinatory practices, recognized as pseudoscientific + since the 18th century, that propose that information about human affairs + and terrestrial events may be discerned by studying the apparent positions + of celestial objects. + + + Natural magic + Natural magic in the context of early modern Europe was a branch of + philosophy that treated occult forces as resulting from natural causes, not + from divine or demonic intervention. + +`; + +/** + * An accordion groups related content sections, each behind a header that can + * be expanded or collapsed. Only one section is open at a time by default; + * set `allow-multiple` to let any number of sections be open simultaneously. + */ +const meta: Meta = { + title: 'Accordion', + component: 'swc-accordion', + args, + argTypes, + render: (args) => template(args, defaultItems), + parameters: { + actions: { handles: [SWC_ACCORDION_ITEM_TOGGLE_EVENT] }, + docs: { + subtitle: 'Groups related content sections behind expandable headers.', + }, + }, + tags: ['migrated'], +}; + +export default meta; + +// ──────────────────── +// AUTODOCS STORY +// ──────────────────── + +export const Playground: Story = { + args: { + density: 'regular', + }, + tags: ['autodocs', 'dev'], +}; + +// ────────────────────────── +// OVERVIEW STORY +// ────────────────────────── + +export const Overview: Story = { + args: { + density: 'regular', + }, + tags: ['overview'], +}; diff --git a/2nd-gen/packages/swc/components/accordion/swc-accordion-item.ts b/2nd-gen/packages/swc/components/accordion/swc-accordion-item.ts new file mode 100644 index 00000000000..cd9853027e7 --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/swc-accordion-item.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2026 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. + */ + +import { defineElement } from '@spectrum-web-components/core/element/index.js'; + +import { AccordionItem } from './AccordionItem.js'; + +declare global { + interface HTMLElementTagNameMap { + 'swc-accordion-item': AccordionItem; + } +} + +defineElement('swc-accordion-item', AccordionItem); diff --git a/2nd-gen/packages/swc/components/accordion/swc-accordion.ts b/2nd-gen/packages/swc/components/accordion/swc-accordion.ts new file mode 100644 index 00000000000..d51f7f1b1e5 --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/swc-accordion.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2026 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. + */ + +import { defineElement } from '@spectrum-web-components/core/element/index.js'; + +import { Accordion } from './Accordion.js'; + +declare global { + interface HTMLElementTagNameMap { + 'swc-accordion': Accordion; + } +} + +defineElement('swc-accordion', Accordion); diff --git a/2nd-gen/packages/swc/components/accordion/test/.gitkeep b/2nd-gen/packages/swc/components/accordion/test/.gitkeep new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/2nd-gen/packages/swc/components/accordion/test/.gitkeep @@ -0,0 +1 @@ + diff --git a/2nd-gen/packages/swc/components/icon/elements/Chevron300Icon.ts b/2nd-gen/packages/swc/components/icon/elements/Chevron300Icon.ts new file mode 100644 index 00000000000..72956bf4b1d --- /dev/null +++ b/2nd-gen/packages/swc/components/icon/elements/Chevron300Icon.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2026 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. + */ +import { html, TemplateResult } from 'lit'; + +export const Chevron300Icon = (): TemplateResult => { + return html` + + + + `; +}; diff --git a/2nd-gen/packages/swc/components/icon/elements/index.ts b/2nd-gen/packages/swc/components/icon/elements/index.ts index b30f66ddd2c..8d6cf638b2f 100644 --- a/2nd-gen/packages/swc/components/icon/elements/index.ts +++ b/2nd-gen/packages/swc/components/icon/elements/index.ts @@ -20,6 +20,7 @@ export * from './Chevron50Icon.js'; export * from './Chevron75Icon.js'; export * from './Chevron100Icon.js'; export * from './Chevron200Icon.js'; +export * from './Chevron300Icon.js'; export * from './CornerTriangle300Icon.js'; export * from './Cross75Icon.js'; export * from './Cross100Icon.js';