diff --git a/.changeset/violet-goats-kick.md b/.changeset/violet-goats-kick.md new file mode 100644 index 00000000000..a4556c9f210 --- /dev/null +++ b/.changeset/violet-goats-kick.md @@ -0,0 +1,5 @@ +--- +'@shopify/polaris': minor +--- + +Added `size` prop to `Tag` diff --git a/polaris-react/src/components/Tag/Tag.module.scss b/polaris-react/src/components/Tag/Tag.module.scss index f8ec864a1ba..52f4e31e2ce 100644 --- a/polaris-react/src/components/Tag/Tag.module.scss +++ b/polaris-react/src/components/Tag/Tag.module.scss @@ -1,9 +1,9 @@ @import '../../styles/common'; $height: 20px; -$button-size: 20px; .Tag { + position: relative; display: inline-flex; max-width: 100%; align-items: center; @@ -208,3 +208,68 @@ $button-size: 20px; background: var(--p-color-bg-fill-tertiary-active); } } + +.sizeLarge, +.sizeLarge:is(.removable, .linkable) { + min-height: 24px; + padding: 0 var(--p-space-200); +} + +/* stylelint-disable-next-line selector-max-class, selector-max-specificity -- override code above */ +.sizeLarge .Link.segmented::after { + margin-right: 0; +} + +.sizeLarge .Button { + opacity: 0; + position: absolute; + right: var(--p-space-050); + left: auto; + width: 20px; + height: 20px; + margin: 0; + background-color: var(--p-color-bg-fill-tertiary); + + &:hover { + color: var(--p-color-icon-secondary-hover); + } + + &:active, + &:focus { + color: var(--p-color-icon-secondary-active); + } +} + +.sizeLarge:hover .Button, +.sizeLarge .Button:focus-visible { + opacity: 1; +} + +.sizeLarge:hover .overlay { + position: absolute; + top: 0; + right: 20px; + bottom: 0; + width: 12px; + pointer-events: none; + background: linear-gradient( + to left, + var(--p-color-bg-fill-tertiary) 0%, + transparent 100% + ); +} +/* stylelint-disable-next-line selector-max-class -- match tag hover color */ +.sizeLarge.removable.linkable { + /* stylelint-disable-next-line selector-max-class, selector-max-specificity -- match tag hover color */ + .Button { + background-color: var(--p-color-bg-fill-tertiary-hover); + } + /* stylelint-disable-next-line selector-max-class, selector-max-specificity -- match tag hover color */ + &:hover .overlay { + background: linear-gradient( + to left, + var(--p-color-bg-fill-tertiary-hover) 0%, + transparent 100% + ); + } +} diff --git a/polaris-react/src/components/Tag/Tag.stories.tsx b/polaris-react/src/components/Tag/Tag.stories.tsx index b2d2df35fdb..c16e5017403 100644 --- a/polaris-react/src/components/Tag/Tag.stories.tsx +++ b/polaris-react/src/components/Tag/Tag.stories.tsx @@ -1,12 +1,47 @@ import React, {useCallback, useState} from 'react'; import type {ComponentMeta} from '@storybook/react'; -import {InlineStack, Icon, LegacyStack, Tag, Bleed} from '@shopify/polaris'; +import { + InlineStack, + Icon, + LegacyStack, + Tag, + Bleed, + BlockStack, + Text, +} from '@shopify/polaris'; import {WandIcon} from '@shopify/polaris-icons'; export default { component: Tag, } as ComponentMeta; +export function All() { + return ( + + Default + +
+ Removable + +
+ Clickable + +
+ With Link + +
+ With Custom Content + +
+ Removable with Link + +
+ Removable large + +
+ ); +} + export function Default() { return ( @@ -101,3 +136,42 @@ export function RemovableWithLink() { return {tagMarkup}; } + +export function RemovableLarge() { + const [selectedTags, setSelectedTags] = useState([ + 'Rustic', + 'Antique', + 'Vinyl', + 'Refurbished', + ]); + + const removeTag = useCallback( + (tag) => () => { + setSelectedTags((previousTags) => + previousTags.filter((previousTag) => previousTag !== tag), + ); + }, + [], + ); + + const tagMarkup = selectedTags.map((option) => ( + + {option} + + )); + + const tagWithLinkMarkup = selectedTags.map((option) => ( + + {option} + + )); + + return ( + + Large + {tagMarkup} + Large with link + {tagWithLinkMarkup} + + ); +} diff --git a/polaris-react/src/components/Tag/Tag.tsx b/polaris-react/src/components/Tag/Tag.tsx index ae9c193b237..6bc784318ee 100644 --- a/polaris-react/src/components/Tag/Tag.tsx +++ b/polaris-react/src/components/Tag/Tag.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {XSmallIcon} from '@shopify/polaris-icons'; -import {classNames} from '../../utilities/css'; +import {classNames, variationName} from '../../utilities/css'; import {useI18n} from '../../utilities/i18n'; import {Icon} from '../Icon'; import {handleMouseUpByBlurring} from '../../utilities/focus'; @@ -21,6 +21,8 @@ export interface NonMutuallyExclusiveProps { accessibilityLabel?: string; /** Url to navigate to when tag is clicked or keypressed. */ url?: string; + /** The size of the tag */ + size?: 'large'; } export type TagProps = NonMutuallyExclusiveProps & @@ -36,6 +38,7 @@ export function Tag({ onRemove, accessibilityLabel, url, + size, }: TagProps) { const i18n = useI18n(); @@ -47,6 +50,7 @@ export function Tag({ onRemove && styles.removable, url && !disabled && styles.linkable, segmented && styles.segmented, + size && styles[variationName('size', size)], ); if (onClick) { @@ -104,6 +108,7 @@ export function Tag({ return ( {tagContent} + {size === 'large' && } {removeButton} ); diff --git a/polaris.shopify.com/content/components/selection-and-input/tag.mdx b/polaris.shopify.com/content/components/selection-and-input/tag.mdx index dbc5853652c..3001b190d67 100644 --- a/polaris.shopify.com/content/components/selection-and-input/tag.mdx +++ b/polaris.shopify.com/content/components/selection-and-input/tag.mdx @@ -28,6 +28,9 @@ examples: - fileName: tag-removable-with-link.tsx title: Removable with link description: A removable attribute to an object that allows merchants to navigate to a resource. + - fileName: tag-removable-large.tsx + title: Removable large + description: A larger, removable attribute to an object that allows merchants to navigate to a resource. previewImg: /images/components/selection-and-input/tag.png --- diff --git a/polaris.shopify.com/pages/examples/tag-removable-large.tsx b/polaris.shopify.com/pages/examples/tag-removable-large.tsx new file mode 100644 index 00000000000..9fca8445e2a --- /dev/null +++ b/polaris.shopify.com/pages/examples/tag-removable-large.tsx @@ -0,0 +1,49 @@ +import {Tag, LegacyStack, Text, BlockStack, Card} from '@shopify/polaris'; +import {useState, useCallback} from 'react'; +import {withPolarisExample} from '../../src/components/PolarisExampleWrapper'; + +export function RemovableLarge() { + const [selectedTags, setSelectedTags] = useState([ + 'Rustic', + 'Antique', + 'Vinyl', + 'Refurbished', + ]); + + const removeTag = useCallback( + (tag: string) => () => { + setSelectedTags((previousTags) => + previousTags.filter((previousTag) => previousTag !== tag), + ); + }, + [], + ); + + const tagMarkup = selectedTags.map((option) => ( + + {option} + + )); + + const tagWithLinkMarkup = selectedTags.map((option) => ( + + {option} + + )); + + return ( + + + Large + {tagMarkup} + + + + Large with link + {tagWithLinkMarkup} + + + ); +} + +export default withPolarisExample(RemovableLarge);