Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,11 @@ import Spinner from '../Spinner'
import {Stack} from '../Stack/Stack'
import {SkeletonBox} from '../Skeleton/SkeletonBox'
import classes from './FilteredActionListLoaders.module.css'
import {FilteredActionListLoadingType, FilteredActionListLoadingTypes} from './constants'

import type {JSX} from 'react'

export class FilteredActionListLoadingType {
public name: string
public appearsInBody: boolean

constructor(name: string, appearsInBody: boolean) {
this.name = name
this.appearsInBody = appearsInBody
}
}

export const FilteredActionListLoadingTypes = {
bodySpinner: new FilteredActionListLoadingType('body-spinner', true),
bodySkeleton: new FilteredActionListLoadingType('body-skeleton', true),
input: new FilteredActionListLoadingType('input', false),
}
export {FilteredActionListLoadingType, FilteredActionListLoadingTypes}

const SKELETON_ROW_HEIGHT = 24
const SKELETON_MIN_ROWS = 3
Expand Down
15 changes: 15 additions & 0 deletions packages/react/src/FilteredActionList/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export class FilteredActionListLoadingType {
public name: string
public appearsInBody: boolean

constructor(name: string, appearsInBody: boolean) {
this.name = name
this.appearsInBody = appearsInBody
}
}

export const FilteredActionListLoadingTypes = {
bodySpinner: new FilteredActionListLoadingType('body-spinner', true),
bodySkeleton: new FilteredActionListLoadingType('body-skeleton', true),
input: new FilteredActionListLoadingType('input', false),
}
34 changes: 2 additions & 32 deletions packages/react/src/KeybindingHint/components/Chord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,9 @@ import {Fragment} from 'react'
import Text from '../../Text'
import type {KeybindingHintProps} from '../props'
import {Key} from './Key'
import {accessibleKeyName} from '../key-names'
import type {Platform} from '../platform'
import {clsx} from 'clsx'
import classes from './Chord.module.css'

/**
* Consistent sort order for modifier keys. There should never be more than one non-modifier
* key in a chord, so we don't need to worry about sorting those - we just put them at
* the end.
*/
const keySortPriorities: Partial<Record<string, number>> = {
control: 1,
meta: 2,
alt: 3,
option: 4,
shift: 5,
function: 6,
}

const keySortPriority = (priority: string) => keySortPriorities[priority] ?? Infinity

const compareLowercaseKeys = (a: string, b: string) => keySortPriority(a) - keySortPriority(b)

/** Split and sort the chord keys in standard order. */
const splitChord = (chord: string) =>
chord
.split('+')
.map(k => k.toLowerCase())
.sort(compareLowercaseKeys)
import {accessibleChordString, splitChord} from './utils'

export const Chord = ({keys, format = 'condensed', variant = 'normal', size = 'normal'}: KeybindingHintProps) => (
<Text
Expand All @@ -56,8 +30,4 @@ export const Chord = ({keys, format = 'condensed', variant = 'normal', size = 'n
</Text>
)

/** Plain string version of `Chord` for use in `aria` string attributes. */
export const accessibleChordString = (chord: string, platform: Platform) =>
splitChord(chord)
.map(key => accessibleKeyName(key, platform))
.join(' ')
export {accessibleChordString}
10 changes: 3 additions & 7 deletions packages/react/src/KeybindingHint/components/Sequence.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Fragment} from 'react'
import type {KeybindingHintProps} from '../props'
import VisuallyHidden from '../../_VisuallyHidden'
import {accessibleChordString, Chord} from './Chord'
import type {Platform} from '../platform'
import {Chord} from './Chord'
import {accessibleSequenceString} from './utils'

const splitSequence = (sequence: string) => sequence.split(' ')

Expand All @@ -21,8 +21,4 @@ export const Sequence = ({keys, ...chordProps}: KeybindingHintProps) =>
</Fragment>
))

