Skip to content

Commit

Permalink
feat: add rounded edges and side label to S2 progress bar (adobe#6918)
Browse files Browse the repository at this point in the history
* feat: add rounded edges and side label to progress bar

* only add margin if label exists
  • Loading branch information
yihuiliao committed Aug 22, 2024
1 parent b4093df commit 72ec2f5
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 16 deletions.
5 changes: 3 additions & 2 deletions packages/@react-spectrum/s2/src/Meter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export interface MeterProps extends Omit<AriaMeterProps, 'children' | 'className

export const MeterContext = createContext<ContextValue<MeterProps, DOMRefValue<HTMLDivElement>>>(null);

const wrapper = style<MeterStyleProps>({
const wrapper = style({
...bar(),
width: {
default: 208,
Expand Down Expand Up @@ -123,7 +123,8 @@ function Meter(props: MeterProps, ref: DOMRef<HTMLDivElement>) {
className={UNSAFE_className + wrapper({
size,
variant,
staticColor
staticColor,
labelPosition: 'top'
}, styles)}>
{({percentage, valueText}) => (
<>
Expand Down
28 changes: 22 additions & 6 deletions packages/@react-spectrum/s2/src/ProgressBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from 'react-aria-components';
import {bar, track} from './bar-utils' with {type: 'macro'};
import {createContext, forwardRef, ReactNode} from 'react';
import {DOMRef, DOMRefValue} from '@react-types/shared';
import {DOMRef, DOMRefValue, LabelPosition} from '@react-types/shared';
import {FieldLabel} from './Field';
import {fieldLabel, getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
import {keyframes} from '../style/style-macro' with {type: 'macro'};
Expand All @@ -37,8 +37,16 @@ interface ProgressBarStyleProps {
* Whether presentation is indeterminate when progress isn't known.
*/
isIndeterminate?: boolean,
/** The static color style to apply. Useful when the button appears over a color background. */
staticColor?: 'white' | 'black'
/**
* The static color style to apply. Useful when the button appears over a color background.
*/
staticColor?: 'white' | 'black',
/**
* The label's overall position relative to the element it is labeling.
* @default 'top'
*/
labelPosition?: LabelPosition

}

export interface ProgressBarProps extends Omit<AriaProgressBarProps, 'children' | 'className' | 'style'>, ProgressBarStyleProps, StyleProps {
Expand Down Expand Up @@ -89,6 +97,7 @@ const trackStyles = style({
const fill = style<ProgressBarStyleProps>({
height: 'full',
borderStyle: 'none',
borderRadius: 'full',
backgroundColor: {
default: 'accent',
staticColor: {
Expand Down Expand Up @@ -117,17 +126,24 @@ const indeterminateAnimation = style({

function ProgressBar(props: ProgressBarProps, ref: DOMRef<HTMLDivElement>) {
[props, ref] = useSpectrumContextProps(props, ref, ProgressBarContext);
let {label, size = 'M', staticColor, isIndeterminate, UNSAFE_style, UNSAFE_className = ''} = props;
let {
label, size = 'M',
staticColor,
isIndeterminate,
labelPosition = 'top',
UNSAFE_style,
UNSAFE_className = ''
} = props;
let domRef = useDOMRef(ref);
return (
<AriaProgressBar
{...props}
ref={domRef}
style={UNSAFE_style}
className={UNSAFE_className + wrapper({...props, size}, props.styles)}>
className={UNSAFE_className + wrapper({...props, size, labelPosition}, props.styles)}>
{({percentage, valueText}) => (
<>
{label && <FieldLabel size={size} labelAlign="start" labelPosition="top" staticColor={staticColor}>{label}</FieldLabel>}
{label && <FieldLabel size={size} labelAlign="start" labelPosition={labelPosition} staticColor={staticColor}>{label}</FieldLabel>}
{label && <span className={valueStyles({size, labelAlign: 'end', staticColor})}>{valueText}</span>}
<div className={trackStyles({...props})}>
<div
Expand Down
41 changes: 33 additions & 8 deletions packages/@react-spectrum/s2/src/bar-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,51 @@ import {centerPadding} from './style-utils' with {type: 'macro'};
export const bar = () => ({
position: 'relative',
display: 'grid',
gridTemplateColumns: '1fr auto',
gridTemplateAreas: [
'label value',
'bar bar'
],
gridTemplateColumns: {
labelPosition: {
top: ['1fr', 'auto'],
side: ['auto', '1fr']
}
},
gridTemplateAreas: {
labelPosition: {
top: [
'label value',
'bar bar',
],
side: [
'label bar value'
]
}
},
alignItems: 'baseline',
isolation: 'isolate',
minWidth: 48, // progress-bar-minimum-width
maxWidth: '[768px]', // progress-bar-maximum-width
minHeight: 'control',
'--field-height': {
type: 'height',
value: 'control'
},
'--track-to-label': {
type: 'height',
value: 4
},
// Spectrum defines the field label/help text with a (minimum) height, with text centered inside.
// Calculate what the gap should be based on the height and line height.
// Use a variable here rather than rowGap since it is applied to the children as padding.
// This allows the gap to collapse when the label/help text is not present.
// Eventually this may be possible to do in pure CSS: https://github.com/w3c/csswg-drafts/issues/5813
'--field-gap': {
type: 'rowGap',
value: centerPadding()
value: centerPadding('calc(var(--field-height) + var(--track-to-label))')
},

columnGap: 12 // spacing-200
} as const);

export const track = () => ({
gridArea: 'bar',
overflow: 'hidden',
marginTop: 4,
borderRadius: 'full',
backgroundColor: {
default: 'gray-300',
Expand Down

0 comments on commit 72ec2f5

Please sign in to comment.