diff --git a/.changeset/young-months-peel.md b/.changeset/young-months-peel.md new file mode 100644 index 00000000000..7322a69ba52 --- /dev/null +++ b/.changeset/young-months-peel.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Remove the CSS module feature flag from SkeletonAvatar SkeletonBox and SkeletonText diff --git a/packages/react/src/experimental/Skeleton/FeatureFlag.tsx b/packages/react/src/experimental/Skeleton/FeatureFlag.tsx deleted file mode 100644 index 267b7ef5906..00000000000 --- a/packages/react/src/experimental/Skeleton/FeatureFlag.tsx +++ /dev/null @@ -1 +0,0 @@ -export const CSS_MODULE_FLAG = 'primer_react_css_modules_ga' diff --git a/packages/react/src/experimental/Skeleton/SkeletonAvatar.tsx b/packages/react/src/experimental/Skeleton/SkeletonAvatar.tsx index 5221154a39c..635b5e4bf39 100644 --- a/packages/react/src/experimental/Skeleton/SkeletonAvatar.tsx +++ b/packages/react/src/experimental/Skeleton/SkeletonAvatar.tsx @@ -1,36 +1,17 @@ import React, {type CSSProperties} from 'react' -import {getBreakpointDeclarations} from '../../utils/getBreakpointDeclarations' -import {get} from '../../constants' import {isResponsiveValue} from '../../hooks/useResponsiveValue' import type {AvatarProps} from '../../Avatar' import {DEFAULT_AVATAR_SIZE} from '../../Avatar/Avatar' import {SkeletonBox} from './SkeletonBox' import classes from './SkeletonAvatar.module.css' import {clsx} from 'clsx' -import {useFeatureFlag} from '../../FeatureFlags' import {merge} from '../../sx' -import {CSS_MODULE_FLAG} from './FeatureFlag' export type SkeletonAvatarProps = Pick & { /** Class name for custom styling */ className?: string } & Omit, 'size'> -const avatarSkeletonStyles = { - '&[data-component="SkeletonAvatar"]': { - borderRadius: '50%', - boxShadow: `0 0 0 1px ${get('colors.avatar.border')}`, - display: 'inline-block', - lineHeight: get('lineHeights.condensedUltra'), - height: 'var(--avatar-size)', - width: 'var(--avatar-size)', - }, - - '&[data-square]': { - borderRadius: 'clamp(4px, var(--avatar-size) - 24px, 6px)', - }, -} - export const SkeletonAvatar: React.FC = ({ size = DEFAULT_AVATAR_SIZE, square, @@ -40,40 +21,23 @@ export const SkeletonAvatar: React.FC = ({ }) => { const responsive = isResponsiveValue(size) const cssSizeVars = {} as Record - const enabled = useFeatureFlag(CSS_MODULE_FLAG) - const avatarSx = responsive - ? { - ...getBreakpointDeclarations( - size, - '--avatar-size' as keyof React.CSSProperties, - value => `${value || DEFAULT_AVATAR_SIZE}px`, - ), - ...avatarSkeletonStyles, - } - : { - '--avatar-size': `${size}px`, - ...avatarSkeletonStyles, - } - if (enabled) { - if (responsive) { - for (const [key, value] of Object.entries(size)) { - cssSizeVars[`--avatarSize-${key}`] = `${value}px` - } - } else { - cssSizeVars['--avatarSize-regular'] = `${size}px` + if (responsive) { + for (const [key, value] of Object.entries(size)) { + cssSizeVars[`--avatarSize-${key}`] = `${value}px` } + } else { + cssSizeVars['--avatarSize-regular'] = `${size}px` } return ( ) } diff --git a/packages/react/src/experimental/Skeleton/SkeletonBox.tsx b/packages/react/src/experimental/Skeleton/SkeletonBox.tsx index a72115aa885..ce8bab69b37 100644 --- a/packages/react/src/experimental/Skeleton/SkeletonBox.tsx +++ b/packages/react/src/experimental/Skeleton/SkeletonBox.tsx @@ -1,13 +1,10 @@ import React from 'react' -import styled, {keyframes} from 'styled-components' -import sx, {merge, type SxProp} from '../../sx' -import {get} from '../../constants' -import {type CSSProperties, type HTMLProps} from 'react' -import {toggleStyledComponent} from '../../internal/utils/toggleStyledComponent' +import {merge, type SxProp} from '../../sx' +import {type CSSProperties} from 'react' import {clsx} from 'clsx' import classes from './SkeletonBox.module.css' -import {useFeatureFlag} from '../../FeatureFlags' -import {CSS_MODULE_FLAG} from './FeatureFlag' +import {defaultSxProp} from '../../utils/defaultSxProp' +import Box from '../../Box' type SkeletonBoxProps = { /** Height of the skeleton "box". Accepts any valid CSS `height` value. */ @@ -17,62 +14,40 @@ type SkeletonBoxProps = { /** The className of the skeleton box */ className?: string } & SxProp & - HTMLProps - -const shimmer = keyframes` - from { mask-position: 200%; } - to { mask-position: 0%; } -` - -const StyledSkeletonBox = toggleStyledComponent( - CSS_MODULE_FLAG, - 'div', - styled.div` - animation: ${shimmer}; - display: block; - background-color: var(--skeletonLoader-bgColor, ${get('colors.canvas.subtle')}); - border-radius: 3px; - height: ${props => props.height || '1rem'}; - width: ${props => props.width}; - - @media (prefers-reduced-motion: no-preference) { - mask-image: linear-gradient(75deg, #000 30%, rgba(0, 0, 0, 0.65) 80%); - mask-size: 200%; - animation: ${shimmer}; - animation-duration: 1s; - animation-iteration-count: infinite; - } - - @media (forced-colors: active) { - outline: 1px solid transparent; - outline-offset: -1px; - } - - ${sx}; - `, -) + React.ComponentPropsWithoutRef<'div'> export const SkeletonBox = React.forwardRef(function SkeletonBox( - {height, width, className, style, ...props}, + {height, width, className, style, sx: sxProp = defaultSxProp, ...props}, ref, ) { - const enabled = useFeatureFlag(CSS_MODULE_FLAG) + if (sxProp !== defaultSxProp) { + return ( + + ) + } return ( - diff --git a/packages/react/src/experimental/Skeleton/SkeletonText.module.css b/packages/react/src/experimental/Skeleton/SkeletonText.module.css index 7615d4eb17b..eeee28e036b 100644 --- a/packages/react/src/experimental/Skeleton/SkeletonText.module.css +++ b/packages/react/src/experimental/Skeleton/SkeletonText.module.css @@ -63,3 +63,8 @@ --line-height: var(--text-body-lineHeight-small); } } + +.SkeletonTextWrapper { + /* stylelint-disable-next-line primer/spacing */ + padding-block: 0.1px; +} diff --git a/packages/react/src/experimental/Skeleton/SkeletonText.tsx b/packages/react/src/experimental/Skeleton/SkeletonText.tsx index 08c2680363f..e22bc91495c 100644 --- a/packages/react/src/experimental/Skeleton/SkeletonText.tsx +++ b/packages/react/src/experimental/Skeleton/SkeletonText.tsx @@ -1,11 +1,8 @@ import React, {type CSSProperties, type HTMLProps} from 'react' -import Box from '../../Box' import {SkeletonBox} from './SkeletonBox' import classes from './SkeletonText.module.css' -import {useFeatureFlag} from '../../FeatureFlags' import {clsx} from 'clsx' import {merge} from '../../sx' -import {CSS_MODULE_FLAG} from './FeatureFlag' type SkeletonTextProps = { /** Size of the text that the skeleton is replacing. */ @@ -18,61 +15,6 @@ type SkeletonTextProps = { className?: string } & Omit, 'size'> -const skeletonTextStyles = { - '&[data-component="SkeletonText"]': { - '--font-size': 'var(--text-body-size-medium, 0.875rem)', - '--line-height': 'var(--text-body-lineHeight-medium, 1.4285)', - '--leading': 'calc(var(--font-size) * var(--line-height) - var(--font-size))', - borderRadius: 'var(--borderRadius-small, 0.1875rem)', - height: 'var(--font-size)', - marginBlock: 'calc(var(--leading) / 2)', - }, - '&[data-in-multiline="true"]': { - marginBlockEnd: 'calc(var(--leading) * 2)', - }, - '&[data-in-multiline="true"]:last-child': { - maxWidth: '65%', - minWidth: '50px', - marginBottom: 0, - }, - '@supports (margin-block: mod(1px, 1px))': { - '&[data-component="SkeletonText"]': { - '--leading': 'mod(var(--font-size) * var(--line-height), var(--font-size))', - }, - }, - '&[data-text-skeleton-size="display"], &[data-text-skeleton-size="titleLarge"]': { - borderRadius: 'var(--borderRadius-medium, 0.375rem)', - }, - '&[data-text-skeleton-size="display"]': { - '--font-size': 'var(--text-display-size, 2.5rem)', - '--line-height': 'var(--text-display-lineHeight, 1.4)', - }, - '&[data-text-skeleton-size="titleLarge"]': { - '--font-size': 'var(--text-title-size-large, 2.5rem)', - '--line-height': 'var(--text-title-lineHeight-large, 1.5)', - }, - '&[data-text-skeleton-size="titleMedium"]': { - '--font-size': 'var(--text-title-size-medium, 1.25rem)', - '--line-height': 'var(--text-title-lineHeight-medium, 1.6)', - }, - '&[data-text-skeleton-size="titleSmall"]': { - '--font-size': 'var(--text-title-size-small, 1rem)', - '--line-height': 'var(--text-title-lineHeight-small, 1.5)', - }, - '&[data-text-skeleton-size="subtitle"]': { - '--font-size': 'var(--text-subtitle-size, 1.25rem)', - '--line-height': 'var(--text-subtitle-lineHeight, 1.6)', - }, - '&[data-text-skeleton-size="bodyLarge"]': { - '--font-size': 'var(--text-body-size-large, 1rem)', - '--line-height': 'var(--text-body-lineHeight-large, 1.5)', - }, - '&[data-text-skeleton-size="bodySmall"]': { - '--font-size': 'var(--text-body-size-small, 0.75rem)', - '--line-height': 'var(--text-body-lineHeight-small, 1.6666)', - }, -} - export const SkeletonText: React.FC = ({ lines = 1, maxWidth, @@ -81,39 +23,23 @@ export const SkeletonText: React.FC = ({ style, ...rest }) => { - const enabled = useFeatureFlag(CSS_MODULE_FLAG) - if (lines < 2) { return ( ) } else { return ( - {Array.from({length: lines}, (_, index) => ( = ({ data-component="SkeletonText" data-in-multiline="true" data-text-skeleton-size={size} - sx={enabled ? {} : skeletonTextStyles} - className={clsx(className, {[classes.SkeletonText]: enabled})} + className={clsx(className, classes.SkeletonText)} {...rest} /> ))} - + ) } } diff --git a/packages/react/src/experimental/Skeleton/__tests__/SkeletonBox.test.tsx b/packages/react/src/experimental/Skeleton/__tests__/SkeletonBox.test.tsx index 654e66e2400..d5ddbe4a7a8 100644 --- a/packages/react/src/experimental/Skeleton/__tests__/SkeletonBox.test.tsx +++ b/packages/react/src/experimental/Skeleton/__tests__/SkeletonBox.test.tsx @@ -1,24 +1,9 @@ import {render} from '@testing-library/react' import React from 'react' -import {FeatureFlags} from '../../../FeatureFlags' import {SkeletonBox} from '../SkeletonBox' describe('SkeletonBox', () => { it('should support `className` on the outermost element', () => { - const Element = () => - const FeatureFlagElement = () => { - return ( - - - - ) - } - expect(render().container.firstChild).toHaveClass('test-class-name') - expect(render().container.firstChild).toHaveClass('test-class-name') + expect(render().container.firstChild).toHaveClass('test-class-name') }) }) diff --git a/packages/react/src/experimental/Skeleton/__tests__/SkeletonText.test.tsx b/packages/react/src/experimental/Skeleton/__tests__/SkeletonText.test.tsx index 3f235ac41ec..d0c03f5001e 100644 --- a/packages/react/src/experimental/Skeleton/__tests__/SkeletonText.test.tsx +++ b/packages/react/src/experimental/Skeleton/__tests__/SkeletonText.test.tsx @@ -1,24 +1,9 @@ import {render} from '@testing-library/react' import React from 'react' -import {FeatureFlags} from '../../../FeatureFlags' import {SkeletonText} from '../SkeletonText' describe('SkeletonText', () => { it('should support `className` on the outermost element', () => { - const Element = () => - const FeatureFlagElement = () => { - return ( - - - - ) - } - expect(render().container.firstChild).toHaveClass('test-class-name') - expect(render().container.firstChild).toHaveClass('test-class-name') + expect(render().container.firstChild).toHaveClass('test-class-name') }) })