/** Plain string version of `Sequence` for use in `aria` string attributes. */
export const accessibleSequenceString = (sequence: string, platform: Platform) =>
splitSequence(sequence)
.map(chord => accessibleChordString(chord, platform))
.join(' then ')
export {accessibleSequenceString}
41 changes: 41 additions & 0 deletions packages/react/src/KeybindingHint/components/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {accessibleKeyName} from '../key-names'
import type {Platform} from '../platform'

/**
* Consistent sort order for modifier keys. There should never be more than one non-modifier
* key in a chord, so we don't need to worry about sorting those - we just put them at
* the end.
*/
const keySortPriorities: Partial<Record<string, number>> = {
control: 1,
meta: 2,
alt: 3,
option: 4,
shift: 5,
function: 6,
}

const keySortPriority = (priority: string) => keySortPriorities[priority] ?? Infinity

const compareLowercaseKeys = (a: string, b: string) => keySortPriority(a) - keySortPriority(b)

/** Split and sort the chord keys in standard order. */
export const splitChord = (chord: string) =>
chord
.split('+')
.map(k => k.toLowerCase())
.sort(compareLowercaseKeys)

const splitSequence = (sequence: string) => sequence.split(' ')

/** Plain string version of `Chord` for use in `aria` string attributes. */
export const accessibleChordString = (chord: string, platform: Platform) =>
splitChord(chord)
.map(key => accessibleKeyName(key, platform))
.join(' ')

/** Plain string version of `Sequence` for use in `aria` string attributes. */
export const accessibleSequenceString = (sequence: string, platform: Platform) =>
splitSequence(sequence)
.map(chord => accessibleChordString(chord, platform))
.join(' then ')
21 changes: 2 additions & 19 deletions packages/react/src/Overlay/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../uti
import classes from './Overlay.module.css'
import {clsx} from 'clsx'
import {useFeatureFlag} from '../FeatureFlags'
import {heightMap, widthMap} from './constants'

