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
107 changes: 107 additions & 0 deletions 2nd-gen/packages/core/components/close-button/CloseButton.base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* 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 { ButtonBase } from '@spectrum-web-components/core/components/button';

import {
CLOSE_BUTTON_VALID_SIZES,
type CloseButtonSize,
type CloseButtonStaticColor,
type CloseButtonVariant,
} from './CloseButton.types.js';

/**
* Abstract base for dismiss close-button semantics shared by rendering layers.
* Extends {@link ButtonBase} with close-button sizing and static-color API.
*/
export abstract class CloseButtonBase extends ButtonBase {
/** @internal */
static override readonly VALID_SIZES: readonly CloseButtonSize[] =
CLOSE_BUTTON_VALID_SIZES;

private _closeButtonSize: CloseButtonSize | null = null;

/**
* Size of the close button. Defaults to medium when omitted; the host does
* not reflect `size` until authors set it explicitly (1st-gen parity).
*/
@property({ type: String })
public override get size(): CloseButtonSize {
return this._closeButtonSize ?? 'm';
}

public override set size(value: CloseButtonSize) {
const normalized = (
value ? (value as string).toLocaleLowerCase() : value
) as CloseButtonSize;
const validSize: CloseButtonSize = CLOSE_BUTTON_VALID_SIZES.includes(
normalized
)
? normalized
: 'm';
const oldSize = this._closeButtonSize ?? 'm';
if (oldSize === validSize) {
return;
}
this._closeButtonSize = validSize;
if (value) {
this.setAttribute('size', validSize);
} else {
this.removeAttribute('size');
}
this.requestUpdate('size', oldSize);
}

/**
* @deprecated Use `static-color` instead. Deprecated alias mapping is
* completed in the API migration phase.
*/
@property({ reflect: true })
public variant: CloseButtonVariant = '';

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

/**
* Close buttons always render a cross icon; treat as icon-present for
* shared {@link ButtonBase} accessibility checks.
*
* @internal
*/
protected override get hasIcon(): boolean {
return true;
}

protected override update(changedProperties: PropertyValues): void {
super.update(changedProperties);
if (this._closeButtonSize === null) {
this.removeAttribute('size');
}
}

protected override updated(changedProperties: PropertyValues): void {
if (
changedProperties.has('variant') &&
(this.variant === 'white' || this.variant === 'black') &&
!this.staticColor
) {
this.staticColor = this.variant;
}
super.updated(changedProperties);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* 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 CLOSE_BUTTON_VALID_SIZES = [
's',
'm',
'l',
'xl',
] as const satisfies readonly ElementSize[];

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

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

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

export type CloseButtonSize = (typeof CLOSE_BUTTON_VALID_SIZES)[number];
export type CloseButtonStaticColor =
(typeof CLOSE_BUTTON_STATIC_COLORS)[number];
export type CloseButtonVariant = (typeof CLOSE_BUTTON_VARIANTS)[number];
13 changes: 13 additions & 0 deletions 2nd-gen/packages/core/components/close-button/index.ts
Original file line number Diff line number Diff line change
@@ -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.
*/
export * from './CloseButton.base.js';
export * from './CloseButton.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 @@ -43,6 +43,10 @@
"types": "./dist/components/button/index.d.ts",
"import": "./dist/components/button/index.js"
},
"./components/close-button": {
"types": "./dist/components/close-button/index.d.ts",
"import": "./dist/components/close-button/index.js"
},
"./components/divider": {
"types": "./dist/components/divider/index.d.ts",
"import": "./dist/components/divider/index.js"
Expand Down Expand Up @@ -186,6 +190,9 @@
"components/button": [
"dist/components/button/index.d.ts"
],
"components/close-button": [
"dist/components/close-button/index.d.ts"
],
"components/divider": [
"dist/components/divider/index.d.ts"
],
Expand Down
93 changes: 93 additions & 0 deletions 2nd-gen/packages/swc/components/close-button/CloseButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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 { classMap } from 'lit/directives/class-map.js';
import { ifDefined } from 'lit/directives/if-defined.js';

import {
CloseButtonBase,
type CloseButtonSize,
} from '@spectrum-web-components/core/components/close-button';

import {
Cross200Icon,
Cross300Icon,
Cross400Icon,
Cross500Icon,
} from '../icon/elements/index.js';

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

const crossIconBySize: Record<CloseButtonSize, () => TemplateResult> = {
s: Cross200Icon,
m: Cross300Icon,
l: Cross400Icon,
xl: Cross500Icon,
};

/**
* A compact dismiss control for dialogs, banners, toasts, and similar chrome.
*
* @element swc-close-button
* @since 0.0.1
*
* @slot - Accessible text label rendered visually hidden next to the cross icon.
*
* @example
* <swc-close-button accessible-label="Close"></swc-close-button>
*
* @example
* <swc-close-button>Close</swc-close-button>
*/
export class CloseButton extends CloseButtonBase {
// ──────────────────────────────
// RENDERING & STYLING
// ──────────────────────────────

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

protected override render(): TemplateResult {
const resolvedName = this.getResolvedAccessibleName();

return html`
<button
class=${classMap({
'swc-CloseButton': true,
'swc-CloseButton--staticWhite': this.staticColor === 'white',
'swc-CloseButton--staticBlack': this.staticColor === 'black',
'swc-CloseButton--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()
: (resolvedName ?? undefined)
)}
>
<span class="swc-CloseButton-icon" aria-hidden="true">
${crossIconBySize[this.size]()}
</span>
<span class="swc-CloseButton-label">
<slot></slot>
</span>
</button>
`;
}
}
50 changes: 50 additions & 0 deletions 2nd-gen/packages/swc/components/close-button/close-button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* 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.
*/

:host {
display: inline-flex;
}

.swc-CloseButton {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
background: transparent;
border: none;
cursor: pointer;
}

.swc-CloseButton:disabled {
cursor: default;
}

.swc-CloseButton-icon {
display: block;
flex-shrink: 0;
}

.swc-CloseButton-icon svg {
display: block;
}

.swc-CloseButton-label {
position: absolute;
inline-size: 1px;
block-size: 1px;
padding: 0;
margin: -1px;
white-space: nowrap;
border: 0;
overflow: hidden;
clip-path: inset(50%);
}
12 changes: 12 additions & 0 deletions 2nd-gen/packages/swc/components/close-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 './CloseButton.js';
Loading
Loading