Skip to content
Merged
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
16 changes: 11 additions & 5 deletions static/app/components/core/form/field/rangeField.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface TestFormProps {
label: string;
defaultValue?: number;
disabled?: boolean | string;
formatLabel?: (value: number | '') => React.ReactNode;
formatOptions?: Intl.NumberFormatOptions;
hintText?: string;
max?: number;
min?: number;
Expand All @@ -25,7 +25,7 @@ function TestForm({
min = 0,
max = 100,
step,
formatLabel,
formatOptions,
}: TestFormProps) {
const form = useScrapsForm({
...defaultFormOptions,
Expand All @@ -46,7 +46,7 @@ function TestForm({
min={min}
max={max}
step={step}
formatLabel={formatLabel}
formatOptions={formatOptions}
/>
</field.Layout.Row>
)}
Expand Down Expand Up @@ -177,8 +177,14 @@ describe('RangeField props', () => {
expect(screen.getByRole('slider')).toHaveAttribute('step', '10');
});

it('supports formatLabel prop', () => {
render(<TestForm label="Volume" formatLabel={v => `${v}%`} defaultValue={50} />);
it('supports formatOptions prop', () => {
render(
<TestForm
label="Volume"
formatOptions={{style: 'unit', unit: 'percent'}}
defaultValue={50}
/>
);

// The label shows on hover/focus, just verify the slider renders
expect(screen.getByRole('slider')).toBeInTheDocument();
Expand Down
12 changes: 9 additions & 3 deletions static/app/components/core/slider/slider.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,15 @@ describe('Slider', () => {
});
});

describe('formatLabel', () => {
describe('formatOptions', () => {
it('formats the value label', () => {
render(<Slider defaultValue={42} formatLabel={v => `${v}%`} aria-label="Test" />);
render(
<Slider
defaultValue={42}
formatOptions={{style: 'unit', unit: 'percent'}}
aria-label="Test"
/>
);
// 42% only appears in the value label (not in edge labels since 42 != min or max)
expect(screen.getByText('42%')).toBeInTheDocument();
});
Expand All @@ -152,7 +158,7 @@ describe('Slider', () => {
<Slider
defaultValue={25}
ticks={{count: 3, labels: true}}
formatLabel={v => `$${v}`}
formatOptions={{style: 'currency', currency: 'USD', maximumFractionDigits: 0}}
aria-label="Test"
/>
);
Expand Down
92 changes: 47 additions & 45 deletions static/app/components/core/slider/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ interface BaseProps extends Omit<
> {
defaultValue?: number;
disabled?: boolean;
/** @deprecated Use `formatOptions` (Intl.NumberFormatOptions) instead. */
formatLabel?: (value: number | '') => React.ReactNode;
/** Intl.NumberFormat options for automatic numeric formatting */
formatOptions?: Intl.NumberFormatOptions;
/** Intl.NumberFormat options for automatic numeric formatting. Pass `'hidden'` to hide all labels. */
formatOptions?: Intl.NumberFormatOptions | 'hidden';
/** ID applied to the hidden input element (enables label `htmlFor` linking) */
id?: string;
max?: number;
Expand Down Expand Up @@ -55,7 +53,6 @@ export function Slider({
step = 1,
disabled = false,
ticks,
formatLabel,
Comment thread
cursor[bot] marked this conversation as resolved.
formatOptions,
name,
id,
Comment thread
sentry[bot] marked this conversation as resolved.
Expand All @@ -78,7 +75,8 @@ export function Slider({

const htmlProps = restProps;

const numberFormatter = useNumberFormatter(formatOptions ?? {});
const isHidden = formatOptions === 'hidden';
const numberFormatter = useNumberFormatter(isHidden ? {} : (formatOptions ?? {}));

const ariaProps: AriaSliderProps = {
minValue: min,
Expand Down Expand Up @@ -142,11 +140,11 @@ export function Slider({
const getFormattedValue = useCallback(
(val: number | '') => {
if (val === '') {
return formatLabel ? formatLabel('') : '';
return '';
}
return formatLabel ? formatLabel(val) : state.getFormattedValue(val);
return state.getFormattedValue(val);
},
[formatLabel, state]
[state]
);

const hasTicks = allTickValues.length > 0;
Expand Down Expand Up @@ -193,44 +191,48 @@ export function Slider({
</VisuallyHidden>
</SliderThumbHitbox>

<ValueLabel
aria-hidden
style={
{
'--thumb-value': `${thumbPercent * 100}%`,
'--thumb-offset': `${(2 * thumbPercent - 1) * 12}px`,
} as React.CSSProperties
}
>
{getFormattedValue(thumbValue)}
</ValueLabel>
{!isHidden && (
<ValueLabel
aria-hidden
style={
{
'--thumb-value': `${thumbPercent * 100}%`,
'--thumb-offset': `${(2 * thumbPercent - 1) * 12}px`,
} as React.CSSProperties
}
>
{getFormattedValue(thumbValue)}
</ValueLabel>
)}
</TrackArea>

<TrackLabels aria-hidden>
<TrackLabel data-position="start" style={{transitionDelay: '0ms'}}>
{getFormattedValue(min)}
</TrackLabel>
{hasTicks &&
intermediateTickValues.map((tickValue, index) => (
<TrackLabel
key={tickValue}
data-intermediate
data-show={ticks?.labels || undefined}
style={{
transitionDelay: `${((index + 1) * tickDelay).toFixed(2)}ms`,
left: `${(state.getValuePercent(tickValue) * 100).toFixed(2)}%`,
}}
>
{getFormattedValue(tickValue)}
</TrackLabel>
))}
<TrackLabel
data-position="end"
style={{transitionDelay: `${tickAnimationDuration}ms`}}
>
{getFormattedValue(max)}
</TrackLabel>
</TrackLabels>
{!isHidden && (
<TrackLabels aria-hidden>
<TrackLabel data-position="start" style={{transitionDelay: '0ms'}}>
{getFormattedValue(min)}
</TrackLabel>
{hasTicks &&
intermediateTickValues.map((tickValue, index) => (
<TrackLabel
key={tickValue}
data-intermediate
data-show={ticks?.labels || undefined}
style={{
transitionDelay: `${((index + 1) * tickDelay).toFixed(2)}ms`,
left: `${(state.getValuePercent(tickValue) * 100).toFixed(2)}%`,
}}
>
{getFormattedValue(tickValue)}
</TrackLabel>
))}
<TrackLabel
data-position="end"
style={{transitionDelay: `${tickAnimationDuration}ms`}}
>
{getFormattedValue(max)}
</TrackLabel>
</TrackLabels>
)}
</SliderWrapper>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export function RangeSlider({
value={sliderValue}
aria-valuetext={labelText}
aria-label={props['aria-label']}
formatLabel={showLabel ? undefined : () => null}
formatOptions={showLabel ? undefined : 'hidden'}
/>
{showCustomInput && (
<StyledInput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ function OnionView({
max={100}
value={opacity}
onChange={onOpacityChange}
formatLabel={v => `${v}%`}
formatOptions={{style: 'unit', unit: 'percent'}}
/>
</Flex>
<Text size="sm" variant="muted">
Expand Down
6 changes: 3 additions & 3 deletions static/gsApp/views/amCheckout/components/volumeSliders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function VolumeSliders({
)
.map(category => {
const allowedValues = activePlan.planCategories[category]?.map(
(bucket: any) => bucket.events
bucket => bucket.events
);

if (!allowedValues) {
Expand All @@ -105,8 +105,8 @@ export function VolumeSliders({

const categoryInfo = getCategoryInfoFromPlural(category);

const min = allowedValues[0];
const max = allowedValues.slice(-1)[0];
const min = allowedValues[0]!;
const max = allowedValues.slice(-1)[0]!;

const billingInterval = utils.getShortInterval(activePlan.billingInterval);
const price = utils.displayPrice({cents: eventBucket.price});
Expand Down
Loading