type StyledOverlayProps = {
width?: keyof typeof widthMap
Expand All @@ -21,25 +22,7 @@ type StyledOverlayProps = {
style?: React.CSSProperties
}

export const heightMap = {
xsmall: '192px',
small: '256px',
medium: '320px',
large: '432px',
xlarge: '600px',
auto: 'auto',
initial: 'auto', // Passing 'initial' initially applies 'auto'
'fit-content': 'fit-content',
}

export const widthMap = {
small: '256px',
medium: '320px',
large: '480px',
xlarge: '640px',
xxlarge: '960px',
auto: 'auto',
}
export {heightMap, widthMap}
const animationDuration = 200

function getSlideAnimationStartingVector(anchorSide?: AnchorSide): {x: number; y: number} {
Expand Down
19 changes: 19 additions & 0 deletions packages/react/src/Overlay/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const heightMap = {
xsmall: '192px',
small: '256px',
medium: '320px',
large: '432px',
xlarge: '600px',
auto: 'auto',
initial: 'auto',
'fit-content': 'fit-content',
}

export const widthMap = {
small: '256px',
medium: '320px',
large: '480px',
xlarge: '640px',
xxlarge: '960px',
auto: 'auto',
}
13 changes: 2 additions & 11 deletions packages/react/src/Timeline/Timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {clsx} from 'clsx'
import React from 'react'
import {useFeatureFlag} from '../FeatureFlags'
import classes from './Timeline.module.css'
import {TimelineBadgeVariants} from './constants'

type StyledTimelineProps = {clipSidebar?: boolean | 'start' | 'end' | 'both'; className?: string}

Expand Down Expand Up @@ -83,17 +84,7 @@ const TimelineItem = React.forwardRef<HTMLDivElement | HTMLLIElement, TimelineIt

TimelineItem.displayName = 'TimelineItem'

export const TimelineBadgeVariants = [
'accent',
'success',
'attention',
'severe',
'danger',
'done',
'open',
'closed',
'sponsors',
] as const
export {TimelineBadgeVariants}

export type TimelineBadgeVariant = (typeof TimelineBadgeVariants)[number]

Expand Down
11 changes: 11 additions & 0 deletions packages/react/src/Timeline/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const TimelineBadgeVariants = [
'accent',
'success',
'attention',
'severe',
'danger',
'done',
'open',
'closed',
'sponsors',
] as const
29 changes: 5 additions & 24 deletions packages/react/src/Token/TokenBase.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import type {ComponentProps, KeyboardEvent} from 'react'
import type {KeyboardEvent} from 'react'
import React from 'react'
import {clsx} from 'clsx'
import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic'
import classes from './TokenBase.module.css'
import {defaultTokenSize, type TokenSizeKeys, tokenSizes} from './constants'
import {isTokenInteractive} from './utils'

export type TokenSizeKeys = 'small' | 'medium' | 'large' | 'xlarge'

export const tokenSizes: Record<TokenSizeKeys, string> = {
small: '16px',
medium: '20px',
large: '24px',
xlarge: '32px',
}

export const defaultTokenSize: TokenSizeKeys = 'medium'
export {defaultTokenSize, isTokenInteractive, tokenSizes}
export type {TokenSizeKeys}

export interface TokenBaseProps
extends Omit<React.HTMLProps<HTMLSpanElement | HTMLButtonElement | HTMLAnchorElement>, 'size' | 'id'> {
Expand Down Expand Up @@ -48,19 +42,6 @@ export interface TokenBaseProps
disabled?: boolean
}

export const isTokenInteractive = ({
as = 'span',
onClick,
onFocus,
tabIndex = -1,
disabled,
}: Pick<ComponentProps<typeof TokenBase>, 'disabled' | 'as' | 'onClick' | 'onFocus' | 'tabIndex'>) => {
if (disabled) {
return false
}
return Boolean(onFocus || onClick || tabIndex > -1 || ['a', 'button'].includes(as))
}

const TokenBase = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement | undefined, TokenBaseProps>(
(
{
Expand Down
10 changes: 10 additions & 0 deletions packages/react/src/Token/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type TokenSizeKeys = 'small' | 'medium' | 'large' | 'xlarge'

export const tokenSizes: Record<TokenSizeKeys, string> = {
small: '16px',
medium: '20px',
large: '24px',
xlarge: '32px',
}

export const defaultTokenSize: TokenSizeKeys = 'medium'
14 changes: 14 additions & 0 deletions packages/react/src/Token/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type {TokenBaseProps} from './TokenBase'

export const isTokenInteractive = ({
as = 'span',
onClick,
onFocus,
tabIndex = -1,
disabled,
}: Pick<TokenBaseProps, 'disabled' | 'as' | 'onClick' | 'onFocus' | 'tabIndex'>) => {
if (disabled) {
return false
}
return Boolean(onFocus || onClick || tabIndex > -1 || ['a', 'button'].includes(as))
}
6 changes: 2 additions & 4 deletions packages/react/src/UnderlineNav/UnderlineNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import CounterLabel from '../CounterLabel'
import {invariant} from '../utils/invariant'
import classes from './UnderlineNav.module.css'
import {getAnchoredPosition} from '@primer/behaviors'
import {getValidChildren} from './utils'

export type UnderlineNavProps = {
children: React.ReactNode
Expand Down Expand Up @@ -109,10 +110,7 @@ const overflowEffect = (
updateListAndMenu({items, menuItems}, iconsVisible, true)
}

export const getValidChildren = (children: React.ReactNode) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return React.Children.toArray(children).filter(child => React.isValidElement(child)) as React.ReactElement<any>[]
}
export {getValidChildren}

const calculatePossibleItems = (childWidthArray: ChildWidthArray, navWidth: number, moreMenuWidth = 0) => {
const widthToFit = navWidth - moreMenuWidth
Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/UnderlineNav/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react'

export const getValidChildren = (children: React.ReactNode) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return React.Children.toArray(children).filter(child => React.isValidElement(child)) as React.ReactElement<any>[]
}
Comment on lines +1 to +6
Loading
Loading