diff --git a/packages/big-design/src/components/FeatureTag/FeatureTag.tsx b/packages/big-design/src/components/FeatureTag/FeatureTag.tsx new file mode 100644 index 000000000..fa2705cb6 --- /dev/null +++ b/packages/big-design/src/components/FeatureTag/FeatureTag.tsx @@ -0,0 +1,32 @@ +import { IconProps } from '@bigcommerce/big-design-icons'; +import React, { AnchorHTMLAttributes, FunctionComponent, ReactElement } from 'react'; + +import { StyledFeatureTag, StyledFeatureTagIcon, StyledFeatureTagLabel } from './styled'; + +export interface FeatureTagProps extends AnchorHTMLAttributes { + icon?: ReactElement; + isActive?: boolean; + label: string; +} + +export const FeatureTag: FunctionComponent = ({ + label, + icon, + isActive, + href, + target, +}) => { + return label ? ( + + {icon ? {icon} : null} + {label} + + ) : null; +}; + +FeatureTag.displayName = 'FeatureTag'; diff --git a/packages/big-design/src/components/FeatureTag/__snapshots__/spec.tsx.snap b/packages/big-design/src/components/FeatureTag/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..b5216558f --- /dev/null +++ b/packages/big-design/src/components/FeatureTag/__snapshots__/spec.tsx.snap @@ -0,0 +1,381 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`render feature tag 1`] = ` +.c0 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #ECEEF5; + border-radius: 0.25rem; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + color: #5E637A; + cursor: pointer; + fill: #5E637A; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + font-size: 0.875rem; + gap: 0.25rem; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + line-height: 1.25rem; + max-width: -webkit-fit-content; + max-width: -moz-fit-content; + max-width: fit-content; + outline: none; + padding-block: calc(0.5rem / 4); + padding-inline: 0.5rem; + -webkit-text-decoration: none; + text-decoration: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.c0.active { + background-color: #F0F3FF; + color: #2852EB; + fill: #3C64F4; +} + +.c0:hover, +.c0.active:hover { + background-color: #DBE3FE; + color: #0B38D9; + fill: #3C64F4; +} + +.c0:focus { + outline: 4px solid #DBE3FE; +} + +.c0:active, +.c0.active:active { + background-color: #9EB3FC; + color: #0B38D9; + fill: #0024A6; +} + +.c0:focused:active { + background-color: #F0F3FF; + color: #0B38D9; + fill: #0B38D9; + outline: 4px solid #9EB3FC; +} + +.c1 { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + + + + Feature Tag + + +`; + +exports[`renders as active 1`] = ` +.c2 { + vertical-align: middle; + height: 1.5rem; + width: 1.5rem; +} + +.c0 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #ECEEF5; + border-radius: 0.25rem; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + color: #5E637A; + cursor: pointer; + fill: #5E637A; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + font-size: 0.875rem; + gap: 0.25rem; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + line-height: 1.25rem; + max-width: -webkit-fit-content; + max-width: -moz-fit-content; + max-width: fit-content; + outline: none; + padding-block: calc(0.5rem / 4); + padding-inline: 0.5rem; + -webkit-text-decoration: none; + text-decoration: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.c0.active { + background-color: #F0F3FF; + color: #2852EB; + fill: #3C64F4; +} + +.c0:hover, +.c0.active:hover { + background-color: #DBE3FE; + color: #0B38D9; + fill: #3C64F4; +} + +.c0:focus { + outline: 4px solid #DBE3FE; +} + +.c0:active, +.c0.active:active { + background-color: #9EB3FC; + color: #0B38D9; + fill: #0024A6; +} + +.c0:focused:active { + background-color: #F0F3FF; + color: #0B38D9; + fill: #0B38D9; + outline: 4px solid #9EB3FC; +} + +.c1 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + height: 1.125rem; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + overflow: hidden; + width: 1.125rem; +} + +.c1 > svg { + -webkit-transform: scale(0.75); + -ms-transform: scale(0.75); + transform: scale(0.75); + -webkit-transform-origin: center; + -ms-transform-origin: center; + transform-origin: center; +} + +.c3 { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + + +
+ +
+ + Feature Tag + +
+`; + +exports[`renders with icon 1`] = ` +.c2 { + vertical-align: middle; + height: 1.5rem; + width: 1.5rem; +} + +.c0 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #ECEEF5; + border-radius: 0.25rem; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + color: #5E637A; + cursor: pointer; + fill: #5E637A; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + font-size: 0.875rem; + gap: 0.25rem; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + line-height: 1.25rem; + max-width: -webkit-fit-content; + max-width: -moz-fit-content; + max-width: fit-content; + outline: none; + padding-block: calc(0.5rem / 4); + padding-inline: 0.5rem; + -webkit-text-decoration: none; + text-decoration: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.c0.active { + background-color: #F0F3FF; + color: #2852EB; + fill: #3C64F4; +} + +.c0:hover, +.c0.active:hover { + background-color: #DBE3FE; + color: #0B38D9; + fill: #3C64F4; +} + +.c0:focus { + outline: 4px solid #DBE3FE; +} + +.c0:active, +.c0.active:active { + background-color: #9EB3FC; + color: #0B38D9; + fill: #0024A6; +} + +.c0:focused:active { + background-color: #F0F3FF; + color: #0B38D9; + fill: #0B38D9; + outline: 4px solid #9EB3FC; +} + +.c1 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + height: 1.125rem; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + overflow: hidden; + width: 1.125rem; +} + +.c1 > svg { + -webkit-transform: scale(0.75); + -ms-transform: scale(0.75); + transform: scale(0.75); + -webkit-transform-origin: center; + -ms-transform-origin: center; + transform-origin: center; +} + +.c3 { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + + +
+ +
+ + Feature Tag + +
+`; diff --git a/packages/big-design/src/components/FeatureTag/index.ts b/packages/big-design/src/components/FeatureTag/index.ts new file mode 100644 index 000000000..9043b64ef --- /dev/null +++ b/packages/big-design/src/components/FeatureTag/index.ts @@ -0,0 +1 @@ +export { FeatureTag, type FeatureTagProps } from './FeatureTag'; diff --git a/packages/big-design/src/components/FeatureTag/spec.tsx b/packages/big-design/src/components/FeatureTag/spec.tsx new file mode 100644 index 000000000..6ea2c4b21 --- /dev/null +++ b/packages/big-design/src/components/FeatureTag/spec.tsx @@ -0,0 +1,38 @@ +import { AutoAwesomeIcon } from '@bigcommerce/big-design-icons'; +import { theme } from '@bigcommerce/big-design-theme'; +import { render } from '@testing-library/react'; +import React from 'react'; + +import 'jest-styled-components'; + +import { FeatureTag } from './FeatureTag'; + +test('render feature tag', () => { + const { container } = render(); + + expect(container.firstChild).toMatchSnapshot(); +}); + +test('renders with icon', () => { + const { container } = render(} label="Feature Tag" />); + + expect(container.firstChild).toMatchSnapshot(); +}); + +test('renders as active', () => { + const { container } = render( + } isActive={true} label="Feature Tag" />, + ); + + expect(container.firstChild).toMatchSnapshot(); + expect(container.firstChild).toHaveStyle(`background-color: ${theme.colors.primary10}`); + expect(container.firstChild).toHaveStyle(`color: ${theme.colors.primary50}`); + expect(container.firstChild).toHaveStyle(`fill: ${theme.colors.primary}`); +}); + +test("doesn't render if label prop is absent", () => { + // @ts-expect-error ignoring since label prop is required + const { container } = render(); + + expect(container.firstChild).toBeNull(); +}); diff --git a/packages/big-design/src/components/FeatureTag/styled.tsx b/packages/big-design/src/components/FeatureTag/styled.tsx new file mode 100644 index 000000000..953f0e81c --- /dev/null +++ b/packages/big-design/src/components/FeatureTag/styled.tsx @@ -0,0 +1,79 @@ +import { theme as defaultTheme } from '@bigcommerce/big-design-theme'; +import styled from 'styled-components'; + +export const StyledFeatureTag = styled.a` + align-items: center; + background-color: ${({ theme }) => theme.colors.secondary20}; + border-radius: ${({ theme }) => theme.borderRadius.normal}; + display: inline-flex; + color: ${({ theme }) => theme.colors.secondary60}; + cursor: pointer; + fill: ${({ theme }) => theme.colors.secondary60}; + flex-wrap: nowrap; + font-size: ${({ theme }) => theme.helpers.remCalc(14)}; + gap: ${({ theme }) => theme.spacing.xxSmall}; + justify-content: center; + line-height: ${({ theme }) => theme.helpers.remCalc(20)}; + max-width: fit-content; + outline: none; + padding-block: calc(${({ theme }) => theme.spacing.xSmall} / 4); + padding-inline: ${({ theme }) => theme.spacing.xSmall}; + text-decoration: none; + user-select: none; + + &.active { + background-color: ${({ theme }) => theme.colors.primary10}; + color: ${({ theme }) => theme.colors.primary50}; + fill: ${({ theme }) => theme.colors.primary}; + } + + &:hover, + &.active:hover { + background-color: ${({ theme }) => theme.colors.primary20}; + color: ${({ theme }) => theme.colors.primary60}; + fill: ${({ theme }) => theme.colors.primary40}; + } + + &:focus { + outline: 4px solid ${({ theme }) => theme.colors.primary20}; + } + + &:active, + &.active:active { + background-color: ${({ theme }) => theme.colors.primary30}; + color: ${({ theme }) => theme.colors.primary60}; + fill: ${({ theme }) => theme.colors.primary70}; + } + + &:focused:active { + background-color: ${({ theme }) => theme.colors.primary10}; + color: ${({ theme }) => theme.colors.primary60}; + fill: ${({ theme }) => theme.colors.primary60}; + outline: 4px solid ${({ theme }) => theme.colors.primary30}; + } +`; + +StyledFeatureTag.defaultProps = { theme: defaultTheme }; + +export const StyledFeatureTagIcon = styled.div` + align-items: center; + display: flex; + flex: 0 0 auto; + height: ${({ theme }) => theme.helpers.remCalc(18)}; + justify-content: center; + overflow: hidden; + width: ${({ theme }) => theme.helpers.remCalc(18)}; + + & > svg { + transform: scale(0.75); + transform-origin: center; + } +`; + +StyledFeatureTagIcon.defaultProps = { theme: defaultTheme }; + +export const StyledFeatureTagLabel = styled.span` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; diff --git a/packages/big-design/src/components/index.ts b/packages/big-design/src/components/index.ts index ce9fc0216..c28989526 100644 --- a/packages/big-design/src/components/index.ts +++ b/packages/big-design/src/components/index.ts @@ -43,3 +43,4 @@ export * from './Toggle'; export * from './Typography'; export * from './Worksheet'; export * from './FileUploader'; +export * from './FeatureTag'; diff --git a/packages/docs/next-env.d.ts b/packages/docs/next-env.d.ts index 4f11a03dc..a4a7b3f5c 100644 --- a/packages/docs/next-env.d.ts +++ b/packages/docs/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.