Skip to content

Commit

Permalink
Merge 6097899 into cbeed21
Browse files Browse the repository at this point in the history
  • Loading branch information
jonrohan authored Oct 30, 2024
2 parents cbeed21 + 6097899 commit 69a1c2c
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-zebras-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

Convert SkeletonBox to CSS modules behind the feature flag
30 changes: 30 additions & 0 deletions packages/react/src/experimental/Skeleton/SkeletonBox.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@keyframes shimmer {
from {
mask-position: 200%;
}

to {
mask-position: 0%;
}
}

.SkeletonBox {
display: block;
height: 1rem;
background-color: var(--bgColor-muted);
border-radius: var(--borderRadius-small);
animation: shimmer;

@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;
}
}
90 changes: 65 additions & 25 deletions packages/react/src/experimental/Skeleton/SkeletonBox.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,80 @@
import type React from 'react'
import React from 'react'
import styled, {keyframes} from 'styled-components'
import sx, {type SxProp} from '../../sx'
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 {clsx} from 'clsx'
import classes from './SkeletonBox.module.css'
import {useFeatureFlag} from '../../FeatureFlags'

type SkeletonBoxProps = {
/** Height of the skeleton "box". Accepts any valid CSS `height` value. */
height?: React.CSSProperties['height']
height?: CSSProperties['height']
/** Width of the skeleton "box". Accepts any valid CSS `width` value. */
width?: React.CSSProperties['width']
} & SxProp
width?: CSSProperties['width']
/** The className of the skeleton box */
className?: string
} & SxProp &
HTMLProps<HTMLDivElement>

const shimmer = keyframes`
from { mask-position: 200%; }
to { mask-position: 0%; }
`
const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team'

export const SkeletonBox = styled.div<SkeletonBoxProps>`
animation: ${shimmer};
display: block;
background-color: var(--bgColor-muted, ${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%;
const StyledSkeletonBox = toggleStyledComponent(
CSS_MODULES_FEATURE_FLAG,
'div',
styled.div<SkeletonBoxProps>`
animation: ${shimmer};
animation-duration: 1s;
animation-iteration-count: infinite;
}
display: block;
background-color: var(--bgColor-muted, ${get('colors.canvas.subtle')});
border-radius: 3px;
height: ${props => props.height || '1rem'};
width: ${props => props.width};
@media (forced-colors: active) {
outline: 1px solid transparent;
outline-offset: -1px;
}
@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;
}
${sx};
`
@media (forced-colors: active) {
outline: 1px solid transparent;
outline-offset: -1px;
}
${sx};
`,
)

export const SkeletonBox = React.forwardRef<HTMLDivElement, SkeletonBoxProps>(function SkeletonBox(
{height, width, className, style, ...props},
ref,
) {
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)
return (
<StyledSkeletonBox
height={enabled ? undefined : height}
width={enabled ? undefined : width}
className={clsx(className, {[classes.SkeletonBox]: enabled})}
style={
enabled
? merge(
style as CSSProperties,
{
height,
width,
} as CSSProperties,
)
: style
}
{...props}
ref={ref}
/>
)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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 = () => <SkeletonBox className={'test-class-name'} />
const FeatureFlagElement = () => {
return (
<FeatureFlags
flags={{
primer_react_css_modules_team: true,
primer_react_css_modules_staff: true,
primer_react_css_modules_ga: true,
}}
>
<Element />
</FeatureFlags>
)
}
expect(render(<Element />).container.firstChild).toHaveClass('test-class-name')
expect(render(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
})
})

0 comments on commit 69a1c2c

Please sign in to comment.