diff --git a/packages/react/src/Token/_RemoveTokenButton.module.css b/packages/react/src/Token/_RemoveTokenButton.module.css new file mode 100644 index 00000000000..e70a8867ec2 --- /dev/null +++ b/packages/react/src/Token/_RemoveTokenButton.module.css @@ -0,0 +1,50 @@ +.TokenButton { + display: inline-flex; + padding: 0; + margin-left: var(--base-size-4); + font-family: inherit; + color: currentColor; + text-decoration: none; + cursor: pointer; + user-select: none; + background-color: transparent; + border: 0; + border-radius: var(--borderRadius-full); + justify-content: center; + align-items: center; + appearance: none; + align-self: baseline; +} + +.TokenButton[data-size='small'] { + width: var(--base-size-16); + height: var(--base-size-16); +} + +.TokenButton[data-size='medium'] { + width: 20px; + height: 20px; +} + +.TokenButton[data-size='large'] { + width: var(--base-size-24); + height: var(--base-size-24); + margin-left: var(--base-size-8); +} + +.TokenButton[data-size='xlarge'] { + width: var(--base-size-32); + height: var(--base-size-32); + margin-left: var(--base-size-8); +} + +.TokenButton:hover, +.TokenButton:focus { + /* TODO: choose a better functional color variable for this */ + background-color: var(--bgColor-neutral-muted); +} + +.TokenButton:active { + /* TODO: choose a better functional color variable for this */ + background-color: var(--bgColor-neutral-muted); +} diff --git a/packages/react/src/Token/_RemoveTokenButton.tsx b/packages/react/src/Token/_RemoveTokenButton.tsx index d5d5784957d..92bf161941e 100644 --- a/packages/react/src/Token/_RemoveTokenButton.tsx +++ b/packages/react/src/Token/_RemoveTokenButton.tsx @@ -2,19 +2,24 @@ import React from 'react' import {XIcon} from '@primer/octicons-react' import styled, {css} from 'styled-components' import {variant} from 'styled-system' +import {clsx} from 'clsx' import {get} from '../constants' -import type {SxProp} from '../sx' -import sx from '../sx' -import type {ComponentProps} from '../utils/types' +import sx, {type SxProp} from '../sx' import type {TokenSizeKeys} from './TokenBase' import {tokenSizes, defaultTokenSize} from './TokenBase' +import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import {useFeatureFlag} from '../FeatureFlags' -interface TokenButtonProps { +import classes from './_RemoveTokenButton.module.css' + +interface TokenButtonProps extends SxProp { borderOffset?: number size?: TokenSizeKeys isParentInteractive?: boolean } +const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team' + const variants = variant<{height: string; width: string}, TokenSizeKeys>({ prop: 'size', variants: { @@ -39,66 +44,84 @@ const variants = variant<{height: string; width: string}, TokenSizeKeys>({ const getTokenButtonIconSize = (size?: TokenSizeKeys) => parseInt(tokenSizes[size || defaultTokenSize], 10) * 0.75 -const StyledTokenButton = styled.span` - background-color: transparent; - font-family: inherit; - color: currentColor; - cursor: pointer; - display: inline-flex; - justify-content: center; - align-items: center; - user-select: none; - appearance: none; - text-decoration: none; - padding: 0; - transform: ${props => `translate(${props.borderOffset}px, -${props.borderOffset}px)`}; - align-self: baseline; - border: 0; - border-radius: 999px; +const StyledTokenButton = toggleStyledComponent( + CSS_MODULES_FEATURE_FLAG, + 'span', + styled.span` + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: inline-flex; + justify-content: center; + align-items: center; + user-select: none; + appearance: none; + text-decoration: none; + padding: 0; + transform: ${props => `translate(${props.borderOffset}px, -${props.borderOffset}px)`}; + align-self: baseline; + border: 0; + border-radius: 999px; + + ${props => { + switch (props.size) { + case 'large': + case 'xlarge': + return css` + margin-left: ${get('space.2')}; + ` + default: + return css` + margin-left: ${get('space.1')}; + ` + } + }} - ${props => { - switch (props.size) { - case 'large': - case 'xlarge': - return css` - margin-left: ${get('space.2')}; - ` - default: - return css` - margin-left: ${get('space.1')}; - ` + &:hover, + &:focus { + // TODO: choose a better functional color variable for this + background-color: ${get('colors.neutral.muted')}; } - }} - &:hover, - &:focus { - // TODO: choose a better functional color variable for this - background-color: ${get('colors.neutral.muted')}; - } + &:active { + // TODO: choose a better functional color variable for this + background-color: ${get('colors.neutral.subtle')}; + } - &:active { - // TODO: choose a better functional color variable for this - background-color: ${get('colors.neutral.subtle')}; - } + ${variants} + ${sx} + `, +) - ${variants} - ${sx} -` +type RemoveTokenButtonProps = TokenButtonProps & Omit, 'size'> -const RemoveTokenButton: React.FC>> = ({ +const RemoveTokenButton = ({ 'aria-label': ariaLabel, isParentInteractive, size = defaultTokenSize, + className, ...rest -}) => { +}: React.PropsWithChildren) => { delete rest.children + const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) + return ( diff --git a/packages/react/src/Token/_TokenTextContainer.module.css b/packages/react/src/Token/_TokenTextContainer.module.css new file mode 100644 index 00000000000..b197cccb919 --- /dev/null +++ b/packages/react/src/Token/_TokenTextContainer.module.css @@ -0,0 +1,46 @@ +.TokenTextContainer { + width: auto; + min-width: 0; + padding: 0; + margin: 0; + overflow: hidden; + font: inherit; + /* stylelint-disable-next-line primer/typography */ + line-height: normal; + color: inherit; + + /* reset anchor styles */ + color: currentColor; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + + /* reset button styles, make the cursor a pointer, and add line-height */ + background: transparent; + border: none; + flex-grow: 1; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + appearance: none; +} + +/* Position psuedo-element above text content, but below the + remove button. + This ensures the or