From 3baa4987bb684790087ff03e41d34f48c86edfce Mon Sep 17 00:00:00 2001
From: Benny Powers <web@bennypowers.com>
Date: Thu, 19 Oct 2023 11:37:11 +0300
Subject: [PATCH 1/7] fix(label)!: remove BaseLabel

Closes #2620
---
 .changeset/remove-base-label.md |  4 ++
 elements/package.json           |  1 -
 elements/pf-label/BaseLabel.css | 44 ----------------
 elements/pf-label/BaseLabel.ts  | 53 -------------------
 elements/pf-label/pf-label.css  | 41 +++++++++++++--
 elements/pf-label/pf-label.ts   | 93 +++++++++++++++++----------------
 6 files changed, 90 insertions(+), 146 deletions(-)
 create mode 100644 .changeset/remove-base-label.md
 delete mode 100644 elements/pf-label/BaseLabel.css
 delete mode 100644 elements/pf-label/BaseLabel.ts

diff --git a/.changeset/remove-base-label.md b/.changeset/remove-base-label.md
new file mode 100644
index 0000000000..bc79ff2729
--- /dev/null
+++ b/.changeset/remove-base-label.md
@@ -0,0 +1,4 @@
+---
+"@patternfly/elements": major
+---
+`<pf-label>`: Removed `BaseLabel` class. Reimplement (recommended) or extend `PfLabel`.
diff --git a/elements/package.json b/elements/package.json
index 0cd47fe88f..192ad19080 100644
--- a/elements/package.json
+++ b/elements/package.json
@@ -35,7 +35,6 @@
     "./pf-jump-links/pf-jump-links-item.js": "./pf-jump-links/pf-jump-links-item.js",
     "./pf-jump-links/pf-jump-links-list.js": "./pf-jump-links/pf-jump-links-list.js",
     "./pf-jump-links/pf-jump-links.js": "./pf-jump-links/pf-jump-links.js",
-    "./pf-label/BaseLabel.js": "./pf-label/BaseLabel.js",
     "./pf-label/pf-label.js": "./pf-label/pf-label.js",
     "./pf-modal/pf-modal.js": "./pf-modal/pf-modal.js",
     "./pf-panel/pf-panel.js": "./pf-panel/pf-panel.js",
diff --git a/elements/pf-label/BaseLabel.css b/elements/pf-label/BaseLabel.css
deleted file mode 100644
index 178d4ed79a..0000000000
--- a/elements/pf-label/BaseLabel.css
+++ /dev/null
@@ -1,44 +0,0 @@
-:host {
-  position: relative;
-  white-space: nowrap;
-  border: 0;
-}
-
-pf-icon, ::slotted(pf-icon) {
-  color: currentColor;
-}
-
-:host,
-#container {
-  display: inline-flex;
-  align-items: center;
-  vertical-align: middle;
-}
-
-#container {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  border-width: 0;
-}
-
-#container::before {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  pointer-events: none;
-  content: "";
-}
-
-[part=icon] {
-  display: none;
-  pointer-events: none;
-}
-
-.hasIcon [part=icon] {
-  display: inline-flex;
-  width: 1em;
-}
-
diff --git a/elements/pf-label/BaseLabel.ts b/elements/pf-label/BaseLabel.ts
deleted file mode 100644
index a3f524c6cb..0000000000
--- a/elements/pf-label/BaseLabel.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { LitElement, html } from 'lit';
-import { classMap } from 'lit/directives/class-map.js';
-
-import { SlotController } from '@patternfly/pfe-core/controllers/slot-controller.js';
-
-import styles from './BaseLabel.css';
-
-/**
- * Base label class
-*/
-export abstract class BaseLabel extends LitElement {
-  static readonly styles = [styles];
-
-  abstract variant?: string;
-
-  abstract color?: string;
-
-  abstract icon?: string;
-
-  /** Represents the state of the anonymous and icon slots */
-  protected slots = new SlotController(this, null, 'icon');
-
-  override render() {
-    const { variant, color, icon } = this;
-    const hasIcon = !!icon || this.slots.hasSlotted('icon');
-    return html`
-      <span id="container"
-            class=${classMap({ hasIcon, [variant ?? '']: !!variant, [color ?? '']: !!color })}>
-        <slot name="icon" part="icon">${this.renderDefaultIcon?.()}</slot>
-        <slot id="text"></slot>
-        ${this.renderSuffix?.() ?? ''}
-      </span>
-    `;
-  }
-
-  /**
-   * Fallback content for the icon slot. When the `icon` attribute is set, it
-   * should render an icon corresponding to the value.
-   *
-   * @example ```html
-   * <pf-icon icon=${this.icon}></pf-icon>
-   * ```
-   */
-  protected abstract renderDefaultIcon?(): unknown;
-
-  /**
-   * Optional override to render content after the anonymous slot.
-   * @example ```html
-   * <button id="close-button">X</button>
-   * ```
-   */
-  protected abstract renderSuffix?(): unknown;
-}
diff --git a/elements/pf-label/pf-label.css b/elements/pf-label/pf-label.css
index 8705c80cda..9ceb276661 100644
--- a/elements/pf-label/pf-label.css
+++ b/elements/pf-label/pf-label.css
@@ -1,10 +1,25 @@
-#pf-container {
-  display: contents;
+:host {
+  position: relative;
+  white-space: nowrap;
+  border: 0;
 }
 
