From 3056af0f12c8fa4e9800f3f1c83e37a902246dfd Mon Sep 17 00:00:00 2001 From: Deeya Upadhyay <58636958+2020Deeya@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:27:24 +0530 Subject: [PATCH] docs: Implement Divider Component (#978) * fix: Implement Divider Component * Temporary build fix * Temporary fix * fix: ci errors, conventions * updated the component * fix: code refactoring * fix: update styles * Minor eslint fix * Renamed button attribute * updated styles with vertical token * update text divider gradient styling and handle rtl * no message * Updated Storybook UI * fix: address review comments * fix: address A11y issues * storybook cleanup * removed aria-label and aria-expanded from mdc-divider * Updated styles * minor eslint fix * Minor one * update RTL visual of the divider * fix: resolved review comments * chore: removed redundant internal state * fix: removed mutation observer * fix: updated the styling without using mutation observer --------- Co-authored-by: Supriya M --- packages/components/config/storybook/utils.ts | 17 +- .../components/divider/divider.component.ts | 233 ++++++++++++++++++ .../components/divider/divider.constants.ts | 49 ++++ .../components/divider/divider.e2e-test.ts | 66 +++++ .../src/components/divider/divider.stories.ts | 154 ++++++++++++ .../src/components/divider/divider.styles.ts | 157 ++++++++++++ .../src/components/divider/divider.types.ts | 8 + .../src/components/divider/index.ts | 12 + 8 files changed, 695 insertions(+), 1 deletion(-) create mode 100644 packages/components/src/components/divider/divider.component.ts create mode 100644 packages/components/src/components/divider/divider.constants.ts create mode 100644 packages/components/src/components/divider/divider.e2e-test.ts create mode 100644 packages/components/src/components/divider/divider.stories.ts create mode 100644 packages/components/src/components/divider/divider.styles.ts create mode 100644 packages/components/src/components/divider/divider.types.ts create mode 100644 packages/components/src/components/divider/index.ts diff --git a/packages/components/config/storybook/utils.ts b/packages/components/config/storybook/utils.ts index f876fb0b3..8178e2844 100644 --- a/packages/components/config/storybook/utils.ts +++ b/packages/components/config/storybook/utils.ts @@ -13,4 +13,19 @@ const disableControls = (keys: Array) => { return objectReturnValue; }; -export { disableControls }; +/** + * To automatically hide controls in storybook + * @param keys - Array of keys to hide + * @returns Object which can be destructured in argTypes + */ +const hideControls = (keys: Array) => { + const objectReturnValue: Record = {}; + keys.forEach((key) => { + objectReturnValue[key] = { + table: { disable: true } + }; + }); + return objectReturnValue; +}; + +export { disableControls, hideControls }; diff --git a/packages/components/src/components/divider/divider.component.ts b/packages/components/src/components/divider/divider.component.ts new file mode 100644 index 000000000..bd6779a91 --- /dev/null +++ b/packages/components/src/components/divider/divider.component.ts @@ -0,0 +1,233 @@ +import { CSSResult, html, PropertyValueMap } from 'lit'; +import { property } from 'lit/decorators.js'; +import styles from './divider.styles'; +import { Component } from '../../models'; +import { + ARROW_ICONS, + BUTTON_TAG, + DEFAULTS, + DIRECTIONS, + DIVIDER_ORIENTATION, + DIVIDER_VARIANT, + TEXT_TAG, +} from './divider.constants'; +import { Directions, DividerOrientation, DividerVariant } from './divider.types'; + +/** + * `mdc-divider` is a component that provides a line to separate and organize content. + * It can also include a button or text positioned centrally, allowing users to interact with the layout. + * + * **Divider Orientation:** + * - **Horizontal**: A thin, horizontal line. + * - **Vertical**: A thin, vertical line. + * + * **Divider Variants:** + * - **solid**: Solid line. + * - **gradient**: Gradient Line. + * + * **Divider Types:** + * - The type of divider is inferred based on the kind of slot present. + * - **Primary**: A simple horizontal or vertical divider. + * - **Text**: A horizontal divider with a text label in the center. + * - **Grabber Button**: A horizontal or vertical divider with a styled button in the center. + * + * **Accessibility:** + * - When the slot is replaced by an `mdc-button`: + * - `aria-label` should be passed to the `mdc-button`. + * - `aria-expanded` should be passed to the `mdc-button`. + * + * **Notes:** + * - If the slot is replaced by an invalid tag name or contains multiple elements, + * the divider defaults to the **Primary** type. + * - To override the styles of the divider, use the provided CSS custom properties. + * + * @tagname mdc-divider + * + * @cssproperty --mdc-divider-background-color - background color of the divider + * @cssproperty --mdc-divider-width - width of the divider + * @cssproperty --mdc-divider-horizontal-gradient - gradient of the horizontal divider + * @cssproperty --mdc-divider-vertical-gradient - gradient of the vertical divider + * @cssproperty --mdc-divider-text-size - font size of label in the text divider + * @cssproperty --mdc-divider-text-color - font color of label in the text divider + * @cssproperty --mdc-divider-text-margin - left and right margin of label in the text divider + * @cssproperty --mdc-divider-text-line-height - line height of label in the text divider + * @cssproperty --mdc-divider-grabber-button-border-radius - border radius of the grabber button + */ +class Divider extends Component { + /** + * Two orientations of divider + * - **horizontal**: A thin, horizontal line with 0.0625rem width. + * - **vertical**: A thin, vertical line with 0.0625rem width. + * + * Note: We do not support "Vertical Text Divider" as of now. + * @default horizontal + */ + @property({ type: String, reflect: true }) + orientation: DividerOrientation = DEFAULTS.ORIENTATION; + + /** + * Two variants of divider + * - **solid**: Solid line. + * - **gradient**: Gradient Line that fades on either sides of the divider. + * @default solid + */ + @property({ type: String, reflect: true }) + variant: DividerVariant = DEFAULTS.VARIANT; + + /** + * Direction of the arrow icon, if applicable. + * - **positive** + * - **negative** + * + * Note: Positive and Negative directions are defined based on Cartesian plane. + * @default 'negative' + */ + @property({ type: String, attribute: 'arrow-direction', reflect: true }) + arrowDirection: string = DEFAULTS.ARROW_DIRECTION; + + /** + * Position of the button, if applicable. + * - **positive** + * - **negative** + * + * Note: Positive and Negative directions are defined based on Cartesian plane. + * @default 'negative' + */ + @property({ type: String, attribute: 'button-position', reflect: true }) + buttonPosition: string = DEFAULTS.BUTTON_DIRECTION; + + /** + * Sets the variant attribute for the divider component. + * If the provided variant is not included in the DIVIDER_VARIANT, + * it defaults to the value specified in DEFAULTS.VARIANT. + * + * @param variant - The variant to set. + */ + private setVariant(variant: DividerVariant) { + this.setAttribute('variant', Object.values(DIVIDER_VARIANT).includes(variant) ? variant : DEFAULTS.VARIANT); + } + + /** + * Sets the orientation attribute for the divider component. + * If the provided orientation is not included in the DIVIDER_ORIENTATION, + * it defaults to the value specified in DEFAULTS.ORIENTATION. + * + * @param orientation - The orientation to set. + */ + private setOrientation(orientation: DividerOrientation) { + this.setAttribute( + 'orientation', + Object.values(DIVIDER_ORIENTATION).includes(orientation) ? orientation : DEFAULTS.ORIENTATION, + ); + } + + /** + * Sets the buttonPosition and arrowDirection attribute for the divider component. + * If the provided buttonPosition and arrowDirection are not included in the DIRECTIONS, + * it defaults to the value specified in DIRECTIONS based on the ORIENTATION. + * + * @param buttonPosition - The buttonPosition to set. + * @param arrowDirection - The arrowDirection to set. + */ + private ensureValidDirections() { + const defaultDirection = this.orientation === DIVIDER_ORIENTATION.HORIZONTAL + ? DIRECTIONS.NEGATIVE + : DIRECTIONS.POSITIVE; + + if (!Object.values(DIRECTIONS).includes(this.buttonPosition as Directions)) { + this.buttonPosition = defaultDirection; + } + + if (!Object.values(DIRECTIONS).includes(this.arrowDirection as Directions)) { + this.arrowDirection = defaultDirection; + } + } + + /** + * Configures the grabber button within the divider. + * + * - Sets the `prefix-icon` attribute for the grabber button based + * on the `arrow-direction` and `orientation` properties. + * + * This method updates the DOM element dynamically if a grabber button is present. + */ + private setGrabberButton(): void { + const buttonElement = this.querySelector('mdc-button'); + if (!buttonElement) return; + + this.ensureValidDirections(); + const iconType = this.getArrowIcon(); + buttonElement.setAttribute('variant', 'secondary'); + buttonElement.setAttribute('prefix-icon', iconType); + } + + /** + * Determines the arrow icon based on the consumer-defined `arrowDirection`. + * + * @returns The icon that represents the arrow direction. + */ + private getArrowIcon(): string { + const isHorizontal = this.orientation === DIVIDER_ORIENTATION.HORIZONTAL; + const isPositive = this.arrowDirection === DIRECTIONS.POSITIVE; + + if (isHorizontal) { + return isPositive ? ARROW_ICONS.UP : ARROW_ICONS.DOWN; + } + + return isPositive ? ARROW_ICONS.RIGHT : ARROW_ICONS.LEFT; + } + + public override update(changedProperties: PropertyValueMap | Map): void { + super.update(changedProperties); + + if (changedProperties.has('orientation')) { + this.setOrientation(this.orientation); + } + + if (changedProperties.has('variant')) { + this.setVariant(this.variant); + } + + if ( + changedProperties.has('orientation') + || changedProperties.has('arrowDirection') + || changedProperties.has('buttonPosition') + ) { + this.setGrabberButton(); + } + } + + /** + * Infers the type of divider based on the kind of slot present. + * @param slot - default slot of divider + */ + private inferDividerType() { + this.setAttribute('data-type', 'mdc-primary-divider'); + + const slot = this.shadowRoot?.querySelector('slot'); + const assignedElements = slot?.assignedElements({ flatten: true }) || []; + if (assignedElements.length > 1) return; + + const hasTextChild = assignedElements.some((el) => el.tagName === TEXT_TAG.toUpperCase()); + const hasButtonChild = assignedElements.some((el) => el.tagName === BUTTON_TAG.toUpperCase()); + + if (hasTextChild && !hasButtonChild) { + this.setAttribute('data-type', 'mdc-text-divider'); + } else if (!hasTextChild && hasButtonChild) { + this.setAttribute('data-type', 'mdc-grabber-divider'); + this.setGrabberButton(); + } + } + + protected override render() { + return html` +
+ +
+ `; + } + + public static override styles: Array = [...Component.styles, ...styles]; +} + +export default Divider; diff --git a/packages/components/src/components/divider/divider.constants.ts b/packages/components/src/components/divider/divider.constants.ts new file mode 100644 index 000000000..f2e7a1921 --- /dev/null +++ b/packages/components/src/components/divider/divider.constants.ts @@ -0,0 +1,49 @@ +import utils from '../../utils/tag-name'; +import { TAG_NAME as BUTTON_TAG } from '../button/button.constants'; +import { TAG_NAME as TEXT_TAG } from '../text/text.constants'; + +const TAG_NAME = utils.constructTagName('divider'); + +const DIVIDER_ORIENTATION = { + HORIZONTAL: 'horizontal', + VERTICAL: 'vertical', +} as const; + +const DIVIDER_VARIANT = { + SOLID: 'solid', + GRADIENT: 'gradient', +} as const; + +/** + * Direction types for both the arrow and button component. + * These directions are dependent on the divider's orientation. + */ +const DIRECTIONS = { + POSITIVE: 'positive', + NEGATIVE: 'negative', +} as const; + +const ARROW_ICONS = { + UP: 'arrow-up-regular', + DOWN: 'arrow-down-regular', + LEFT: 'arrow-left-regular', + RIGHT: 'arrow-right-regular', +} as const; + +const DEFAULTS = { + ORIENTATION: DIVIDER_ORIENTATION.HORIZONTAL, + VARIANT: DIVIDER_VARIANT.SOLID, + ARROW_DIRECTION: DIRECTIONS.NEGATIVE, + BUTTON_DIRECTION: DIRECTIONS.NEGATIVE, +} as const; + +export { + TAG_NAME, + DEFAULTS, + DIVIDER_VARIANT, + DIVIDER_ORIENTATION, + DIRECTIONS, + BUTTON_TAG, + TEXT_TAG, + ARROW_ICONS, +}; diff --git a/packages/components/src/components/divider/divider.e2e-test.ts b/packages/components/src/components/divider/divider.e2e-test.ts new file mode 100644 index 000000000..1967bd2c2 --- /dev/null +++ b/packages/components/src/components/divider/divider.e2e-test.ts @@ -0,0 +1,66 @@ +import { test } from '../../../config/playwright/setup'; + +test.beforeEach(async ({ componentsPage }) => { + await componentsPage.mount({ + html: ` + + `, + }); +}); + +test.skip('mdc-divider', async ({ componentsPage }) => { + const divider = componentsPage.page.locator('mdc-divider'); + + // initial check for the divider be visible on the screen: + await divider.waitFor(); + + /** + * ACCESSIBILITY + */ + await test.step('accessibility', async () => { + await componentsPage.accessibility.checkForA11yViolations('divider-default'); + }); + + /** + * VISUAL REGRESSION + */ + await test.step('visual-regression', async () => { + await test.step('matches screenshot of element', async () => { + await componentsPage.visualRegression.takeScreenshot('mdc-divider', { element: divider }); + }); + }); + + /** + * ATTRIBUTES + */ + await test.step('attributes', async () => { + await test.step('attribute X should be present on component by default', async () => { + // TODO: add test here + }); + }); + + /** + * INTERACTIONS + */ + await test.step('interactions', async () => { + await test.step('mouse/pointer', async () => { + await test.step('component should fire callback x when clicking on it', async () => { + // TODO: add test here + }); + }); + + await test.step('focus', async () => { + await test.step('component should be focusable with tab', async () => { + // TODO: add test here + }); + + // add additional tests here, like tabbing through several parts of the component + }); + + await test.step('keyboard', async () => { + await test.step('component should fire callback x when pressing y', async () => { + // TODO: add test here + }); + }); + }); +}); diff --git a/packages/components/src/components/divider/divider.stories.ts b/packages/components/src/components/divider/divider.stories.ts new file mode 100644 index 000000000..4e577c926 --- /dev/null +++ b/packages/components/src/components/divider/divider.stories.ts @@ -0,0 +1,154 @@ +import type { Meta, StoryObj, Args } from '@storybook/web-components'; +import '.'; +import { html } from 'lit'; +import { classArgType, styleArgType } from '../../../config/storybook/commonArgTypes'; +import { DIVIDER_ORIENTATION, DIVIDER_VARIANT, DIRECTIONS } from './divider.constants'; +import { disableControls, hideControls } from '../../../config/storybook/utils'; + +const contentMap: Record> = { + text: html`Label`, + // button role has been specifically added for managing storybook A11y. + grabber: html``, + noChildren: html``, +}; + +const render = (args: Args) => { + const content = contentMap[args.typeOfChildren] || html``; + + return html` +
+ + ${content} + +
+ `; +}; + +const meta: Meta = { + title: 'Work In Progress/divider', + tags: ['autodocs'], + component: 'mdc-divider', + render, + parameters: { + badges: ['wip'], + }, + argTypes: { + typeOfChildren: { + control: 'radio', + options: ['noChildren', 'text', 'grabber'], + description: 'Choose the type of content to render inside the divider', + }, + orientation: { + control: 'radio', + options: Object.values(DIVIDER_ORIENTATION), + }, + variant: { + control: 'radio', + options: Object.values(DIVIDER_VARIANT), + }, + 'arrow-direction': { + control: 'select', + options: Object.values(DIRECTIONS), + }, + 'button-position': { + control: 'select', + options: Object.values(DIRECTIONS), + }, + ...disableControls([ + '--mdc-divider-background-color', + '--mdc-divider-width', + '--mdc-divider-horizontal-gradient', + '--mdc-divider-vertical-gradient', + '--mdc-divider-text-size', + '--mdc-divider-text-color', + '--mdc-divider-text-margin', + '--mdc-divider-grabber-button-border-radius', + '--mdc-divider-text-line-height', + ]), + ...classArgType, + ...styleArgType, + ...hideControls(['observer']), + }, +}; + +export default meta; + +export const Example: StoryObj = { + args: { + typeOfChildren: 'noChildren', + orientation: DIVIDER_ORIENTATION.HORIZONTAL, + variant: DIVIDER_VARIANT.SOLID, + 'arrow-direction': DIRECTIONS.NEGATIVE, + 'button-position': DIRECTIONS.NEGATIVE, + }, + decorators: [ + (Story, context) => { + // Enforce horizontal orientation when typeOfChildren is 'text' + if (context.args.typeOfChildren === 'text' && context.args.orientation === DIVIDER_ORIENTATION.VERTICAL) { + context.args.orientation = DIVIDER_ORIENTATION.HORIZONTAL; + } + return Story(); + }, + ], +}; + +export const noChildrenDivider: StoryObj = { + argTypes: { + ...meta.argTypes, + typeOfChildren: { + control: 'radio', + options: ['noChildren'], + description: 'NoChildren type is selected', + }, + ...hideControls(['arrow-direction', 'button-position']), + }, + args: { + typeOfChildren: 'noChildren', + orientation: DIVIDER_ORIENTATION.HORIZONTAL, + variant: DIVIDER_VARIANT.SOLID, + }, +}; + +export const textDivider: StoryObj = { + argTypes: { + ...meta.argTypes, + typeOfChildren: { + control: 'radio', + options: ['text'], + description: 'Text type is selected', + }, + orientation: { + control: 'radio', + options: [DIVIDER_ORIENTATION.HORIZONTAL], + description: `Only horizontal orientation with 0.0625rem width is allowed. + We do not support "Vertical Text Divider" as of now.`, + }, + ...hideControls(['arrow-direction', 'button-position']), + }, + args: { + ...noChildrenDivider.args, + typeOfChildren: 'text', + }, +}; + +export const grabberButtonDivider: StoryObj = { + argTypes: { + ...meta.argTypes, + typeOfChildren: { + control: 'radio', + options: ['grabber'], + description: 'Grabber Button type is selected', + }, + }, + args: { + ...noChildrenDivider.args, + typeOfChildren: 'grabber', + 'arrow-direction': DIRECTIONS.NEGATIVE, + 'button-position': DIRECTIONS.NEGATIVE, + }, +}; diff --git a/packages/components/src/components/divider/divider.styles.ts b/packages/components/src/components/divider/divider.styles.ts new file mode 100644 index 000000000..41e299637 --- /dev/null +++ b/packages/components/src/components/divider/divider.styles.ts @@ -0,0 +1,157 @@ +import { css } from 'lit'; +import { hostFitContentStyles } from '../../utils/styles'; + +/** + * Divider component styles + */ +const styles = [ + hostFitContentStyles, + /* Host styles */ + css` + :host { + --mdc-divider-background-color: var(--mds-color-theme-outline-secondary-normal); + --mdc-divider-width: 0.0625rem; + --mdc-divider-horizontal-gradient: var(--mds-color-theme-gradientdivider-default-normal); + --mdc-divider-vertical-gradient: var(--mds-color-theme-gradientdivider-vertical-normal); + --mdc-divider-text-size: var(--mds-font-size-body-midsize); + --mdc-divider-text-color: var(--mds-color-theme-text-secondary-normal); + --mdc-divider-text-line-height: var(--mds-font-lineheight-body-midsize); + --mdc-divider-text-margin: 1.5rem; + --mdc-divider-grabber-button-border-radius: 0.5rem; + + display: flex; + justify-content: center; + } + + /* Primary and grabber divider styles */ + :host([data-type='mdc-primary-divider']), + :host([data-type='mdc-grabber-divider']) { + background-color: var(--mdc-divider-background-color); + } + + /* Orientation-specific styles */ + :host([orientation='horizontal']) { + flex-direction: row; + height: var(--mdc-divider-width); + width: 100%; + } + + :host([orientation='vertical']:not([data-type='mdc-text-divider'])) { + flex-direction: column; + height: 100%; + width: var(--mdc-divider-width); + } + + /* Gradient styles for primary and grabber dividers */ + :host([orientation='horizontal'][variant='gradient'][data-type='mdc-primary-divider']), + :host([orientation='horizontal'][variant='gradient'][data-type='mdc-grabber-divider']) { + background: var(--mdc-divider-horizontal-gradient); + } + + :host([orientation='vertical'][variant='gradient'][data-type='mdc-primary-divider']), + :host([orientation='vertical'][variant='gradient'][data-type='mdc-grabber-divider']) { + background: var(--mdc-divider-vertical-gradient); + } + + /* Hiding slotted content for primary dividers */ + :host([data-type='mdc-primary-divider']) ::slotted(*) { + display: none; + } + + /** Button divider styles */ + :host([orientation='vertical']) ::slotted(mdc-button) { + width: 1.25rem; + height: 2.5rem; + border-radius: 0 + var(--mdc-divider-grabber-button-border-radius) + var(--mdc-divider-grabber-button-border-radius) + 0; + } + + :host([orientation='horizontal']) ::slotted(mdc-button) { + height: 1.25rem; + width: 2.5rem; + border-radius: 0 + 0 + var(--mdc-divider-grabber-button-border-radius) + var(--mdc-divider-grabber-button-border-radius); + } + + :host([orientation='horizontal'][button-position='positive']), + :host([orientation='vertical'][button-position='negative']) { + align-items: end; + } + + :host([orientation='horizontal'][button-position='negative']), + :host([orientation='vertical'][button-position='positive']) { + align-items: start; + } + + :host([orientation='horizontal'][button-position='positive']) ::slotted(mdc-button) { + border-radius: var(--mdc-divider-grabber-button-border-radius) + var(--mdc-divider-grabber-button-border-radius) + 0 + 0; + border-bottom-color: transparent; + } + + :host([orientation='horizontal'][button-position='negative']) ::slotted(mdc-button) { + border-top-color: transparent; + } + + :host([orientation='vertical'][button-position='negative']:dir(ltr)) ::slotted(mdc-button), + :host([orientation='vertical'][button-position='negative']:dir(rtl)) ::slotted(mdc-button) { + border-radius: var(--mdc-divider-grabber-button-border-radius) + 0 + 0 + var(--mdc-divider-grabber-button-border-radius); + border-right-color: transparent; + } + + :host([orientation='vertical'][button-position='positive']:dir(ltr)) ::slotted(mdc-button), + :host([orientation='vertical'][button-position='positive']:dir(rtl)) ::slotted(mdc-button) { + border-left-color: transparent; + } + + :host([orientation='vertical'][button-position='positive']:dir(rtl)) ::slotted(mdc-button) { + border-radius: 0 + var(--mdc-divider-grabber-button-border-radius) + var(--mdc-divider-grabber-button-border-radius) + 0; + transform: rotate(180deg); + } + + :host([orientation='vertical'][button-position='negative']:dir(rtl)) ::slotted(mdc-button) { + transform: rotate(180deg); + } + + /** Text divider styles */ + :host([orientation='horizontal'][variant='gradient'][data-type='mdc-text-divider']), + :host([orientation='horizontal'][variant='solid'][data-type='mdc-text-divider']) { + align-items: center; + } + + :host([data-type='mdc-text-divider']) > div { + width: 100%; + height: 100%; + background-color: var(--mdc-divider-background-color); + } + + :host([orientation='horizontal'][variant='gradient'][data-type='mdc-text-divider']) > div:first-of-type { + background: linear-gradient(to right, transparent, 30%, var(--mdc-divider-background-color)); + } + + :host([orientation='horizontal'][variant='gradient'][data-type='mdc-text-divider']) > div:last-of-type { + background: linear-gradient(to left, transparent, 30%, var(--mdc-divider-background-color)); + } + + :host([data-type='mdc-text-divider']) ::slotted(mdc-text) { + margin: 0 var(--mdc-divider-text-margin); + color: var(--mdc-divider-text-color); + font-size: var(--mdc-divider-text-size); + line-height: var(--mdc-divider-text-line-height); + } + `, +]; + +export default styles; diff --git a/packages/components/src/components/divider/divider.types.ts b/packages/components/src/components/divider/divider.types.ts new file mode 100644 index 000000000..28218a92c --- /dev/null +++ b/packages/components/src/components/divider/divider.types.ts @@ -0,0 +1,8 @@ +import type { ValueOf } from '../../utils/types'; +import { DIVIDER_ORIENTATION, DIVIDER_VARIANT, DIRECTIONS } from './divider.constants'; + +type DividerOrientation = ValueOf; +type DividerVariant = ValueOf; +type Directions = ValueOf; + +export { DividerOrientation, DividerVariant, Directions }; diff --git a/packages/components/src/components/divider/index.ts b/packages/components/src/components/divider/index.ts new file mode 100644 index 000000000..9f6555f2c --- /dev/null +++ b/packages/components/src/components/divider/index.ts @@ -0,0 +1,12 @@ +import Divider from './divider.component'; +import { TAG_NAME } from './divider.constants'; + +Divider.register(TAG_NAME); + +declare global { + interface HTMLElementTagNameMap { + ['mdc-divider']: Divider + } +} + +export default Divider;