diff --git a/.changeset/remove-basebutton.md b/.changeset/remove-basebutton.md new file mode 100644 index 0000000000..f674ea21a6 --- /dev/null +++ b/.changeset/remove-basebutton.md @@ -0,0 +1,4 @@ +--- +"@patternfly/elements": major +--- +``: Removed `BaseButton` class. Reimplement (recommended) or extend `PfButton`. diff --git a/elements/custom-elements-manifest.mjs b/elements/custom-elements-manifest.mjs new file mode 100644 index 0000000000..7b9ac24cda --- /dev/null +++ b/elements/custom-elements-manifest.mjs @@ -0,0 +1,14 @@ +import { pfeCustomElementsManifestConfig } from '@patternfly/pfe-tools/custom-elements-manifest/config.js'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; + +// HACK: cem runs from `./elements` in a monorepo +const rootDir = dirname(dirname(fileURLToPath(import.meta.url))); + +export default pfeCustomElementsManifestConfig({ + rootDir, + globs: [ + './*/pf-*.ts', + './*/Base*.ts' + ], +}); diff --git a/elements/package.json b/elements/package.json index b6bd9dfc61..4751e29eff 100644 --- a/elements/package.json +++ b/elements/package.json @@ -23,7 +23,6 @@ "./pf-background-image/pf-background-image.js": "./pf-background-image/pf-background-image.js", "./pf-badge/pf-badge.js": "./pf-badge/pf-badge.js", "./pf-banner/pf-banner.js": "./pf-banner/pf-banner.js", - "./pf-button/BaseButton.js": "./pf-button/BaseButton.js", "./pf-button/pf-button.js": "./pf-button/pf-button.js", "./pf-card/BaseCard.js": "./pf-card/BaseCard.js", "./pf-card/pf-card.js": "./pf-card/pf-card.js", diff --git a/elements/pf-button/BaseButton.css b/elements/pf-button/BaseButton.css deleted file mode 100644 index beecabeee6..0000000000 --- a/elements/pf-button/BaseButton.css +++ /dev/null @@ -1,68 +0,0 @@ -:host([hidden]) { - display: none !important; -} - -[hidden] { - display: none !important; -} - -.pf-button { - cursor: pointer; - position: relative; - font-family: inherit; -} - -.pf-button { - border-width: 0; - border-style: solid; -} - -.pf-button::after { - position: absolute; - inset: 0 0 0 0; - content: ""; - border-style: solid; -} - -:host(:is(:disabled, [aria-disabled=true])), -:host(:is(:disabled, [aria-disabled=true])) #container, -:host(:is(:disabled, [aria-disabled=true])) .pf-button, -:host(:is(:disabled, [aria-disabled=true])[danger]) .pf-button, -:host(:is(:disabled, [aria-disabled=true])[variant=link]) .pf-button { - pointer-events: none; - cursor: default; -} - -[part=icon] { - display: none; - pointer-events: none; -} - -.pf-button.hasIcon { - position: relative; - display: flex; - align-items: center; -} - -.pf-button.hasIcon [part=icon] { - display: inline-flex; - align-items: center; - position: absolute; - width: 16px; -} - -:host(:not([disabled])) .hasIcon [part=icon] { - cursor: pointer; -} - -[part=icon] ::slotted(*) { - width: 16px; - max-width: 16px; - height: 16px; - max-height: 16px; -} - -.hasIcon button { - position: absolute; - inset: 0; -} diff --git a/elements/pf-button/BaseButton.ts b/elements/pf-button/BaseButton.ts deleted file mode 100644 index 05907ec0d1..0000000000 --- a/elements/pf-button/BaseButton.ts +++ /dev/null @@ -1,106 +0,0 @@ -// we will shortly remove this file in #2631 -/* eslint-disable lit-a11y/no-aria-slot */ -import type { TemplateResult } from 'lit'; -import { LitElement, html } from 'lit'; -import { property } from 'lit/decorators/property.js'; -import { classMap } from 'lit/directives/class-map.js'; -import { ifDefined } from 'lit/directives/if-defined.js'; - -import { InternalsController } from '@patternfly/pfe-core/controllers/internals-controller.js'; - -import styles from './BaseButton.css'; - -/** - * Base button class - * @csspart button - Internal button element - * @csspart icon - Container for the icon slot - * @slot icon - * Contains the button's icon or state indicator, e.g. a spinner. - * @slot - * Must contain exactly one ` - `; - } - - async formDisabledCallback() { - await this.updateComplete; - this.requestUpdate(); - } - - #onClick() { - switch (this.type) { - case 'reset': - return this.#internals.reset(); - default: - return this.#internals.submit(); - } - } - - /** - * Fallback content for the icon slot. When the `icon` attribute is set, it - * should render an icon corresponding to the value. - * @example ```html - * - * ``` - */ - protected abstract renderDefaultIcon(): TemplateResult; -} diff --git a/elements/pf-button/pf-button.ts b/elements/pf-button/pf-button.ts index 7890013788..9c1958d788 100644 --- a/elements/pf-button/pf-button.ts +++ b/elements/pf-button/pf-button.ts @@ -143,26 +143,39 @@ export type ButtonVariant = ( export class PfButton extends LitElement { static readonly formAssociated = true; + static override readonly shadowRootOptions = { + ...LitElement.shadowRootOptions, + delegatesFocus: true, + }; + static readonly styles = [ tokensStyles, iconStyles, styles, ]; - /** Represents the state of a stateful button */ - @property({ type: Boolean, reflect: true }) loading = false; + @property({ reflect: true }) type?: 'button' | 'submit' | 'reset'; - /** Applies plain styles */ - @property({ type: Boolean, reflect: true }) plain = false; + /** Accessible name for the button, use when the button does not have slotted text */ + @property() label?: string; - /** Not as urgent as danger */ - @property({ type: Boolean, reflect: true }) warning = false; + /** Form value for the button */ + @property() value?: string; + + /** Form element name for the button */ + @property() name?: string; + + /** Disables the button */ + @property({ reflect: true, type: Boolean }) disabled = false; + + /** Represents the state of a stateful button */ + @property({ type: Boolean, reflect: true }) loading = false; /** Changes the size of the button. */ @property({ reflect: true }) size?: 'small' | 'large'; - /** Icon set for the `icon` property */ - @property({ attribute: 'icon-set' }) iconSet?: string; + /** Not as urgent as danger */ + @property({ type: Boolean, reflect: true }) warning = false; /** * Use danger buttons for actions a user can take that are potentially @@ -171,6 +184,9 @@ export class PfButton extends LitElement { */ @property({ type: Boolean, reflect: true }) danger = false; + /** Applies plain styles */ + @property({ type: Boolean, reflect: true }) plain = false; + /** * Changes the style of the button. * - Primary: Used for the most important call to action on a page. Try to @@ -187,21 +203,12 @@ export class PfButton extends LitElement { @property({ reflect: true, type: Boolean }) block = false; - /** Disables the button */ - @property({ reflect: true, type: Boolean }) disabled = false; - - @property({ reflect: true }) type?: 'button' | 'submit' | 'reset'; - - /** Accessible name for the button, use when the button does not have slotted text */ - @property() label?: string; - - @property() value?: string; - - @property() name?: string; - /** Shorthand for the `icon` slot, the value is icon name */ @property() icon?: string; + /** Icon set for the `icon` property */ + @property({ attribute: 'icon-set' }) iconSet?: string; + #internals = InternalsController.of(this, { role: 'button' }); #slots = new SlotController(this, 'icon', null); @@ -222,7 +229,12 @@ export class PfButton extends LitElement { this.#internals.ariaDisabled = String(!!this.disabled); } - protected override render() { + async formDisabledCallback() { + await this.updateComplete; + this.requestUpdate(); + } + + override render() { const hasIcon = !!this.icon || !!this.loading || this.#slots.hasSlotted('icon'); const { warning, variant, danger, loading, plain, inline, block, size } = this; const disabled = this.#disabled; @@ -244,7 +256,7 @@ export class PfButton extends LitElement { + ?hidden="${!this.icon || this.loading}"> @@ -254,11 +266,6 @@ export class PfButton extends LitElement { `; } - async formDisabledCallback() { - await this.updateComplete; - this.requestUpdate(); - } - #onClick() { if (!this.#disabled) { switch (this.type) {