+pf-icon, ::slotted(pf-icon) {
+  color: currentColor;
+}
+
+:host,
 #container {
-  --pf-global--icon--FontSize--sm: 14px;
+  display: inline-flex;
+  align-items: center;
+  vertical-align: middle;
+}
 
+#container {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  border-width: 0;
   padding-top: var(--pf-c-label--PaddingTop, var(--pf-global--spacer--xs, 0.25rem));
   padding-left: var(--pf-c-label--PaddingLeft, var(--pf-global--spacer--sm, 0.5rem));
   padding-bottom: var(--pf-c-label--PaddingBottom, var(--pf-global--spacer--xs, 0.25rem));
@@ -15,13 +30,32 @@
   border-radius: var(--pf-c-label--BorderRadius, 30em);
   max-width: var(--pf-c-label__content--MaxWidth, 100%);
   color: var(--pf-c-label__content--Color, var(--pf-global--Color--100, #151515));
+
+  --pf-global--icon--FontSize--sm: 14px;
 }
 
 #container::before {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  pointer-events: none;
+  content: "";
   border-radius: var(--pf-c-label--BorderRadius, 30em);
   border: var(--pf-c-label__content--before--BorderWidth, 1px) solid var(--pf-c-label__content--before--BorderColor, var(--pf-global--palette--black-300, #d2d2d2));
 }
 
+[part=icon] {
+  display: none;
+  pointer-events: none;
+}
+
+.hasIcon [part=icon] {
+  display: inline-flex;
+  width: 1em;
+}
+
 .compact {
   --pf-c-label--PaddingTop: var(--pf-c-label--m-compact--PaddingTop, 0);
   --pf-c-label--PaddingRight: var(--pf-c-label--m-compact--PaddingRight, var(--pf-global--spacer--sm, 0.5rem));
@@ -30,7 +64,6 @@
   --pf-global--icon--FontSize--sm: 12px;
 }
 
-
 .blue {
   --pf-c-label__content--Color: var(--pf-c-label--m-blue__content--Color, var(--pf-global--info-color--200, #002952));
   --pf-c-label--BackgroundColor: var(--pf-c-label--m-blue--BackgroundColor, var(--pf-global--palette--blue-50, #e7f1fa));
diff --git a/elements/pf-label/pf-label.ts b/elements/pf-label/pf-label.ts
index fa5309f3ee..be6627a713 100644
--- a/elements/pf-label/pf-label.ts
+++ b/elements/pf-label/pf-label.ts
@@ -1,31 +1,19 @@
-import { html } from 'lit';
+import { LitElement, html } from 'lit';
 import { customElement } from 'lit/decorators/custom-element.js';
 import { property } from 'lit/decorators/property.js';
 import { classMap } from 'lit/directives/class-map.js';
 
-import { ComposedEvent } from '@patternfly/pfe-core';
-
-import { BaseLabel } from './BaseLabel.js';
+import { SlotController } from '@patternfly/pfe-core/controllers/slot-controller.js';
 
 import '@patternfly/elements/pf-button/pf-button.js';
 
 import styles from './pf-label.css';
 
-export type LabelVariant = (
-  | 'filled'
-  | 'outline'
-);
-
-export type LabelColor = (
-  | 'blue'
-  | 'cyan'
-  | 'green'
-  | 'orange'
-  | 'purple'
-  | 'red'
-  | 'grey'
-  | 'gold'
-)
+export class LabelCloseEvent extends Event {
+  constructor() {
+    super('close', { bubbles: true });
+  }
+}
 
 /**
  * The **label** component allows users to add specific element captions for user
@@ -33,7 +21,7 @@ export type LabelColor = (
  *
  * @summary Allows users to display meta data in a stylized form.
  *
- * @fires close - when a removable label's close button is clicked
+ * @fires {LabelCloseEvent} close - when a removable label's close button is clicked
  *
  * @cssprop {<length>} --pf-c-label--FontSize   {@default `0.875em`}
  *
@@ -112,22 +100,22 @@ export type LabelColor = (
  * @cssprop {<length>} --pf-c-label--m-compact--PaddingLeft    {@default `0.5rem`}
  */
 @customElement('pf-label')
-export class PfLabel extends BaseLabel {
-  static readonly styles = [...BaseLabel.styles, styles];
+export class PfLabel extends LitElement {
+  static readonly styles = [styles];
 
-  static readonly shadowRootOptions: ShadowRootInit = { ...BaseLabel.shadowRootOptions, delegatesFocus: true };
+  static readonly shadowRootOptions: ShadowRootInit = { ...LitElement.shadowRootOptions, delegatesFocus: true };
 
   /**
    * Changes the style of the label.
    * - Filled: Colored background with colored border.
    * - Outline: White background with colored border.
    */
-  @property() variant: LabelVariant = 'filled';
+  @property() variant: 'filled' | 'outline' = 'filled';
 
   /**
    * Changes the color of the label
    */
-  @property() color: LabelColor = 'grey';
+  @property() color: 'blue' | 'cyan' | 'green' | 'orange' | 'purple' | 'red' | 'grey' | 'gold' = 'grey';
 
   /** Shorthand for the `icon` slot, the value is icon name */
   @property() icon?: string;
@@ -144,34 +132,51 @@ export class PfLabel extends BaseLabel {
   /** Text label for a removable label's close button */
   @property({ attribute: 'close-button-label' }) closeButtonLabel?: string;
 
+  /** Represents the state of the anonymous and icon slots */
+  #slots = new SlotController(this, null, 'icon');
+
   override render() {
     const { compact, truncated } = this;
+    const { variant, color, icon } = this;
+    const hasIcon = !!icon || this.#slots.hasSlotted('icon');
     return html`
-      <span id="pf-container" class="${classMap({ compact, truncated })}">${super.render()}</span>
-    `;
-  }
-
-  protected override renderDefaultIcon() {
-    return !this.icon ? '' : html`
-      <pf-icon icon="${this.icon}" size="sm"></pf-icon>
+      <span id="container"
+            class="${classMap({
+              hasIcon,
+              compact,
+              truncated,
+              [variant ?? '']: !!variant,
+              [color ?? '']: !!color })}">
+        <slot name="icon" part="icon">
+          <pf-icon ?hidden="${!icon}"
+                   size="sm"
+                   .icon="${this.icon || undefined as unknown as string}"></pf-icon>
+        </slot>
+        <slot id="text"></slot>
+        <span part="close-button" ?hidden=${!this.removable}>
+          <pf-button plain
+                     @click="${this.#onClickClose}"
+                     label="${this.closeButtonLabel ?? 'remove'}">
+            <svg viewBox="0 0 352 512">
+              <path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"/>
+            </svg>
+          </pf-button>
+        </span>
+      </span>
     `;
   }
 
-  protected override renderSuffix() {
-    return !this.removable ? '' : html`
-      <span part="close-button" ?hidden=${!this.removable}>
-        <pf-button plain
-                    @click="${() => this.dispatchEvent(new ComposedEvent('close'))}"
-                    label="${this.closeButtonLabel ?? 'remove'}">
-          <svg viewBox="0 0 352 512">
-            <path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"/>
-          </svg>
-        </pf-button>
-      </span>
-    `;
+  #onClickClose() {
+    if (this.removable && this.dispatchEvent(new LabelCloseEvent())) {
+      this.remove();
+    }
   }
 }
 
+export type LabelVariant = PfLabel['variant'];
+
+export type LabelColor = PfLabel['color'];
+
 declare global {
   interface HTMLElementTagNameMap {
     'pf-label': PfLabel;

From 16630a73c587997652c9a05a9fdc57acb36c9afe Mon Sep 17 00:00:00 2001
From: Benny Powers <web@bennypowers.com>
Date: Thu, 19 Oct 2023 11:44:42 +0300
Subject: [PATCH 2/7] feat(label): self-remove on close

---
 .changeset/label-close-remove.md | 17 +++++++++++++++++
 elements/pf-label/pf-label.ts    |  2 +-
 2 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 .changeset/label-close-remove.md

diff --git a/.changeset/label-close-remove.md b/.changeset/label-close-remove.md
new file mode 100644
index 0000000000..063b1d7797
--- /dev/null
+++ b/.changeset/label-close-remove.md
@@ -0,0 +1,17 @@
+---
+"@patternfly/elements": major
+---
+`<pf-label>`: when clicking close button, `close` event is fired.
+Now, if that event is not cancelled, the label will remove itself from the document.
+
+To restore previous behaviour:
+
+```js
+import { LabelCloseEvent } from '@patternfly/elements/pf-label/pf-label.js';
+label.addEventListener('close', function(event) {
+  if (event instanceof LabelCloseEvent) {
+    event.preventDefault();
+    return false;
+  }
+});
+```
diff --git a/elements/pf-label/pf-label.ts b/elements/pf-label/pf-label.ts
index be6627a713..a16162a17d 100644
--- a/elements/pf-label/pf-label.ts
+++ b/elements/pf-label/pf-label.ts
@@ -11,7 +11,7 @@ import styles from './pf-label.css';
 
 export class LabelCloseEvent extends Event {
   constructor() {
-    super('close', { bubbles: true });
+    super('close', { bubbles: true, cancelable: true });
   }
 }
 

From f4b507beb61407eb2ef5d42b15eb4a066ce1b9af Mon Sep 17 00:00:00 2001
From: Benny Powers <web@bennypowers.com>
Date: Thu, 19 Oct 2023 11:48:52 +0300
Subject: [PATCH 3/7] test(label): update tests

---
 elements/pf-label/test/pf-label.spec.ts | 44 +++++++++++++++----------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/elements/pf-label/test/pf-label.spec.ts b/elements/pf-label/test/pf-label.spec.ts
index a21006dce7..5705208855 100644
--- a/elements/pf-label/test/pf-label.spec.ts
+++ b/elements/pf-label/test/pf-label.spec.ts
@@ -22,14 +22,6 @@ const exampleWithOutlineAttribute = html`
   <pf-label variant="outline">Default Outline</pf-label>
 `;
 
-const exampleWithIconAttribute = html`
-  <pf-label icon="rh-icon-virtual-storage-stack">Default Icon</pf-label>
-`;
-
-const exampleWithIconAttributeEmpty = html`
-  <pf-label icon="">Default</pf-label>
-`;
-
 const exampleWithCompactAttribute = html`
   <pf-label compact>Default Compact</pf-label>
 `;
@@ -102,18 +94,34 @@ describe('<pf-label>', function() {
     expect(beforeStyles.getPropertyValue('border-color')).to.equal('rgb(210, 210, 210)');
   });
 
-  it('should render a pf-icon if the icon attribute is present and valid', async function() {
-    const el = await createFixture<PfLabel>(exampleWithIconAttribute);
-    await el.updateComplete;
-    const icon = el.shadowRoot!.querySelector('pf-icon')!;
-    expect(icon.icon).to.equal(el.icon);
+  describe('with valid icon attribute', function() {
+    let element: PfLabel;
+    beforeEach(async function() {
+      element = await createFixture<PfLabel>(html`
+        <pf-label icon="rh-icon-virtual-storage-stack">Default Icon</pf-label>
+      `);
+      element.updateComplete;
+    });
+    it('should render a pf-icon', async function() {
+      const icon = element.shadowRoot!.querySelector('pf-icon')!;
+      expect(icon.hidden).to.be.false;
+      expect(icon.icon).to.equal(element.icon);
+    });
   });
 
-  it('should not render a pf-icon if the icon attribute is present but empty', async function() {
-    const el = await createFixture<PfLabel>(exampleWithIconAttributeEmpty);
-    await el.updateComplete;
-    const icon = el.shadowRoot!.querySelector('pf-icon')!;
-    expect(icon).to.be.equal(null);
+  describe('with empty icon attribute', function() {
+    let element: PfLabel;
+    beforeEach(async function() {
+      element = await createFixture<PfLabel>(html`
+        <pf-label icon="">Default</pf-label>
+      `);
+      element.updateComplete;
+    });
+    it('should not render a pf-icon', async function() {
+      const icon = element.shadowRoot!.querySelector('pf-icon')!;
+      expect(icon.hidden).to.be.true;
+      expect(icon.icon).to.be.undefined;
+    });
   });
 
   it('should display compact version if the attribute is-compact is present', async function() {

From ee60430e864ba5c5ce542a3d2619e064eda8dd99 Mon Sep 17 00:00:00 2001
From: Steven Spriggs <steven.spriggs@gmail.com>
Date: Wed, 1 Nov 2023 10:35:33 -0400
Subject: [PATCH 4/7] fix(label): correct font-size unit, include missing pf
 global var

---
 elements/pf-label/pf-label.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/elements/pf-label/pf-label.css b/elements/pf-label/pf-label.css
index 9ceb276661..40f770bdb5 100644
--- a/elements/pf-label/pf-label.css
+++ b/elements/pf-label/pf-label.css
@@ -24,7 +24,7 @@ pf-icon, ::slotted(pf-icon) {
   padding-left: var(--pf-c-label--PaddingLeft, var(--pf-global--spacer--sm, 0.5rem));
   padding-bottom: var(--pf-c-label--PaddingBottom, var(--pf-global--spacer--xs, 0.25rem));
   padding-right: var(--pf-c-label--PaddingRight, var(--pf-global--spacer--sm, 0.5rem));
-  font-size: var(--pf-c-label--FontSize, 0.875em);
+  font-size: var(--pf-c-label--FontSize, var(--pf-global--FontSize--sm, 0.875rem));
   color: var(--pf-c-label--Color, var(--pf-global--Color--100, #151515));
   background-color: var(--pf-c-label--BackgroundColor, var(--pf-global--palette--black-150, #f5f5f5));
   border-radius: var(--pf-c-label--BorderRadius, 30em);

From 3e299002b5d490cfd547c1e9dbb4ce2624cbd2cc Mon Sep 17 00:00:00 2001
From: Steven Spriggs <steven.spriggs@gmail.com>
Date: Tue, 14 Nov 2023 12:10:58 -0500
Subject: [PATCH 5/7] docs(label): fix accesibility demo

---
 elements/pf-label/docs/pf-label.md | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/elements/pf-label/docs/pf-label.md b/elements/pf-label/docs/pf-label.md
index 4466257d6d..34c7ae8423 100644
--- a/elements/pf-label/docs/pf-label.md
+++ b/elements/pf-label/docs/pf-label.md
@@ -31,6 +31,17 @@
   </div>
 
   {% htmlexample %}
+  <style>
+    .visually-hidden-class {
+      clip: rect(0 0 0 0); 
+      clip-path: inset(50%);
+      height: 1px;
+      overflow: hidden;
+      position: absolute;
+      white-space: nowrap; 
+      width: 1px;
+    }
+  </style>
   <pf-label color="red">
     Red <span class="visually-hidden-class">Warning</span>
   </pf-label>

From 40d5569fabdeb81eac068c49a0480d72e3032b22 Mon Sep 17 00:00:00 2001
From: Steven Spriggs <steven.spriggs@gmail.com>
Date: Tue, 14 Nov 2023 12:20:18 -0500
Subject: [PATCH 6/7] fix(label): removes the removal of element and only
 triggers close event

---
 elements/pf-label/pf-label.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/elements/pf-label/pf-label.ts b/elements/pf-label/pf-label.ts
index a16162a17d..37d5a0d54b 100644
--- a/elements/pf-label/pf-label.ts
+++ b/elements/pf-label/pf-label.ts
@@ -167,9 +167,10 @@ export class PfLabel extends LitElement {
   }
 
   #onClickClose() {
-    if (this.removable && this.dispatchEvent(new LabelCloseEvent())) {
-      this.remove();
+    if (this.removable) {
+      return;
     }
+    this.dispatchEvent(new LabelCloseEvent());
   }
 }
 

From 536273bd068d8216755378d91c5f2b62d9bc7461 Mon Sep 17 00:00:00 2001
From: Steven Spriggs <steven.spriggs@gmail.com>
Date: Tue, 14 Nov 2023 12:21:34 -0500
Subject: [PATCH 7/7] fix(label): undo last commit, see the example in the
 changeset

---
 elements/pf-label/pf-label.ts | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/elements/pf-label/pf-label.ts b/elements/pf-label/pf-label.ts
index 37d5a0d54b..a16162a17d 100644
--- a/elements/pf-label/pf-label.ts
+++ b/elements/pf-label/pf-label.ts
@@ -167,10 +167,9 @@ export class PfLabel extends LitElement {
   }
 
   #onClickClose() {
-    if (this.removable) {
-      return;
+    if (this.removable && this.dispatchEvent(new LabelCloseEvent())) {
+      this.remove();
     }
-    this.dispatchEvent(new LabelCloseEvent());
   }
 }