Skip to content
Draft
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
15 changes: 10 additions & 5 deletions packages/@react-spectrum/s2/src/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import {ActionButtonGroup} from './ActionButtonGroup';
import {announce} from 'react-aria/private/live-announcer/LiveAnnouncer';
import {banner, StyleProps} from './style-utils' with {type: 'macro'};
import {CloseButton} from './CloseButton';
import {ContextValue, SlotProps} from 'react-aria-components/slots';
import {
Expand All @@ -31,7 +32,6 @@ import {DOMProps, DOMRef, DOMRefValue, Key} from '@react-types/shared';
import {FocusScope} from 'react-aria/FocusScope';
import intlMessages from '../intl/*.json';
import {lightDark, style} from '../style' with {type: 'macro'};
import {StyleProps} from './style-utils' with {type: 'macro'};
import {useControlledState} from 'react-stately/useControlledState';
import {useDOMRef} from './useDOMRef';
import {useEnterAnimation, useExitAnimation} from 'react-aria/private/utils/animation';
Expand All @@ -42,6 +42,7 @@ import {useResizeObserver} from 'react-aria/private/utils/useResizeObserver';
import {useSpectrumContextProps} from './useSpectrumContextProps';

const actionBarStyles = style({
...banner(),
borderRadius: 'lg',
'--s2-container-bg': {
type: 'backgroundColor',
Expand All @@ -60,10 +61,7 @@ const actionBarStyles = style({
isEmphasized: 'transparent',
forcedColors: 'ButtonBorder'
},
paddingX: 8,
paddingY: 12,
display: 'flex',
gap: 16,
alignItems: 'center',
position: {
isInContainer: 'absolute'
Expand Down Expand Up @@ -194,7 +192,14 @@ const ActionBarInner = forwardRef(function ActionBarInner(
{...keyboardProps}
className={
(props.UNSAFE_className || '') +
actionBarStyles({isEmphasized, isInContainer: !!scrollRef, isEntering, isExiting})
actionBarStyles({
isEmphasized,
isInContainer: !!scrollRef,
isEntering,
isExiting,
orientation: 'horizontal',
density: 'compact'
})
}
style={{
insetInlineEnd: `calc(var(--insetEnd) + ${scrollbarWidth}px)`,
Expand Down
33 changes: 15 additions & 18 deletions packages/@react-spectrum/s2/src/Disclosure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ import {CenterBaseline} from './CenterBaseline';
import Chevron from '../ui-icons/Chevron';

import {ContextValue, Provider, useSlottedContext} from 'react-aria-components/slots';
import {
controlGap,
controlPadding,
verticalPadding,
getAllowedOverrides,
StyleProps,
StylesPropWithFont,
UnsafeStyles,
horizontalPadding
} from './style-utils' with {type: 'macro'};
import {
DisclosureStateContext,
Disclosure as RACDisclosure,
Expand All @@ -41,12 +51,6 @@ import {
DisclosureProps as RACDisclosureProps
} from 'react-aria-components/Disclosure';
import {filterDOMProps} from 'react-aria/filterDOMProps';
import {
getAllowedOverrides,
StyleProps,
StylesPropWithFont,
UnsafeStyles
} from './style-utils' with {type: 'macro'};
import {Heading} from 'react-aria-components/Heading';
import React, {createContext, forwardRef, ReactNode, useContext} from 'react';
import {useDOMRef} from './useDOMRef';
Expand Down Expand Up @@ -189,9 +193,9 @@ const buttonStyles = style(
display: 'flex',
flexGrow: 1,
alignItems: 'baseline',
paddingX: 'calc(self(minHeight) * 3/8 - 1px)',
paddingX: controlPadding(),
paddingY: centerPadding(),
gap: 'calc(self(minHeight) * 3/8 - 1px)',
gap: controlPadding(),
minHeight: {
// compact is equivalent to 'control', but other densities have more padding.
size: {
Expand Down Expand Up @@ -359,16 +363,9 @@ const panelStyles = style({
});

const panelInner = style({
paddingTop: 8,
paddingBottom: 16,
paddingX: {
size: {
S: 8,
M: space(9),
L: 12,
XL: space(15)
}
}
paddingTop: verticalPadding('L'),
paddingBottom: verticalPadding('2XL'),
paddingX: controlPadding()
});

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-spectrum/s2/src/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ const innerDivStyle = style(
{
padding: {
padding: {
default: 8,
default: 'popover-padding',
none: 0
}
},
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-spectrum/s2/src/RadioGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {CenterBaseline} from './CenterBaseline';
import {ContextValue} from 'react-aria-components/slots';
import {
controlFont,
controlGap,
controlSize,
field,
getAllowedOverrides,
Expand Down Expand Up @@ -232,7 +233,7 @@ const radioField = style(
default: ['max-content', '1fr'],
isNoVisibleLabel: ['max-content']
},
columnGap: 'text-to-control',
columnGap: controlGap(),
alignContent: 'start',
font: controlFont(),
'--field-height': {
Expand Down
79 changes: 75 additions & 4 deletions packages/@react-spectrum/s2/src/style-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,74 @@ const controlSizeS = {
}
} as const;

// Base Gap
export const controlGap = () =>
({
default: 'base-gap-medium',
size: {
XS: 'base-gap-extra-small',
S: 'base-gap-small',
L: 'base-gap-large',
XL: 'base-gap-extra-large'
}
}) as const;

// Base Horizontal Padding - dynamic
export const controlPadding = () =>
({
default: 'base-padding-horizontal-medium',
size: {
XS: 'base-padding-horizontal-extra-small',
S: 'base-padding-horizontal-small',
L: 'base-padding-horizontal-large',
XL: 'base-padding-horizontal-extra-large',
'2XL': 'base-padding-horizontal-2x-large'
}
}) as const;

const verticalPaddingTokens = {
XS: 'base-padding-vertical-extra-small',
S: 'base-padding-vertical-small',
M: 'base-padding-vertical-medium',
L: 'base-padding-vertical-large',
XL: 'base-padding-vertical-extra-large',
'2XL': 'base-padding-vertical-2x-large'
} as const;

const horizontalPaddingTokens = {
XS: 'base-padding-horizontal-extra-small',
S: 'base-padding-horizontal-small',
M: 'base-padding-horizontal-medium',
L: 'base-padding-horizontal-large',
XL: 'base-padding-horizontal-extra-large',
'2XL': 'base-padding-horizontal-2x-large'
} as const;

// Base Vertical Padding - static
export const verticalPadding = (size: keyof typeof verticalPaddingTokens = 'M') =>
verticalPaddingTokens[size];

// Base Horizontal Padding - static
export const horizontalPadding = (size: keyof typeof horizontalPaddingTokens = 'M') =>
horizontalPaddingTokens[size];

export const banner = () =>
({
paddingX: {
density: {
default: 'banner-padding-horizontal',
compact: 'banner-padding-horizontal-compact'
}
},
paddingY: 'banner-padding-vertical',
gap: {
orientation: {
horizontal: 'banner-gap-horizontal',
vertical: 'banner-gap-vertical'
}
}
}) as const;

// This generates the border radius for t-shirt sizes using the
// Major Second logarithmic scale.
export const controlBorderRadius = (size: 'default' | 'sm' = 'default') =>
Expand Down Expand Up @@ -274,8 +342,11 @@ interface ControlResult {
height?: ReturnType<typeof controlSize>;
display?: 'flex';
alignItems?: 'center' | {default: 'baseline'; [iconOnly]: 'center'};
columnGap?: 'text-to-visual';
paddingX?: 'pill' | 'edge-to-text' | {default: 'pill' | 'edge-to-text'; [iconOnly]: 0};
columnGap?: ReturnType<typeof controlGap>;
paddingX?:
| 'pill'
| ReturnType<typeof controlPadding>
| {default: 'pill' | ReturnType<typeof controlPadding>; [iconOnly]: 0};
paddingY?: 0 | `[${string}]`;
}

Expand All @@ -286,7 +357,7 @@ const iconOnly = ':has([slot=icon]):not(:has([data-rsp-slot=text]))';
* The text can optionally wrap, aligning the icon with the first line of text.
*/
export function control(options: ControlOptions): ControlResult {
let paddingX = options.shape === 'pill' ? ('pill' as const) : ('edge-to-text' as const);
let paddingX = options.shape === 'pill' ? ('pill' as const) : controlPadding();
let result: ControlResult = {
font: controlFont(),
display: 'flex',
Expand All @@ -303,7 +374,7 @@ export function control(options: ControlOptions): ControlResult {
}

if (options.icon) {
result.columnGap = 'text-to-visual';
result.columnGap = controlGap();
result.paddingX = {
default: paddingX,
[iconOnly]: 0
Expand Down
61 changes: 59 additions & 2 deletions packages/@react-spectrum/s2/style/spectrum-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
fontSizeToken,
generateOverlayColorScale,
getToken,
getSetToken,
shadowToken,
simpleColorScale,
weirdColorToken
Expand Down Expand Up @@ -427,24 +428,80 @@ export function space(this: MacroContext | void, px: number): string {

const relativeSpacing = {
// font-size relative values
/**
* @deprecated Use `controlGap()` from `style-utils`, which selects a `base-gap-*` tier per
* component size.
*/
'text-to-control': fontRelative(10),
/**
* @deprecated Use `controlGap()` from `style-utils`, which selects a `base-gap-*` tier per
* component size.
*/
'text-to-visual': {
default: fontRelative(6), // -> 5px, 5px, 6px, 7px, 8px
touch: fontRelative(8, 17) // -> 6px, 7px, 8px, 9px, 10px, should be 7px, 7px, 8px, 9px, 11px
},
// height relative values
/**
* @deprecated Use `controlPadding()` from `style-utils`, which selects a
* `base-padding-horizontal-*` tier per component size.
*/
'edge-to-text': 'calc(self(height, self(minHeight)) * 3 / 8)',
pill: 'calc(self(height, self(minHeight)) / 2)'
} as const;

// Base gap/padding tiers, selected per component size at the call site
// (see `controlGap`/`controlPadding` in `style-utils`). The token holds the
// desktop value; the `--s2-scale` variable produces the touch value.
const sizeSpacing = {
'base-gap-extra-small': size(parseFloat(getToken('base-gap-extra-small'))),
'base-gap-small': size(parseFloat(getToken('base-gap-small'))),
'base-gap-medium': size(parseFloat(getToken('base-gap-medium'))),
'base-gap-large': size(parseFloat(getToken('base-gap-large'))),
'base-gap-extra-large': size(parseFloat(getToken('base-gap-extra-large'))),
'base-padding-horizontal-extra-small': size(
parseFloat(getSetToken('base-padding-horizontal-extra-small'))
),
'base-padding-horizontal-small': size(parseFloat(getSetToken('base-padding-horizontal-small'))),
'base-padding-horizontal-medium': size(parseFloat(getSetToken('base-padding-horizontal-medium'))),
'base-padding-horizontal-large': size(parseFloat(getSetToken('base-padding-horizontal-large'))),
'base-padding-horizontal-extra-large': size(
parseFloat(getSetToken('base-padding-horizontal-extra-large'))
),
'base-padding-horizontal-2x-large': size(
parseFloat(getSetToken('base-padding-horizontal-2x-large'))
),
'base-padding-vertical-extra-small': size(
parseFloat(getToken('base-padding-vertical-extra-small'))
),
'base-padding-vertical-small': size(parseFloat(getToken('base-padding-vertical-small'))),
'base-padding-vertical-medium': size(parseFloat(getToken('base-padding-vertical-medium'))),
'base-padding-vertical-large': size(parseFloat(getToken('base-padding-vertical-large'))),
'base-padding-vertical-extra-large': size(
parseFloat(getToken('base-padding-vertical-extra-large'))
),
'base-padding-vertical-2x-large': size(parseFloat(getToken('base-padding-vertical-2x-large'))),
'banner-gap-horizontal': size(parseFloat(getToken('banner-gap-horizontal'))),
'banner-gap-vertical': size(parseFloat(getToken('banner-gap-vertical'))),
'banner-padding-horizontal': size(parseFloat(getToken('banner-padding-horizontal'))),
'banner-padding-horizontal-compact': size(
parseFloat(getToken('banner-padding-horizontal-compact'))
),
'banner-padding-vertical': size(parseFloat(getToken('banner-padding-vertical'))),
'popover-padding': size(parseFloat(getToken('popover-padding'))),
'popover-gap': size(parseFloat(getToken('popover-gap')))
} as const;

const spacing = {
...baseSpacing,
...relativeSpacing
...relativeSpacing,
...sizeSpacing
};

const padding = {
...basePadding,
...relativeSpacing
...relativeSpacing,
...sizeSpacing
};

/**
Expand Down
8 changes: 8 additions & 0 deletions packages/@react-spectrum/s2/style/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export function getToken(name: TokenName): string {
return (tokens[name] as any).value;
}

// Some dimension tokens store their value under a responsive set (e.g. desktop/mobile)
// rather than a top-level `value`. In S2 the touch scale is applied via the `--s2-scale`
// CSS variable, so we read the desktop value and let that variable produce the touch value.
export function getSetToken(name: TokenName, set: 'desktop' | 'mobile' = 'desktop'): string {
let token = tokens[name] as any;
return token.sets ? token.sets[set].value : token.value;
}

export interface ColorToken {
type: 'color';
light: string;
Expand Down
Loading