diff --git a/.changeset/warm-buckets-fold.md b/.changeset/warm-buckets-fold.md new file mode 100644 index 00000000000..fcdea09d996 --- /dev/null +++ b/.changeset/warm-buckets-fold.md @@ -0,0 +1,28 @@ +--- +"@hashicorp/design-system-components": minor +--- + +# Interactive +- Introduced `` (a generic, "utility" component used internally by all the interactive elements like buttons and links) + +# Button +- updated the button API to handle also links as ``/`` + - it can be used in place of the `` component (see below) + - when the button is a link + - the text is underlined for differentiation with a normal button - ⚠️ **Visual change!** + - the button responds to `space` key event +- removed the `@type` argument from the API in favour of the `type` native attribute - 🚨 **Breaking change!** + +# Link/LinkTo::CTA +- removed the `` component, in favour of `` component (see above) - 🚨 **Breaking change!** + +# Link::Inline +- added the `` component (with API very similar to the ``) + +# Dropdown +- Updated the `Dropdown::ListItem::Interactive` to use the new `` component + +# Alert/Toast components +- Removed the `` action (now you can use directly ``) + + diff --git a/packages/components/addon/components/hds/alert/index.hbs b/packages/components/addon/components/hds/alert/index.hbs index ec5d0e8926e..7ff941c3fc4 100644 --- a/packages/components/addon/components/hds/alert/index.hbs +++ b/packages/components/addon/components/hds/alert/index.hbs @@ -14,9 +14,7 @@
{{yield (hash - Button=(component "hds/button" size="small") - Link::Standalone=(component "hds/link/standalone" size="small") - LinkTo::Standalone=(component "hds/link-to/standalone" size="small") + Button=(component "hds/button" size="small") Link::Standalone=(component "hds/link/standalone" size="small") ) }}
diff --git a/packages/components/addon/components/hds/button/index.hbs b/packages/components/addon/components/hds/button/index.hbs index 798090db3df..7d438de2110 100644 --- a/packages/components/addon/components/hds/button/index.hbs +++ b/packages/components/addon/components/hds/button/index.hbs @@ -1,4 +1,16 @@ - \ No newline at end of file +
\ No newline at end of file diff --git a/packages/components/addon/components/hds/button/index.js b/packages/components/addon/components/hds/button/index.js index 56db744c4c6..1069168b2a4 100644 --- a/packages/components/addon/components/hds/button/index.js +++ b/packages/components/addon/components/hds/button/index.js @@ -3,11 +3,9 @@ import { assert } from '@ember/debug'; export const DEFAULT_SIZE = 'medium'; export const DEFAULT_COLOR = 'primary'; -export const DEFAULT_TYPE = 'button'; export const DEFAULT_ICONPOSITION = 'leading'; export const SIZES = ['small', 'medium', 'large']; export const COLORS = ['primary', 'secondary', 'tertiary', 'critical']; -export const TYPES = ['button', 'submit', 'reset']; export const ICONPOSITIONS = ['leading', 'trailing']; export default class HdsButtonIndexComponent extends Component { @@ -126,25 +124,6 @@ export default class HdsButtonIndexComponent extends Component { } } - /** - * @param type - * @type {string} - * @default button - * @description The value for the button's `type` attribute. Acceptable values are `button`, `submit`, and `reset` - */ - get type() { - let { type = DEFAULT_TYPE } = this.args; - - assert( - `@type for "Hds::Button" must be one of the following: ${TYPES.join( - ', ' - )}; received: ${type}`, - TYPES.includes(type) - ); - - return type; - } - /** * @param isFullWidth * @type {boolean} diff --git a/packages/components/addon/components/hds/dropdown/list-item/interactive.hbs b/packages/components/addon/components/hds/dropdown/list-item/interactive.hbs index 832b7a521e9..16be60ecf18 100644 --- a/packages/components/addon/components/hds/dropdown/list-item/interactive.hbs +++ b/packages/components/addon/components/hds/dropdown/list-item/interactive.hbs @@ -1,43 +1,22 @@
  • - {{#if @route}} - - {{#if @icon}} -
    - -
    - {{/if}} -
    - {{this.text}} + + {{#if @icon}} +
    +
    - - {{else if @href}} -
    - {{#if @icon}} -
    - -
    - {{/if}} -
    - {{this.text}} -
    -
    - {{else}} - - {{/if}} + {{/if}} +
    + {{this.text}} +
    +
  • \ No newline at end of file diff --git a/packages/components/addon/components/hds/interactive/index.hbs b/packages/components/addon/components/hds/interactive/index.hbs new file mode 100644 index 00000000000..69943383e6a --- /dev/null +++ b/packages/components/addon/components/hds/interactive/index.hbs @@ -0,0 +1,33 @@ +{{! IMPORTANT: we removed the newlines before/after the yield to reduce the issues with unexpected whitespaces (see https://github.com/hashicorp/design-system/pull/231#issuecomment-1123502499) }} +{{! NOTICE: we can't support the direct use of the "href" HTML attribute via ...attributes in the elements, because we need to rely on the "@href" Ember argument to differentiate between different types of generated output }} +{{#if @route}} + {{#if this.isRouteExternal}} + {{yield}} + {{else}} + {{yield}} + {{/if}} +{{else if @href}} + {{#if this.isHrefExternal}} + {{yield}} + {{else}} + {{yield}} + {{/if}} +{{else}} + +{{/if}} \ No newline at end of file diff --git a/packages/components/addon/components/hds/interactive/index.js b/packages/components/addon/components/hds/interactive/index.js new file mode 100644 index 00000000000..3b0ae362fbb --- /dev/null +++ b/packages/components/addon/components/hds/interactive/index.js @@ -0,0 +1,33 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +export default class HdsInteractiveComponent extends Component { + /** + * Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer") + * + * @param isHrefExternal + * @type boolean + * @default true + */ + get isHrefExternal() { + return this.args.isHrefExternal ?? true; + } + + /** + * Determines if a @route value is "external" (uses the LinkToExternal component instead of LinkTo) + * + * @param isRouteExternal + * @type boolean + * @default false + */ + get isRouteExternal() { + return this.args.isRouteExternal ?? false; + } + + @action + onKeyUp(event) { + if (event.key === ' ' || event.code === 'Space') { + event.target.click(); + } + } +} diff --git a/packages/components/addon/components/hds/link-to/cta.hbs b/packages/components/addon/components/hds/link-to/cta.hbs deleted file mode 100644 index a47743d34d5..00000000000 --- a/packages/components/addon/components/hds/link-to/cta.hbs +++ /dev/null @@ -1,51 +0,0 @@ -{{! -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// -// Notice: in this component we're using directly the styles from the `Hds::Button` component -// using the `hds-button` class names (and adding a specialized class for the "cta", see below) -// If you need to change the styling of the `Button` component, remember that this will impact also -// this component too. -// If instead you need to change only the styling of the `CTA` component, you can do it -// in the CSS file using the specialized class declared there. -// This is NOT a standard approach that we use in the HDS design system implementation, but it's been -// the least worst option we could find to solve the problem of sharing the exact same style of the -// `Button (primary)` with other components. -}} - - - {{#if this.icon}} - {{#if (eq this.iconPosition "leading")}} -
    - -
    -
    - {{this.text}} -
    - {{else}} -
    - {{this.text}} -
    -
    - -
    - {{/if}} - {{else}} -
    - {{this.text}} -
    - {{/if}} -
    \ No newline at end of file diff --git a/packages/components/addon/components/hds/link-to/cta.js b/packages/components/addon/components/hds/link-to/cta.js deleted file mode 100644 index a9ed2ad5948..00000000000 --- a/packages/components/addon/components/hds/link-to/cta.js +++ /dev/null @@ -1,165 +0,0 @@ -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// -// Notice: in this component we're using directly the styles from the `Hds::Button` component -// using the `hds-button` class names (and adding a specialized class for the "cta", see below) -// If you need to change the styling of the `Button` component, remember that this will impact also -// this component too. -// If instead you need to change only the styling of the `CTA` component, you can do it -// in the CSS file using the specialized class declared there. -// This is NOT a standard approach that we use in the HDS design system implementation, but it's been -// the least worst option we could find to solve the problem of sharing the exact same style of the -// `Button (primary)` with other components. - -import Component from '@glimmer/component'; -import { assert } from '@ember/debug'; -import { action } from '@ember/object'; - -export const DEFAULT_SIZE = 'medium'; -export const DEFAULT_ICONPOSITION = 'leading'; -export const SIZES = ['small', 'medium', 'large']; -export const ICONPOSITIONS = ['leading', 'trailing']; - -export default class HdsLinkToCtaComponent extends Component { - /** - * @param text - * @type {string} - * @description The text of the component. If no text value is defined an error will be thrown. - */ - get text() { - let { text } = this.args; - - assert( - '@text for "Hds::LinkTo::Cta" must have a valid value', - text !== undefined - ); - - return text; - } - - /** - * @param size - * @type {string} - * @default medium - * @description The size of the component; acceptable values are `small`, `medium`, and `large` - */ - get size() { - let { size = DEFAULT_SIZE } = this.args; - - assert( - `@size for "Hds::LinkTo::Cta" must be one of the following: ${SIZES.join( - ', ' - )}; received: ${size}`, - SIZES.includes(size) - ); - - return size; - } - - /** - * @param icon - * @type {string} - * @default null - * @description The name of the icon to be used. - */ - get icon() { - return this.args.icon ?? null; - } - - /** - * @param iconPosition - * @type {string} - * @default leading - * @description Positions the icon before or after the text; allowed values are `leading` or `trailing` - */ - get iconPosition() { - let { iconPosition = DEFAULT_ICONPOSITION } = this.args; - - assert( - `@iconPosition for "Hds::LinkTo::Cta" must be one of the following: ${ICONPOSITIONS.join( - ', ' - )}; received: ${iconPosition}`, - ICONPOSITIONS.includes(iconPosition) - ); - - return iconPosition; - } - - /** - * @param iconSize - * @type {string} - * @default 16 - * @description ensures that the correct icon size is used. Automatically calculated. - */ - get iconSize() { - if (this.args.size === 'large') { - return '24'; - } else { - return '16'; - } - } - - /** - * @param isFullWidth - * @type {boolean} - * @default false - * @description Indicates that the component should take up the full width of the parent container. The default is false. - */ - get isFullWidth() { - return this.args.isFullWidth ?? false; - } - - /** - * @param route - * @type {string|null} - * @description Checks to make sure route is defined. - */ - get route() { - let { route } = this.args; - assert( - '@route must be defined for "Hds::LinkTo::Cta"', - route !== undefined - ); - - return route; - } - - /** - * Get the class names to apply to the component. - * @method classNames - * @return {string} The "class" attribute to apply to the component. - */ - get classNames() { - let classes = [ - 'hds-button', - 'hds-button--color-primary', - 'hds-link-cta--inherit-button-styles', - ]; - - // add a class based on the @size argument - classes.push(`hds-button--size-${this.size}`); - - // add a class based on the @isFullWidth argument - if (this.isFullWidth) { - classes.push('hds-button--width-full'); - } - - return classes.join(' '); - } - - @action - didInsert(el) { - // we need to register the element to compare it with the one that triggered the "key/space" event - this.el = el; - } - - @action - onKeySpace(event) { - if (event.target === this.el) { - event.target.click(); - } - } -} diff --git a/packages/components/addon/components/hds/link-to/standalone.hbs b/packages/components/addon/components/hds/link-to/standalone.hbs deleted file mode 100644 index 862b19fcbd9..00000000000 --- a/packages/components/addon/components/hds/link-to/standalone.hbs +++ /dev/null @@ -1,25 +0,0 @@ - - {{#if (eq this.iconPosition "leading")}} - - - {{else}} - - - {{/if}} - \ No newline at end of file diff --git a/packages/components/addon/components/hds/link-to/standalone.js b/packages/components/addon/components/hds/link-to/standalone.js deleted file mode 100644 index d7238b9e647..00000000000 --- a/packages/components/addon/components/hds/link-to/standalone.js +++ /dev/null @@ -1,151 +0,0 @@ -import Component from '@glimmer/component'; -import { assert } from '@ember/debug'; - -export const DEFAULT_ICONPOSITION = 'leading'; -export const DEFAULT_COLOR = 'primary'; -export const DEFAULT_SIZE = 'medium'; -export const ICONPOSITIONS = ['leading', 'trailing']; -export const COLORS = ['primary', 'secondary']; -export const SIZES = ['small', 'medium', 'large']; - -export default class HdsLinkToStandaloneComponent extends Component { - /** - * @param text - * @type {string} - * @description The text of the link. If no text value is defined an error will be thrown. - */ - get text() { - let { text } = this.args; - - assert( - '@text for "Hds::LinkTo::Standalone" must have a valid value', - text !== undefined - ); - - return text; - } - - /** - * @param route - * @type {string|null} - * @description Checks to make sure route is defined. - */ - get route() { - let { route } = this.args; - assert( - '@route must be defined for "Hds::LinkTo::Standalone"', - route !== undefined - ); - - return route; - } - - /** - * @param color - * @type {string} - * @default primary - * @description Determines the color of link to be used; acceptable values are `primary` and `secondary` - */ - get color() { - let { color = DEFAULT_COLOR } = this.args; - - assert( - `@color for "Hds::LinkTo::Standalone" must be one of the following: ${COLORS.join( - ', ' - )}; received: ${color}`, - COLORS.includes(color) - ); - - return color; - } - - /** - * @param icon - * @type {string|null} - * @default null - * @description The name of the icon to be used. An icon name must be defined. - */ - get icon() { - let { icon } = this.args; - - assert( - '@icon for "Hds::LinkTo::Standalone" must have a valid value', - icon !== undefined - ); - - return icon; - } - - /** - * @param iconPosition - * @type {string} - * @default leading - * @description Positions the icon before or after the text; allowed values are `leading` or `trailing` - */ - get iconPosition() { - let { iconPosition = DEFAULT_ICONPOSITION } = this.args; - - assert( - `@iconPosition for "Hds::LinkTo::Standalone" must be one of the following: ${ICONPOSITIONS.join( - ', ' - )}; received: ${iconPosition}`, - ICONPOSITIONS.includes(iconPosition) - ); - - return iconPosition; - } - - /** - * @param size - * @type {string} - * @default medium - * @description The size of the standalone link; acceptable values are `small`, `medium`, and `large` - */ - get size() { - let { size = DEFAULT_SIZE } = this.args; - - assert( - `@size for "Hds::LinkTo::Standalone" must be one of the following: ${SIZES.join( - ', ' - )}; received: ${size}`, - SIZES.includes(size) - ); - - return size; - } - - /** - * @param iconSize - * @type {string} - * @default 16 - * @description ensures that the correct icon size is used. Automatically calculated. - */ - get iconSize() { - if (this.args.size === 'large') { - return '24'; - } else { - return '16'; - } - } - - /** - * Get the class names to apply to the component. - * @method LinkToStandalone#classNames - * @return {string} The "class" attribute to apply to the component. - */ - get classNames() { - // Notice: we've left this class name the same as the hds::link::standalone (we didn't add the "-to") so we didn't have to replicate the CSS - let classes = ['hds-link-standalone']; - - // add a class based on the @size argument - classes.push(`hds-link-standalone--size-${this.size}`); - - // add a class based on the @color argument - classes.push(`hds-link-standalone--color-${this.color}`); - - // add a class based on the @iconPosition argument - classes.push(`hds-link-standalone--icon-position-${this.iconPosition}`); - - return classes.join(' '); - } -} diff --git a/packages/components/addon/components/hds/link/cta.hbs b/packages/components/addon/components/hds/link/cta.hbs deleted file mode 100644 index 5959fe9ea4f..00000000000 --- a/packages/components/addon/components/hds/link/cta.hbs +++ /dev/null @@ -1,50 +0,0 @@ -{{! -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// -// Notice: in this component we're using directly the styles from the `Hds::Button` component -// using the `hds-button` class names (and adding a specialized class for the "cta", see below) -// If you need to change the styling of the `Button` component, remember that this will impact also -// this component too. -// If instead you need to change only the styling of the `CTA` component, you can do it -// in the CSS file using the specialized class declared there. -// This is NOT a standard approach that we use in the HDS design system implementation, but it's been -// the least worst option we could find to solve the problem of sharing the exact same style of the -// `Button (primary)` with other components. -}} - -{{! template-lint-disable link-href-attributes }} -{{! we can disable this linting rule because the developer will add the html attribute themselves }} - - {{#if this.icon}} - {{#if (eq this.iconPosition "leading")}} -
    - -
    -
    - {{this.text}} -
    - {{else}} -
    - {{this.text}} -
    -
    - -
    - {{/if}} - {{else}} -
    - {{this.text}} -
    - {{/if}} -
    \ No newline at end of file diff --git a/packages/components/addon/components/hds/link/cta.js b/packages/components/addon/components/hds/link/cta.js deleted file mode 100644 index a1370e2c37b..00000000000 --- a/packages/components/addon/components/hds/link/cta.js +++ /dev/null @@ -1,150 +0,0 @@ -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ -// β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ -// β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ -// -// Notice: in this component we're using directly the styles from the `Hds::Button` component -// using the `hds-button` class names (and adding a specialized class for the "cta", see below) -// If you need to change the styling of the `Button` component, remember that this will impact also -// this component too. -// If instead you need to change only the styling of the `CTA` component, you can do it -// in the CSS file using the specialized class declared there. -// This is NOT a standard approach that we use in the HDS design system implementation, but it's been -// the least worst option we could find to solve the problem of sharing the exact same style of the -// `Button (primary)` with other components. - -import Component from '@glimmer/component'; -import { assert } from '@ember/debug'; -import { action } from '@ember/object'; - -export const DEFAULT_SIZE = 'medium'; -export const DEFAULT_ICONPOSITION = 'leading'; -export const SIZES = ['small', 'medium', 'large']; -export const ICONPOSITIONS = ['leading', 'trailing']; - -export default class HdsLinkCtaComponent extends Component { - /** - * @param text - * @type {string} - * @description The text of the component. If no text value is defined an error will be thrown. - */ - get text() { - let { text } = this.args; - - assert( - '@text for "Hds::Link::Cta" must have a valid value', - text !== undefined - ); - - return text; - } - - /** - * @param size - * @type {string} - * @default medium - * @description The size of the component; acceptable values are `small`, `medium`, and `large` - */ - get size() { - let { size = DEFAULT_SIZE } = this.args; - - assert( - `@size for "Hds::Link::Cta" must be one of the following: ${SIZES.join( - ', ' - )}; received: ${size}`, - SIZES.includes(size) - ); - - return size; - } - - /** - * @param icon - * @type {string} - * @default null - * @description The name of the icon to be used. - */ - get icon() { - return this.args.icon ?? null; - } - - /** - * @param iconPosition - * @type {string} - * @default leading - * @description Positions the icon before or after the text; allowed values are `leading` or `trailing` - */ - get iconPosition() { - let { iconPosition = DEFAULT_ICONPOSITION } = this.args; - - assert( - `@iconPosition for "Hds::Link::Cta" must be one of the following: ${ICONPOSITIONS.join( - ', ' - )}; received: ${iconPosition}`, - ICONPOSITIONS.includes(iconPosition) - ); - - return iconPosition; - } - - /** - * @param iconSize - * @type {string} - * @default 16 - * @description ensures that the correct icon size is used. Automatically calculated. - */ - get iconSize() { - if (this.args.size === 'large') { - return '24'; - } else { - return '16'; - } - } - - /** - * @param isFullWidth - * @type {boolean} - * @default false - * @description Indicates that the component should take up the full width of the parent container. The default is false. - */ - get isFullWidth() { - return this.args.isFullWidth ?? false; - } - - /** - * Get the class names to apply to the component. - * @method classNames - * @return {string} The "class" attribute to apply to the component. - */ - get classNames() { - let classes = [ - 'hds-button', - 'hds-button--color-primary', - 'hds-link-cta--inherit-button-styles', - ]; - - // add a class based on the @size argument - classes.push(`hds-button--size-${this.size}`); - - // add a class based on the @isFullWidth argument - if (this.isFullWidth) { - classes.push('hds-button--width-full'); - } - - return classes.join(' '); - } - - @action - didInsert(el) { - // we need to register the element to compare it with the one that triggered the "key/space" event - this.el = el; - } - - @action - onKeySpace(event) { - if (event.target === this.el) { - event.target.click(); - } - } -} diff --git a/packages/components/addon/components/hds/link/inline.hbs b/packages/components/addon/components/hds/link/inline.hbs new file mode 100644 index 00000000000..e641bbd62f0 --- /dev/null +++ b/packages/components/addon/components/hds/link/inline.hbs @@ -0,0 +1,23 @@ +{{! IMPORTANT: we removed the newlines before/after the yield to reduce the issues with unexpected whitespaces (see https://github.com/hashicorp/design-system/pull/231#issuecomment-1123502499) }} +{{! IMPORTANT: we need to add "squishies" here (~) because otherwise the whitespace added by Ember becomes visible in the link (being an inline element) - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }} +{{#if (and @icon (eq this.iconPosition "leading"))~}} + + + + {{~/if~}}{{yield}}{{~#if (and @icon (eq this.iconPosition "trailing"))~}} + + + + {{~/if}} \ No newline at end of file diff --git a/packages/components/addon/components/hds/link/inline.js b/packages/components/addon/components/hds/link/inline.js new file mode 100644 index 00000000000..31af27dcbb3 --- /dev/null +++ b/packages/components/addon/components/hds/link/inline.js @@ -0,0 +1,71 @@ +import Component from '@glimmer/component'; +import { assert } from '@ember/debug'; + +export const DEFAULT_ICONPOSITION = 'trailing'; +export const DEFAULT_COLOR = 'primary'; +export const ICONPOSITIONS = ['leading', 'trailing']; +export const COLORS = ['primary', 'secondary']; + +export default class HdsLinkInlineComponent extends Component { + constructor() { + super(...arguments); + if (!(this.args.href || this.args.route)) { + assert('@href or @route must be defined for '); + } + } + + /** + * @param color + * @type {string} + * @default primary + * @description Determines the color of link to be used; acceptable values are `primary` and `secondary` + */ + get color() { + let { color = DEFAULT_COLOR } = this.args; + + assert( + `@color for "Hds::Link::Inline" must be one of the following: ${COLORS.join( + ', ' + )}; received: ${color}`, + COLORS.includes(color) + ); + + return color; + } + + /** + * @param iconPosition + * @type {string} + * @default leading + * @description Positions the icon before or after the text; allowed values are `leading` or `trailing` + */ + get iconPosition() { + let { iconPosition = DEFAULT_ICONPOSITION } = this.args; + + assert( + `@iconPosition for "Hds::Link::Inline" must be one of the following: ${ICONPOSITIONS.join( + ', ' + )}; received: ${iconPosition}`, + ICONPOSITIONS.includes(iconPosition) + ); + + return iconPosition; + } + + /** + * Get the class names to apply to the component. + * @method LinkInline#classNames + * @return {string} The "class" attribute to apply to the component. + */ + get classNames() { + let classes = ['hds-link-inline']; + + // add a class based on the @color argument + classes.push(`hds-link-inline--color-${this.color}`); + + // add a class based on the @iconPosition argument + classes.push(`hds-link-inline--icon-${this.iconPosition}`); + + return classes.join(' '); + } +} diff --git a/packages/components/addon/components/hds/link/standalone.hbs b/packages/components/addon/components/hds/link/standalone.hbs index be624cc8353..d051d617af0 100644 --- a/packages/components/addon/components/hds/link/standalone.hbs +++ b/packages/components/addon/components/hds/link/standalone.hbs @@ -1,6 +1,17 @@ -{{! template-lint-disable link-href-attributes }} -{{! we can disable this linting rule because the developer will add the html attribute themselves }} - + {{#if (eq this.iconPosition "leading")}} {{/if}} - -{{! template-lint-enable link-href-attributes }} \ No newline at end of file +
    \ No newline at end of file diff --git a/packages/components/addon/components/hds/link/standalone.js b/packages/components/addon/components/hds/link/standalone.js index 715d741795d..4302a52d6aa 100644 --- a/packages/components/addon/components/hds/link/standalone.js +++ b/packages/components/addon/components/hds/link/standalone.js @@ -9,6 +9,13 @@ export const COLORS = ['primary', 'secondary']; export const SIZES = ['small', 'medium', 'large']; export default class HdsLinkStandaloneComponent extends Component { + constructor() { + super(...arguments); + if (!(this.args.href || this.args.route)) { + assert('@href or @route must be defined for '); + } + } + /** * @param text * @type {string} diff --git a/packages/components/addon/components/hds/toast/index.hbs b/packages/components/addon/components/hds/toast/index.hbs index 0331f2b9987..9198e9ea2b2 100644 --- a/packages/components/addon/components/hds/toast/index.hbs +++ b/packages/components/addon/components/hds/toast/index.hbs @@ -8,13 +8,6 @@ as |A| > {{yield - (hash - Title=A.Title - Description=A.Description - Button=A.Button - Link::Standalone=A.Link::Standalone - LinkTo::Standalone=A.LinkTo::Standalone - Generic=A.Generic - ) + (hash Title=A.Title Description=A.Description Button=A.Button Link::Standalone=A.Link::Standalone Generic=A.Generic) }} \ No newline at end of file diff --git a/packages/components/app/components/hds/link/cta.js b/packages/components/app/components/hds/interactive/index.js similarity index 66% rename from packages/components/app/components/hds/link/cta.js rename to packages/components/app/components/hds/interactive/index.js index e17544e4adc..b2ae123b278 100644 --- a/packages/components/app/components/hds/link/cta.js +++ b/packages/components/app/components/hds/interactive/index.js @@ -1 +1 @@ -export { default } from '@hashicorp/design-system-components/components/hds/link/cta'; +export { default } from '@hashicorp/design-system-components/components/hds/interactive/index'; diff --git a/packages/components/app/components/hds/link-to/standalone.js b/packages/components/app/components/hds/link-to/standalone.js deleted file mode 100644 index 04e398cdb1f..00000000000 --- a/packages/components/app/components/hds/link-to/standalone.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@hashicorp/design-system-components/components/hds/link-to/standalone'; diff --git a/packages/components/app/components/hds/link-to/cta.js b/packages/components/app/components/hds/link/inline.js similarity index 71% rename from packages/components/app/components/hds/link-to/cta.js rename to packages/components/app/components/hds/link/inline.js index 5f4607b6aed..4fdc6c175f1 100644 --- a/packages/components/app/components/hds/link-to/cta.js +++ b/packages/components/app/components/hds/link/inline.js @@ -1 +1 @@ -export { default } from '@hashicorp/design-system-components/components/hds/link-to/cta'; +export { default } from '@hashicorp/design-system-components/components/hds/link/inline'; diff --git a/packages/components/app/styles/@hashicorp/design-system-components.scss b/packages/components/app/styles/@hashicorp/design-system-components.scss index 189491ebf11..f8f1d31d3fa 100644 --- a/packages/components/app/styles/@hashicorp/design-system-components.scss +++ b/packages/components/app/styles/@hashicorp/design-system-components.scss @@ -16,7 +16,7 @@ @use "../components/disclosure"; @use "../components/dropdown"; @use "../components/icon-tile"; -@use "../components/link/cta"; +@use "../components/link/inline"; @use "../components/link/standalone"; @use "../components/toast"; // END COMPONENT CSS FILES IMPORTS diff --git a/packages/components/app/styles/components/button.scss b/packages/components/app/styles/components/button.scss index 437cd31a8d9..d04d2247574 100644 --- a/packages/components/app/styles/components/button.scss +++ b/packages/components/app/styles/components/button.scss @@ -26,6 +26,11 @@ $hds-button-focus-border-width: 3px; position: relative; width: auto; + // the element behaves differently than a