diff --git a/.changeset/legal-swans-occur.md b/.changeset/legal-swans-occur.md new file mode 100644 index 00000000000..6b641130ada --- /dev/null +++ b/.changeset/legal-swans-occur.md @@ -0,0 +1,5 @@ +--- +"@hashicorp/design-system-components": major +--- + +Removed the deprecated `MenuPrimitive` component diff --git a/packages/components/package.json b/packages/components/package.json index a99475c364a..76c752d5cd9 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -305,7 +305,6 @@ "./components/hds/layout/grid/item.js": "./dist/_app_/components/hds/layout/grid/item.js", "./components/hds/link/inline.js": "./dist/_app_/components/hds/link/inline.js", "./components/hds/link/standalone.js": "./dist/_app_/components/hds/link/standalone.js", - "./components/hds/menu-primitive.js": "./dist/_app_/components/hds/menu-primitive.js", "./components/hds/modal/body.js": "./dist/_app_/components/hds/modal/body.js", "./components/hds/modal/footer.js": "./dist/_app_/components/hds/modal/footer.js", "./components/hds/modal/header.js": "./dist/_app_/components/hds/modal/header.js", diff --git a/packages/components/src/components.ts b/packages/components/src/components.ts index 400dc061324..3b6fcc9a9d0 100644 --- a/packages/components/src/components.ts +++ b/packages/components/src/components.ts @@ -390,8 +390,5 @@ export { default as HdsDismissButton } from './components/hds/dismiss-button/ind // Interactive export { default as HdsInteractive } from './components/hds/interactive/index.ts'; -// MenuPrimitive -export { default as HdsMenuPrimitive } from './components/hds/menu-primitive/index.ts'; - // PopoverPrimitive export { default as HdsPopoverPrimitive } from './components/hds/popover-primitive/index.ts'; diff --git a/packages/components/src/components/hds/dropdown/index.ts b/packages/components/src/components/hds/dropdown/index.ts index 12bccfcd4ce..2f652915604 100644 --- a/packages/components/src/components/hds/dropdown/index.ts +++ b/packages/components/src/components/hds/dropdown/index.ts @@ -15,7 +15,7 @@ import { } from './types.ts'; import type { ComponentLike } from '@glint/template'; -import type { MenuPrimitiveSignature } from '../menu-primitive'; +import type { HdsPopoverPrimitiveSignature } from '../popover-primitive/index.ts'; import type { HdsDropdownFooterSignature } from './footer'; import type { HdsDropdownHeaderSignature } from './header'; import type { HdsDropdownListItemCheckboxSignature } from './list-item/checkbox'; @@ -39,15 +39,16 @@ export const POSITIONS: HdsDropdownPositions[] = Object.values( ); export interface HdsDropdownSignature { - Args: MenuPrimitiveSignature['Args'] & { + Args: { height?: string; isInline?: boolean; - isOpen?: boolean; + isOpen?: HdsPopoverPrimitiveSignature['Args']['isOpen']; listPosition?: HdsDropdownPositions; width?: string; enableCollisionDetection?: HdsAnchoredPositionOptions['enableCollisionDetection']; preserveContentInDom?: boolean; matchToggleWidth?: boolean; + onClose?: HdsPopoverPrimitiveSignature['Args']['onClose']; }; Blocks: { default: [ @@ -69,7 +70,7 @@ export interface HdsDropdownSignature { }, ]; }; - Element: MenuPrimitiveSignature['Element']; + Element: HTMLDivElement; } export default class HdsDropdown extends Component { diff --git a/packages/components/src/components/hds/menu-primitive/index.hbs b/packages/components/src/components/hds/menu-primitive/index.hbs deleted file mode 100644 index 29a6c04850b..00000000000 --- a/packages/components/src/components/hds/menu-primitive/index.hbs +++ /dev/null @@ -1,25 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: MPL-2.0 -}} -{{! - THIS COMPONENT IS NOW DEPRECATED -}} -{{! template-lint-disable no-invalid-interactive }} -
-
- {{yield (hash onClickToggle=this.onClickToggle isOpen=this.isOpen) to="toggle"}} -
- {{#if this.isOpen}} -
- {{yield (hash close=this.close) to="content"}} -
- {{/if}} -
-{{! template-lint-enable no-invalid-interactive }} \ No newline at end of file diff --git a/packages/components/src/components/hds/menu-primitive/index.ts b/packages/components/src/components/hds/menu-primitive/index.ts deleted file mode 100644 index db655a604da..00000000000 --- a/packages/components/src/components/hds/menu-primitive/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import Component from '@glimmer/component'; -import { deprecate } from '@ember/debug'; -import { tracked } from '@glimmer/tracking'; -import { action } from '@ember/object'; -import { schedule } from '@ember/runloop'; -import type Owner from '@ember/owner'; - -export interface MenuPrimitiveSignature { - Args: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onClose?: (...args: any[]) => void; - }; - Blocks: { - toggle?: [ - { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onClickToggle: (event: MouseEvent, ...args: any[]) => void; - isOpen?: boolean; - }, - ]; - content?: [ - { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - close: (...args: any[]) => void; - }, - ]; - }; - Element: HTMLDivElement; -} - -export default class MenuPrimitive extends Component { - @tracked isOpen: boolean | undefined; // notice: if in the future we need to add a "@isOpen" prop to control the status from outside (eg to have the MenuPrimitive opened on render) just add "this.args.isOpen" here to initalize the variable - @tracked toggleRef: HTMLElement | undefined; - @tracked _element!: HTMLElement; - - constructor(owner: Owner, args: MenuPrimitiveSignature['Args']) { - super(owner, args); - - deprecate( - 'The `Hds::MenuPrimitive` component is now deprecated and will be removed in the next major version of `@hashicorp/design-system-components`.', - false, - { - id: 'hds.components.menu-primitive', - until: '5.0.0', - url: 'https://helios.hashicorp.design/components/menu-primitive?tab=version%20history#460', - for: '@hashicorp/design-system-components', - since: { - enabled: '4.10.0', - available: '4.10.0', - }, - } - ); - } - - @action - didInsert(element: HTMLElement): void { - this._element = element; - } - - @action - onClickToggle(event: MouseEvent): void { - // we store a reference to the DOM node that has the "onClickToggle" event associated with it - if (!this.toggleRef) { - this.toggleRef = event.currentTarget as HTMLElement; - } - this.isOpen = !this.isOpen; - // we explicitly apply a focus state to the toggle element to overcome a bug in WebKit (see https://github.com/hashicorp/design-system/commit/40cd7f6b3cb15c45f9a1235fafd0fb3ed58e6e62) - this.toggleRef?.focus(); - } - - @action - onFocusOut(event: FocusEvent): void { - // due to inconsistent implementation of relatedTarget across browsers we use the activeElement as a fallback - // if the related target is not part of the disclosed content we close the disclosed container - if ( - !this._element.contains( - (event.relatedTarget as Node) || (document.activeElement as Node) - ) - ) { - this.close(); - } - } - - @action - onKeyUp(event: KeyboardEvent): void { - if (event.key === 'Escape') { - this.close(); - this.toggleRef?.focus(); - } - } - - @action - close(): void { - // we schedule this afterRender to avoid an error in tests caused by updating `isOpen` multiple times in the same computation - // eslint-disable-next-line ember/no-runloop - schedule('afterRender', (): void => { - this.isOpen = false; - // we call the "onClose" callback if it exists (and is a function) - if (this.args.onClose && typeof this.args.onClose === 'function') { - this.args.onClose(); - } - }); - } -} diff --git a/packages/components/src/styles/@hashicorp/design-system-components.scss b/packages/components/src/styles/@hashicorp/design-system-components.scss index 00c6008b820..c74eaa36f4b 100644 --- a/packages/components/src/styles/@hashicorp/design-system-components.scss +++ b/packages/components/src/styles/@hashicorp/design-system-components.scss @@ -39,7 +39,6 @@ @use "../components/icon-tile"; @use "../components/layout"; // multiple components @use "../components/link"; // multiple components -@use "../components/menu-primitive"; @use "../components/modal"; @use "../components/page-header"; @use "../components/pagination"; diff --git a/packages/components/src/styles/components/dropdown.scss b/packages/components/src/styles/components/dropdown.scss index 0c35374cd8b..014c6146f74 100644 --- a/packages/components/src/styles/components/dropdown.scss +++ b/packages/components/src/styles/components/dropdown.scss @@ -207,7 +207,7 @@ $hds-dropdown-toggle-border-radius: $hds-button-border-radius; // LIST // UL ELEMENT -// GOES INSIDE HDS::MenuPrimitive's :content block +// GOES INSIDE HDS::PopoverPrimitive's popover element .hds-dropdown__content { position: relative; diff --git a/packages/components/src/styles/components/menu-primitive.scss b/packages/components/src/styles/components/menu-primitive.scss deleted file mode 100644 index 0ed5a234395..00000000000 --- a/packages/components/src/styles/components/menu-primitive.scss +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -// -// MenuPrimitive COMPONENT -// - -.hds-menu-primitive { - position: relative; - width: fit-content; -} diff --git a/packages/components/src/template-registry.ts b/packages/components/src/template-registry.ts index 66183aa31c6..2af371f3514 100644 --- a/packages/components/src/template-registry.ts +++ b/packages/components/src/template-registry.ts @@ -168,7 +168,6 @@ import type HdsLayoutGridComponent from './components/hds/layout/grid'; import type HdsLayoutGridItemComponent from './components/hds/layout/grid/item'; import type HdsLinkInlineComponent from './components/hds/link/inline'; import type HdsLinkStandaloneComponent from './components/hds/link/standalone'; -import type HdsMenuPrimitiveComponent from './components/hds/menu-primitive'; import type HdsModalBodyComponent from './components/hds/modal/body'; import type HdsModalFooterComponent from './components/hds/modal/footer'; import type HdsModalHeaderComponent from './components/hds/modal/header'; @@ -806,10 +805,6 @@ export default interface HdsComponentsRegistry { 'Hds::Link::Standalone': typeof HdsLinkStandaloneComponent; 'hds/link/standalone': typeof HdsLinkStandaloneComponent; - // MenuPrimitive - 'Hds::MenuPrimitive': typeof HdsMenuPrimitiveComponent; - 'hds/menu-primitive': typeof HdsMenuPrimitiveComponent; - // Modal 'Hds::Modal': typeof HdsModalComponent; 'hds/modal': typeof HdsModalComponent; diff --git a/showcase/app/router.ts b/showcase/app/router.ts index 3defc276327..9c93eafb5eb 100644 --- a/showcase/app/router.ts +++ b/showcase/app/router.ts @@ -137,7 +137,6 @@ Router.map(function () { this.route('disclosure-primitive'); this.route('dismiss-button'); this.route('interactive'); - this.route('menu-primitive'); this.route('popover-primitive'); }); this.route('page-overrides', { path: 'overrides' }, function () { diff --git a/showcase/app/styles/app.scss b/showcase/app/styles/app.scss index fb06fee50bd..f4205a7f1bf 100644 --- a/showcase/app/styles/app.scss +++ b/showcase/app/styles/app.scss @@ -66,7 +66,6 @@ @use "./showcase-pages/layout/flex" as showcase-layout-flex; @use "./showcase-pages/layout/grid" as showcase-layout-grid; @use "./showcase-pages/link-inline" as showcase-link-inline; -@use "./showcase-pages/menu-primitive" as showcase-menu-primitive; @use "./showcase-pages/modal" as showcase-modal; @use "./showcase-pages/page-header" as showcase-page-header; @use "./showcase-pages/pagination" as showcase-pagination; diff --git a/showcase/app/styles/showcase-pages/menu-primitive.scss b/showcase/app/styles/showcase-pages/menu-primitive.scss deleted file mode 100644 index 02f0eea3691..00000000000 --- a/showcase/app/styles/showcase-pages/menu-primitive.scss +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -// MenuPrimitive - -body.page-utilities-menu-primitive { - .shw-utility-menu-primitive-container { - min-height: 120px; - padding: 20px; - outline: 1px dotted var(--shw-color-gray-400); - } - - .shw-utility-menu-primitive-content-list-of-links { - width: fit-content; - margin: 4px 0 0 0; - padding: 10px; - list-style: none; - border: 1px solid #ccc; - - li { - margin: 0; - padding: 0; - - & + li { - border-top: 1px dotted #ccc; - } - } - - a { - display: block; - padding: 5px; - } - } - - .shw-utility-menu-primitive-button-wrapper { - padding: 20px; - outline: 1px dotted #ccc; - } -} diff --git a/showcase/app/templates/index.hbs b/showcase/app/templates/index.hbs index e54ca02ab7e..151c12a3c52 100644 --- a/showcase/app/templates/index.hbs +++ b/showcase/app/templates/index.hbs @@ -369,11 +369,6 @@ Interactive -
  • - - MenuPrimitive - -
  • PopoverPrimitive diff --git a/showcase/app/templates/page-utilities/menu-primitive.hbs b/showcase/app/templates/page-utilities/menu-primitive.hbs deleted file mode 100644 index ac2456e9fc2..00000000000 --- a/showcase/app/templates/page-utilities/menu-primitive.hbs +++ /dev/null @@ -1,141 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: MPL-2.0 -}} - -{{page-title "MenuPrimitive Component"}} - -MenuPrimitive - -
    - - - With generic HTML <button> and generic content (placeholder) - -
    - - <:toggle as |t|> - - - <:content> - - - -
    -
    -
    - - - With generic HTML <button> and generic list of <a> links - -
    - - <:toggle as |t|> - - - <:content as |c|> - - - -
    -
    -
    - - - With generic HTML - <button> - and generic - <input type="date"> - - -
    - - <:toggle as |t|> - - - <:content> - - - -
    -
    -
    - - - With <Hds::Button> and generic list of <a> links - -
    - - <:toggle as |t|> - - - <:content as |c|> - - - -
    -
    -
    - - - With - <Hds::Button> - inside a larger container and generic list of - <a> - links - -
    - - <:toggle as |t|> -
    - -
    - - <:content as |c|> - - -
    -
    -
    -
    - -
    \ No newline at end of file diff --git a/showcase/tests/integration/components/hds/menu-primitive/index-test.js b/showcase/tests/integration/components/hds/menu-primitive/index-test.js deleted file mode 100644 index d284b683bb4..00000000000 --- a/showcase/tests/integration/components/hds/menu-primitive/index-test.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'showcase/tests/helpers'; -import { - click, - triggerEvent, - triggerKeyEvent, - render, - resetOnerror, -} from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | hds/menu-primitive/index', function (hooks) { - setupRenderingTest(hooks); - - hooks.afterEach(() => { - resetOnerror(); - }); - - test('it should render the component with a CSS class that matches the component name', async function (assert) { - await render(hbs``); - assert.dom('div#test-menu-primitive').hasClass('hds-menu-primitive'); - }); - - // TOGGLE + CONTENT - - test('it should render the "toggle" block but not the "content', async function (assert) { - await render(hbs` - - <:toggle> - - - - `); - await click('button#test-toggle-button'); - assert.dom('.hds-menu-primitive__content').exists(); - assert.dom('button#test-content-button').exists(); - await click('button#test-content-button'); - assert.dom('.hds-menu-primitive__content').doesNotExist(); - assert.dom('button#test-content-button').doesNotExist(); - }); -}); diff --git a/website/docs/components/breadcrumb/partials/code/component-api.md b/website/docs/components/breadcrumb/partials/code/component-api.md index c8414ae4ad0..e7a55f262d3 100644 --- a/website/docs/components/breadcrumb/partials/code/component-api.md +++ b/website/docs/components/breadcrumb/partials/code/component-api.md @@ -53,7 +53,7 @@ The Breadcrumb component is composed of three different parts, each with their o Set on the truncation toggle button. Accepts a string. - Elements passed as children are yielded to the content of the [MenuPrimitive](/utilities/menu-primitive) component (used to show/hide the yielded Breadcrumb Items via a "toggle" button). + Elements passed as children are yielded to the content of the [PopoverPrimitive](/utilities/popover-primitive) component (used to show/hide the yielded Breadcrumb Items via a "toggle" button). This component supports use of [`...attributes`](https://guides.emberjs.com/release/in-depth-topics/patterns-for-components/#toc_attribute-ordering). diff --git a/website/docs/utilities/disclosure-primitive/index.md b/website/docs/utilities/disclosure-primitive/index.md index 12e84933c37..20d84d180a9 100644 --- a/website/docs/utilities/disclosure-primitive/index.md +++ b/website/docs/utilities/disclosure-primitive/index.md @@ -5,7 +5,6 @@ caption: An internal utility component that provides show/hide functionality. related: - components/accordion - components/reveal - - utilities/menu-primitive previewImage: assets/illustrations/utilities/disclosure-primitive.jpg navigation: keywords: diff --git a/website/docs/utilities/disclosure-primitive/partials/code/how-to-use.md b/website/docs/utilities/disclosure-primitive/partials/code/how-to-use.md index 1aa2eec1bc9..b4fe3882bdf 100644 --- a/website/docs/utilities/disclosure-primitive/partials/code/how-to-use.md +++ b/website/docs/utilities/disclosure-primitive/partials/code/how-to-use.md @@ -9,8 +9,6 @@ The `DisclosurePrimitive` component renders an interactive element that triggers When the content is disclosed, the container can be closed by toggling the button (`click` or `enter/return`). -The [MenuPrimitive](/utilities/menu-primitive), another variant of this primitive, includes extra functionality to close the content panel by either clicking outside of the content, or via the `esc` key. - ```handlebars <:toggle as |t|> diff --git a/website/docs/utilities/menu-primitive/index.md b/website/docs/utilities/menu-primitive/index.md deleted file mode 100644 index bea8e07e917..00000000000 --- a/website/docs/utilities/menu-primitive/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: MenuPrimitive -description: An internal utility component that provides show/hide functionality. -caption: An internal utility component that provides show/hide functionality. -related: - - components/breadcrumb - - components/dropdown - - utilities/disclosure-primitive -previewImage: assets/illustrations/utilities/menu-primitive.jpg -navigation: - keywords: - - show - - hide - - accordion - - dropdown - - reveal -status: - deprecated: 4.10.0 ---- - -
    - @include "partials/code/how-to-use.md" - @include "partials/code/component-api.md" -
    - -
    - @include "partials/version-history/version-history.md" -
    diff --git a/website/docs/utilities/menu-primitive/partials/code/component-api.md b/website/docs/utilities/menu-primitive/partials/code/component-api.md deleted file mode 100644 index 1c78fc5c4d5..00000000000 --- a/website/docs/utilities/menu-primitive/partials/code/component-api.md +++ /dev/null @@ -1,31 +0,0 @@ -## Component API - -### MenuPrimitive - - - - A named block that works as "toggle" for the MenuPrimitive. - - - A function to be called by the interactive element to toggle visibility of the content. - - - Hook into this tracked property to access the state of `isOpen`. - - - - - A named block for the content that is shown/hidden upon toggling. - - - A function to programmatically close the MenuPrimitive. - - - - - A callback function invoked when the MenuPrimitive is closed (if provided). - - - This component supports use of [`...attributes`](https://guides.emberjs.com/release/in-depth-topics/patterns-for-components/#toc_attribute-ordering). - - diff --git a/website/docs/utilities/menu-primitive/partials/code/how-to-use.md b/website/docs/utilities/menu-primitive/partials/code/how-to-use.md deleted file mode 100644 index c83c97af526..00000000000 --- a/website/docs/utilities/menu-primitive/partials/code/how-to-use.md +++ /dev/null @@ -1,29 +0,0 @@ -!!! Warning - -**Deprecation notice** - -The `MenuPrimitive` component is deprecated and will be removed in a future major release. It has been replaced internally with the [`PopoverPrimitive`](/utilities/popover-primitive). -!!! - -## How to use this component - -The `MenuPrimitive` component renders an interactive element that triggers a custom event handler provided by the `:toggle` block (passed via `hash` by Ember). To comply with accessibility best practices, this element is usually a button or a component that renders a button. - -When the content is disclosed, the container can be closed in various way; toggling via the button (`click` or `enter/return`), clicking outside of the content, or via the `esc` key. - -**Note:** [DisclosurePrimitive](/utilities/disclosure-primitive), another variant of this primitive, excludes the functionality to close the content panel by either clicking outside of the content, or via the `esc` key. - -```handlebars - - <:toggle as |t|> - - - <:content> - your content here - - -``` - -### Content positioning - -The `:content` block is **not** positioned in relation to the `:toggle` block. We recommend applying `position: absolute` to a wrapper around the content that is then passed to the `:content` block. diff --git a/website/docs/utilities/menu-primitive/partials/version-history/version-history.md b/website/docs/utilities/menu-primitive/partials/version-history/version-history.md deleted file mode 100644 index 08695b741ad..00000000000 --- a/website/docs/utilities/menu-primitive/partials/version-history/version-history.md +++ /dev/null @@ -1,7 +0,0 @@ -## 4.10.0 - -In this version we replaced all `MenuPrimitive` instances with `PopoverPrimitive`. For this reason we now consider the MenuPrimitive deprecated and we plan to removed in a future major release. - -### How to migrate - -Consider migrating the existing `MenuPrimitive` instances to [`PopoverPrimitive`](/utilities/popover-primitive). diff --git a/website/docs/utilities/popover-primitive/index.md b/website/docs/utilities/popover-primitive/index.md index 442438e968e..90e5e792c2d 100644 --- a/website/docs/utilities/popover-primitive/index.md +++ b/website/docs/utilities/popover-primitive/index.md @@ -11,7 +11,6 @@ links: https://github.com/hashicorp/design-system/tree/main/packages/components/src/components/hds/popover-primitive related: - utilities/disclosure-primitive - - utilities/menu-primitive previewImage: assets/illustrations/utilities/popover-primitive.jpg navigation: keywords: diff --git a/website/public/assets/illustrations/utilities/menu-primitive.jpg b/website/public/assets/illustrations/utilities/menu-primitive.jpg deleted file mode 100644 index b8e01345214..00000000000 Binary files a/website/public/assets/illustrations/utilities/menu-primitive.jpg and /dev/null differ diff --git a/website/tests/acceptance/utilities/menu-primitive-test.js b/website/tests/acceptance/utilities/menu-primitive-test.js deleted file mode 100644 index 5f049a46561..00000000000 --- a/website/tests/acceptance/utilities/menu-primitive-test.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import { module, test } from 'qunit'; -import { visit, currentURL } from '@ember/test-helpers'; -import { setupApplicationTest } from 'website/tests/helpers'; -import { a11yAudit } from 'ember-a11y-testing/test-support'; - -module('Acceptance | utilities/menu-primitive', function (hooks) { - setupApplicationTest(hooks); - - test('visiting /utilities/menu-primitive', async function (assert) { - await visit('/utilities/menu-primitive'); - - assert.strictEqual(currentURL(), '/utilities/menu-primitive'); - }); - - test('utilities/menu-primitive passes a11y automated checks', async function (assert) { - await visit('/utilities/menu-primitive'); - await a11yAudit(); - assert.ok(true, 'a11y automation audit passed'); - }); -});