Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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';

// ──────────────────
// SHARED
// ──────────────────

export const ACTION_BUTTON_VALID_SIZES = [
'xs',
's',
'm',
'l',
'xl',
] as const satisfies readonly ElementSize[];

export const ACTION_BUTTON_STATIC_COLORS = ['white', 'black'] as const;

// ──────────────────
// TYPES
// ──────────────────

export type ActionButtonSize = (typeof ACTION_BUTTON_VALID_SIZES)[number];
export type ActionButtonStaticColor =
(typeof ACTION_BUTTON_STATIC_COLORS)[number];
12 changes: 12 additions & 0 deletions 2nd-gen/packages/core/components/action-button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* 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 './ActionButton.types.js';
7 changes: 7 additions & 0 deletions 2nd-gen/packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
},
"type": "module",
"exports": {
"./components/action-button": {
"types": "./dist/components/action-button/index.d.ts",
"import": "./dist/components/action-button/index.js"
},
"./components/alert-banner": {
"types": "./dist/components/alert-banner/index.d.ts",
"import": "./dist/components/alert-banner/index.js"
Expand Down Expand Up @@ -165,6 +169,9 @@
},
"typesVersions": {
"*": {
"components/action-button": [
"dist/components/action-button/index.d.ts"
],
"components/alert-banner": [
"dist/components/alert-banner/index.d.ts"
],
Expand Down
141 changes: 141 additions & 0 deletions 2nd-gen/packages/swc/components/action-button/ActionButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* 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, PropertyValues, TemplateResult } from 'lit';
import { property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { ifDefined } from 'lit/directives/if-defined.js';

import {
ACTION_BUTTON_VALID_SIZES,
type ActionButtonSize,
type ActionButtonStaticColor,
} from '@spectrum-web-components/core/components/action-button';
import { ButtonBase } from '@spectrum-web-components/core/components/button';

import styles from './action-button.css';

/**
* A compact action button for toolbars, action groups, and icon-first chrome.
*
* @element swc-action-button
* @since 0.0.1
*
* @slot - Visible button label.
* @slot icon - Optional leading icon displayed before the label.
*
* @example
* <swc-action-button>Edit</swc-action-button>
*
* @example
* <swc-action-button quiet>
* <sp-icon-edit slot="icon"></sp-icon-edit>
* Edit
* </swc-action-button>
*/
export class ActionButton extends ButtonBase {
// ──────────────────────
// API OVERRIDES
// ──────────────────────

/** @internal */
static override readonly VALID_SIZES: readonly ActionButtonSize[] =
ACTION_BUTTON_VALID_SIZES;

/**
* Size of the button. Supports the full `xs`–`xl` range; `xs` is an
* action-button-specific addition not available on `swc-button`.
*/
@property({ type: String })
public override get size(): ActionButtonSize {
return this._size ?? 'm';
}

public override set size(value: ActionButtonSize) {
const normalized = (
value ? (value as string).toLocaleLowerCase() : value
) as ActionButtonSize;
const validSize: ActionButtonSize = ACTION_BUTTON_VALID_SIZES.includes(
normalized
)
? normalized
: 'm';
const oldSize = this._size ?? 'm';
if (oldSize === validSize) {
return;
}
this._size = validSize;
this.setAttribute('size', validSize);
this.requestUpdate('size', oldSize);
}

private _size: ActionButtonSize | null = null;

// ───────────────────
// API ADDITIONS
// ───────────────────

/**
* Applies the quiet (low-emphasis) visual treatment.
*/
@property({ type: Boolean, reflect: true })
public quiet: boolean = false;

/**
* Static color treatment for display over colored or image backgrounds.
*/
@property({ type: String, reflect: true, attribute: 'static-color' })
public staticColor?: ActionButtonStaticColor;

// ──────────────────────────────
// RENDERING & STYLING
// ──────────────────────────────

public static override get styles(): CSSResultArray {
return [styles];
}

protected override render(): TemplateResult {
return html`
<button
class=${classMap({
'swc-ActionButton': true,
'swc-ActionButton--hasIcon': this.hasIcon,
'swc-ActionButton--iconOnly': this.hasIcon && !this.hasLabel,
'swc-ActionButton--pendingActive': this.pendingActive,
})}
type="button"
@click=${this.handleClick}
?disabled=${this.disabled}
aria-disabled=${ifDefined(
this.pending && !this.disabled ? 'true' : undefined
)}
aria-label=${ifDefined(
this.pending ? this.getPendingAccessibleName() : this.accessibleLabel
)}
>
<slot name="icon"></slot>
<span class="swc-ActionButton-label">
<slot></slot>
</span>
</button>
`;
}

protected override update(changes: PropertyValues): void {
super.update(changes);
// Counteracts SizedMixin's auto-reflect of size="m" when no size was explicitly set.
if (this._size === null) {
this.removeAttribute('size');
}
}
}
17 changes: 17 additions & 0 deletions 2nd-gen/packages/swc/components/action-button/action-button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* 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.
*/

.swc-ActionButton {
display: inline-flex;
align-items: center;
justify-content: center;
}
12 changes: 12 additions & 0 deletions 2nd-gen/packages/swc/components/action-button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* 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 './ActionButton.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* 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 { Meta, StoryObj as Story } from '@storybook/web-components';
import { getStorybookHelpers } from '@wc-toolkit/storybook-helpers';

import '@adobe/spectrum-wc/components/action-button/swc-action-button.js';

// ────────────────
// METADATA
// ────────────────

const { args, argTypes, template } = getStorybookHelpers('swc-action-button');

/**
* A compact action button for toolbars, action groups, and icon-first chrome.
*/
const meta: Meta = {
title: 'Action Button',
component: 'swc-action-button',
args,
argTypes,
render: (args) => template(args),
parameters: {
docs: {
subtitle: 'Compact button for toolbars and action groups',
},
},
tags: ['migrated'],
};

export default meta;

// ────────────────────
// AUTODOCS STORY
// ────────────────────

export const Playground: Story = {
args: {
'default-slot': 'Edit',
},
tags: ['autodocs', 'dev'],
};

// ──────────────────────────
// OVERVIEW STORY
// ──────────────────────────

export const Overview: Story = {
args: {
'default-slot': 'Edit',
},
tags: ['overview'],
};
Original file line number Diff line number Diff line change
@@ -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 { defineElement } from '@spectrum-web-components/core/element/index.js';

import { ActionButton } from './ActionButton.js';

declare global {
interface HTMLElementTagNameMap {
'swc-action-button': ActionButton;
}
}

defineElement('swc-action-button', ActionButton);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* 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.
*/

/**
* Accessibility tests for ActionButton component (2nd generation).
*
* ARIA snapshot tests validate the accessibility tree structure.
* aXe WCAG compliance and color contrast validation are run via
* test-storybook (see .storybook/test-runner.ts). Both are included
* in the `test:a11y` command.
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* 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 { Meta, StoryObj as Story } from '@storybook/web-components';

import meta, { Overview } from '../stories/action-button.stories.js';

export default {
...meta,
title: 'Action Button/Tests',
parameters: {
...meta.parameters,
docs: { disable: true, page: null },
},
tags: ['!autodocs', 'dev'],
} as Meta;

// Placeholder: play function with component-specific assertions is added in Phase 6.
export const OverviewTest: Story = {
...Overview,
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
| ------------------- | ------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Accordion | ✓ | | | | | | |
| Action Bar | | | | | | | |
| Action Button | ✓ | | | | | | |
| Action Button | ✓ | | ✓ | | | | |
| Action Group | ✓ | | | | | | |
| Action Menu | | | | | | | |
| Alert Banner | ✓ | ✓ | | | | | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [Accordion migration roadmap](accordion/rendering-and-styling-migration-analysis.md)
- Action Button
- [Action button accessibility migration analysis](action-button/accessibility-migration-analysis.md)
- [Action button migration plan](action-button/migration-plan.md)
- [Action button migration roadmap](action-button/rendering-and-styling-migration-analysis.md)
- Action Group
- [Action group migration roadmap](action-group/rendering-and-styling-migration-analysis.md)
Expand Down
Loading
Loading