diff --git a/src/components/link/link-story.ts b/src/components/link/link-story.ts index fb49d41ab..e2895d24b 100644 --- a/src/components/link/link-story.ts +++ b/src/components/link/link-story.ts @@ -1,7 +1,7 @@ /** * @license * - * Copyright IBM Corp. 2019, 2021 + * Copyright IBM Corp. 2019, 2022 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -16,7 +16,7 @@ import { boolean, select } from '@storybook/addon-knobs'; import Download16 from 'carbon-web-components/es/icons/download/16'; import textNullable from '../../../.storybook/knob-text-nullable'; import ifNonNull from '../../globals/directives/if-non-null'; -import { LINK_SIZE } from './link'; +import { LINK_SIZE, ICON_PLACEMENT } from './link'; import storyDocs from './link-story.mdx'; const sizes = { @@ -25,6 +25,11 @@ const sizes = { [`Large size (${LINK_SIZE.LARGE})`]: LINK_SIZE.LARGE, }; +const placementTypes = { + [`${ICON_PLACEMENT.LEFT}`]: ICON_PLACEMENT.LEFT, + [`${ICON_PLACEMENT.RIGHT}`]: ICON_PLACEMENT.RIGHT, +}; + export const Default = args => { const { disabled, download, href, hreflang, linkRole, ping, rel, size, target, type, onClick } = args?.['bx-link'] ?? {}; return html` @@ -48,13 +53,15 @@ export const Default = args => { Default.storyName = 'Default'; export const pairedWithIcon = args => { - const { disabled, download, href, hreflang, linkRole, ping, rel, size, target, type, onClick } = args?.['bx-link'] ?? {}; + const { disabled, download, href, hreflang, iconPlacement, linkRole, ping, rel, size, target, type, onClick } = + args?.['bx-link-with-icon'] ?? {}; return html` { `; }; +pairedWithIcon.parameters = { + knobs: { + 'bx-link-with-icon': () => ({ + iconPlacement: select('Icon Position (icon-placement):', placementTypes, placementTypes[`${ICON_PLACEMENT.RIGHT}`]), + }), + }, +}; + export default { title: 'Components/Link', parameters: { diff --git a/src/components/link/link.scss b/src/components/link/link.scss index a8019d326..a4b4ddfc5 100644 --- a/src/components/link/link.scss +++ b/src/components/link/link.scss @@ -1,5 +1,5 @@ // -// Copyright IBM Corp. 2019, 2021 +// Copyright IBM Corp. 2019, 2022 // // This source code is licensed under the Apache-2.0 license found in the // LICENSE file in the root directory of this source tree. @@ -20,4 +20,24 @@ $css--plex: true !default; .#{$prefix}--link__icon[hidden] { display: none; } + + &.#{$prefix}--link-with-icon__icon-left, + .#{$prefix}--link-with-icon.#{$prefix}--link-with-icon--inline-icon.#{$prefix}--link-with-icon__icon-left { + display: flex; + justify-content: flex-end; + flex-direction: row-reverse; + + .#{$prefix}--link__icon { + margin-left: 0; + } + + svg, + ::slotted(svg[slot='icon']) { + align-self: start; + position: relative; + margin-left: 0; + margin-right: $carbon--spacing-03; + top: 1px; + } + } } diff --git a/src/components/link/link.ts b/src/components/link/link.ts index da8d27e67..6b3f4cbeb 100644 --- a/src/components/link/link.ts +++ b/src/components/link/link.ts @@ -1,7 +1,7 @@ /** * @license * - * Copyright IBM Corp. 2019, 2021 + * Copyright IBM Corp. 2019, 2022 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -10,10 +10,13 @@ import { classMap } from 'lit-html/directives/class-map'; import { html, property, customElement, LitElement, query } from 'lit-element'; import settings from 'carbon-components/es/globals/js/settings'; +import { ICON_PLACEMENT } from '../../globals/defs'; import ifNonNull from '../../globals/directives/if-non-null'; import FocusMixin from '../../globals/mixins/focus'; import styles from './link.scss'; +export { ICON_PLACEMENT }; + const { prefix } = settings; /** @@ -149,6 +152,18 @@ class BXLink extends FocusMixin(LitElement) { @property({ reflect: true }) hreflang!: string; + /** + * Icon placement(right (default) | left) + */ + @property({ attribute: 'icon-placement', reflect: true }) + iconPlacement = ICON_PLACEMENT.RIGHT; + + /** + * Positions the icon inline with text when `true` + */ + @property({ type: Boolean }) + iconInline = true; + /** * The a11y role for ``. */ @@ -192,6 +207,22 @@ class BXLink extends FocusMixin(LitElement) { }); } + updated() { + const { iconInline, iconPlacement, _linkNode: linkNode } = this; + if (linkNode) { + linkNode.classList.add(`${prefix}--link-with-icon`); + linkNode.classList.toggle(`${prefix}--link-with-icon__icon-${ICON_PLACEMENT.LEFT}`, iconPlacement === ICON_PLACEMENT.LEFT); + linkNode.classList.toggle( + `${prefix}--link-with-icon__icon-${ICON_PLACEMENT.RIGHT}`, + iconPlacement === ICON_PLACEMENT.RIGHT + ); + + if (iconInline && iconPlacement === ICON_PLACEMENT.RIGHT) { + linkNode.classList.add(`${prefix}--link-with-icon--inline-icon`); + } + } + } + render() { const { disabled } = this; return disabled ? this._renderDisabledLink() : this._renderLink(); diff --git a/src/globals/defs.ts b/src/globals/defs.ts new file mode 100644 index 000000000..993d2427b --- /dev/null +++ b/src/globals/defs.ts @@ -0,0 +1,23 @@ +/** + * @license + * + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * Icon Placement. + */ +export enum ICON_PLACEMENT { + /** + * left of footer copy + */ + LEFT = 'left', + + /** + * right of footer copy + */ + RIGHT = 'right', +}