Skip to content

Commit 00fce14

Browse files
authored
fix(s2): Fix Switch in RTL locales (#8534)
1 parent fe5e1b6 commit 00fce14

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

packages/@react-spectrum/s2/src/Switch.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import {
1414
Switch as AriaSwitch,
1515
SwitchProps as AriaSwitchProps,
1616
ContextValue,
17-
SwitchRenderProps
17+
SwitchRenderProps,
18+
useLocale
1819
} from 'react-aria-components';
1920
import {baseColor, focusRing, fontRelative, style} from '../style' with {type: 'macro'};
2021
import {CenterBaseline} from './CenterBaseline';
2122
import {controlFont, controlSize, getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
2223
import {createContext, forwardRef, ReactNode, useContext, useRef} from 'react';
23-
import {FocusableRef, FocusableRefValue, GlobalDOMAttributes} from '@react-types/shared';
24+
import {Direction, FocusableRef, FocusableRefValue, GlobalDOMAttributes} from '@react-types/shared';
2425
import {FormContext, useFormProps} from './Form';
2526
import {pressScale} from './pressScale';
2627
import {useFocusableRef} from '@react-spectrum/utils';
@@ -124,7 +125,7 @@ const handle = style<RenderProps>({
124125
});
125126

126127
// Use an inline style to calculate the transform so we can combine it with the press scale.
127-
const transformStyle = ({isSelected}: SwitchRenderProps) => ({
128+
const transformStyle = ({isSelected, direction}: SwitchRenderProps & {direction: Direction}) => {
128129
// In the default state, the handle is 8px smaller than the track. When selected it grows to 6px smaller than the track.
129130
// Normally this could be calculated as a scale transform with (trackHeight - 8px) / trackHeight, however,
130131
// CSS does not allow division with units. To solve this we use a 3d perspective transform. Perspective is the
@@ -143,11 +144,15 @@ const transformStyle = ({isSelected}: SwitchRenderProps) => ({
143144
//
144145
// defaultPerspective = trackHeight - 8px
145146
// selectedPerspective = 2 * (trackHeight - 6px)
146-
transform: isSelected
147-
// The selected state also translates the X position to the end of the track (minus the borders).
148-
? 'translateX(calc(var(--trackWidth) - 100% - 4px)) perspective(calc(2 * (var(--trackHeight) - 6px))) translateZ(-4px)'
149-
: 'perspective(calc(var(--trackHeight) - 8px)) translateZ(-4px)'
150-
});
147+
const placement =
148+
direction === 'ltr'
149+
? // The selected state also translates the X position to the end of the track (minus the borders).
150+
'translateX(calc(var(--trackWidth) - 100% - 4px)) perspective(calc(2 * (var(--trackHeight) - 6px))) translateZ(-4px)'
151+
: 'translateX(calc(100% - var(--trackWidth) + 4px)) perspective(calc(2 * (var(--trackHeight) - 6px))) translateZ(-4px)';
152+
return {
153+
transform: isSelected ? placement : 'perspective(calc(var(--trackHeight) - 8px)) translateZ(-4px)'
154+
};
155+
};
151156

152157
/**
153158
* Switches allow users to turn an individual option on or off.
@@ -160,6 +165,7 @@ export const Switch = /*#__PURE__*/ forwardRef(function Switch(props: SwitchProp
160165
let domRef = useFocusableRef(ref, inputRef);
161166
let handleRef = useRef(null);
162167
let isInForm = !!useContext(FormContext);
168+
let {direction} = useLocale();
163169
props = useFormProps(props);
164170
return (
165171
<AriaSwitch
@@ -179,7 +185,7 @@ export const Switch = /*#__PURE__*/ forwardRef(function Switch(props: SwitchProp
179185
})}>
180186
<div
181187
ref={handleRef}
182-
style={pressScale(handleRef, transformStyle)(renderProps)}
188+
style={pressScale(handleRef, transformStyle)({...renderProps, direction})}
183189
className={handle(renderProps)} />
184190
</div>
185191
</CenterBaseline>

0 commit comments

Comments
 (0)