Skip to content

Commit f607066

Browse files
authored
Merge pull request #4952 from GeekyAnts/fix/slider-states
Fix/slider states
2 parents 662eee9 + 962734b commit f607066

File tree

6 files changed

+175
-18
lines changed

6 files changed

+175
-18
lines changed

src/components/primitives/Slider/Slider.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ function Slider({ isDisabled, isReadOnly, ...props }: ISliderProps, ref?: any) {
7070
isReadOnly: isReadOnly,
7171
onTrackLayout: onLayout,
7272
thumbSize: resolvedProps.thumbSize,
73-
sliderSize: resolvedProps.sliderSize,
73+
sliderSize: resolvedProps.sliderTrackHeight,
74+
_interactionBox: resolvedProps._interactionBox,
7475
};
7576
// eslint-disable-next-line react-hooks/exhaustive-deps
7677
}, [
@@ -83,7 +84,7 @@ function Slider({ isDisabled, isReadOnly, ...props }: ISliderProps, ref?: any) {
8384
isReadOnly,
8485
onLayout,
8586
resolvedProps.thumbSize,
86-
resolvedProps.sliderSize,
87+
resolvedProps.sliderTrackHeight,
8788
]);
8889

8990
//TODO: refactor for responsive prop

src/components/primitives/Slider/SliderThumb.tsx

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,24 @@ import type { ISliderThumbProps } from './types';
88
import Box from '../Box';
99
import { SliderContext } from './Context';
1010
import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps';
11+
import { useHover } from '@react-native-aria/interactions';
12+
import { mergeRefs } from '../../../utils';
13+
import { extractInObject, stylingProps } from '../../../theme/tools/utils';
14+
import { Stack } from '../Stack';
15+
import { Center } from '../../composites/Center';
1116

1217
function SliderThumb(props: ISliderThumbProps, ref: any) {
18+
const [isPressed, setIsPressed] = React.useState(false);
19+
20+
const [isFocused, setIsFocused] = React.useState(false);
21+
const handleFocus = (focusState: boolean, callback: any) => {
22+
setIsFocused(focusState);
23+
callback();
24+
};
25+
26+
const _ref = React.useRef(null);
27+
const { isHovered } = useHover({}, _ref);
28+
1329
const {
1430
state,
1531
trackLayout,
@@ -18,16 +34,31 @@ function SliderThumb(props: ISliderThumbProps, ref: any) {
1834
thumbSize,
1935
isReadOnly,
2036
isDisabled,
37+
_interactionBox: interactionBoxContext,
2138
} = React.useContext(SliderContext);
22-
const resolvedProps = usePropsResolution(
39+
const {
40+
onFocus,
41+
onBlur,
42+
_stack,
43+
_interactionBox,
44+
...resolvedProps
45+
} = usePropsResolution(
2346
'SliderThumb',
2447
{
2548
size: thumbSize,
49+
_interactionBox: interactionBoxContext,
2650
colorScheme,
2751
...props,
2852
},
29-
{ isDisabled, isReadOnly }
53+
{
54+
isDisabled,
55+
isReadOnly,
56+
isPressed,
57+
isFocused,
58+
isHovered,
59+
}
3060
);
61+
3162
const inputRef = React.useRef(null);
3263
const { thumbProps, inputProps } = useSliderThumb(
3364
{
@@ -39,6 +70,10 @@ function SliderThumb(props: ISliderThumbProps, ref: any) {
3970
state
4071
);
4172

73+
React.useEffect(() => {
74+
setIsPressed(state.isThumbDragging(0));
75+
}, [state]);
76+
4277
const thumbAbsoluteSize = useToken('sizes', resolvedProps.size);
4378

4479
const thumbStyles: any = {
@@ -59,6 +94,23 @@ function SliderThumb(props: ISliderThumbProps, ref: any) {
5994
thumbStyles.transform.push({
6095
scale: state.isThumbDragging(0) ? resolvedProps.scaleOnPressed : 1,
6196
});
97+
98+
const [layoutProps, nonLayoutProps] = extractInObject(resolvedProps, [
99+
...stylingProps.margin,
100+
...stylingProps.layout,
101+
...stylingProps.flexbox,
102+
...stylingProps.position,
103+
...stylingProps.outline,
104+
]);
105+
106+
const [
107+
accessibilityProps,
108+
nonAccessibilityProps,
109+
] = extractInObject(nonLayoutProps, [
110+
'accessibilityRole',
111+
'accessibilityState',
112+
]);
113+
62114
//TODO: refactor for responsive prop
63115
if (useHasResponsiveProps(props)) {
64116
return null;
@@ -69,17 +121,30 @@ function SliderThumb(props: ISliderThumbProps, ref: any) {
69121
position="absolute"
70122
{...thumbProps}
71123
{...resolvedProps}
72-
ref={ref}
73-
style={[thumbStyles, props.style]}
124+
{...accessibilityProps}
125+
{...layoutProps}
126+
style={[thumbStyles, resolvedProps.style]}
127+
onFocus={(e: any) => {
128+
handleFocus(true, onFocus ? () => onFocus(e) : () => {});
129+
}}
130+
onBlur={(e: any) => {
131+
handleFocus(false, onBlur ? () => onBlur(e) : () => {});
132+
}}
74133
// {...(isReadOnly && _readOnly)}
75134
// {...(isDisabled && _disabled)}
135+
ref={mergeRefs([_ref, ref])}
76136
>
77-
{props.children}
78-
{Platform.OS === 'web' && (
79-
<VisuallyHidden>
80-
<input ref={inputRef} {...inputProps} />
81-
</VisuallyHidden>
82-
)}
137+
<Stack {..._stack}>
138+
<Box {..._interactionBox} />
139+
<Center {...nonAccessibilityProps}>
140+
{props.children}
141+
{Platform.OS === 'web' && (
142+
<VisuallyHidden>
143+
<input ref={inputRef} {...inputProps} />
144+
</VisuallyHidden>
145+
)}
146+
</Center>
147+
</Stack>
83148
</Box>
84149
);
85150
}

src/components/primitives/Slider/types.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import type { MutableRefObject } from 'react';
22
import type { CustomProps } from '../../../components/types';
33
import type { InterfaceBoxProps } from '../Box';
44
import type { ColorSchemeType } from '../../../components/types';
5+
import type { ResponsiveValue } from '../../types';
6+
import type { ISizes } from '../../../theme/base/sizes';
57

68
export interface InterfaceSliderProps extends InterfaceBoxProps<ISliderProps> {
79
/** The current value of the Slider */
@@ -52,6 +54,14 @@ export interface InterfaceSliderProps extends InterfaceBoxProps<ISliderProps> {
5254
_disabled?: any;
5355
/** Props applied if isReadOnly is true. */
5456
_readOnly?: any;
57+
/** Prop applied to change slider track height */
58+
sliderTrackHeight?: ResponsiveValue<ISizes | (string & {}) | number>;
59+
/**Prop applied to change size of slider thumb */
60+
thumbSize?: ResponsiveValue<ISizes | (string & {}) | number>;
61+
/**
62+
* You can style interaction box around the checkbox using this.
63+
*/
64+
_interactionBox?: Omit<Partial<ISliderThumbProps>, '_interactionBox'>;
5565
}
5666

5767
export interface ISliderTrackProps
@@ -91,6 +101,18 @@ export interface ISliderThumbProps
91101
_disabled?: any;
92102
/** Props applied if isReadOnly is true. */
93103
_readOnly?: any;
104+
/**
105+
* Props to be passed to the slider thumb when button is hovered.
106+
*/
107+
_hover?: Omit<Partial<ISliderThumbProps>, '_hover'>;
108+
/**
109+
* Props to be passed to the slider thumb when button is pressed.
110+
*/
111+
_pressed?: Omit<Partial<ISliderThumbProps>, '_pressed'>;
112+
/**
113+
* Props to be passed to the slider thumb when button is focused.
114+
*/
115+
_focus?: Omit<Partial<ISliderThumbProps>, '_focus'>;
94116
}
95117

96118
export type ISliderComponentType = ((

src/theme/components/slider.ts

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,91 @@ export const SliderTrack = {
2727

2828
export const SliderThumb = {
2929
baseStyle: (props: any) => {
30-
let { colorScheme } = props;
30+
const { colorScheme } = props;
31+
const { primary } = props.theme.colors;
3132
return {
3233
borderRadius: 'full',
3334
zIndex: 999,
3435
alignItems: 'center',
3536
justifyContent: 'center',
36-
scaleOnPressed: 1.2,
37+
scaleOnPressed: 1,
38+
_interactionBox: {
39+
position: 'absolute',
40+
borderRadius: 'full',
41+
zIndex: -1,
42+
},
43+
_stack: {
44+
direction: 'row',
45+
alignItems: 'center',
46+
justifyContent: 'center',
47+
space: 2,
48+
},
3749
_light: {
3850
bg: `${colorScheme}.600`,
51+
_hover: {
52+
_web: {
53+
outlineWidth: '4px',
54+
outlineColor: primary[300],
55+
outlineStyle: 'solid',
56+
},
57+
},
58+
_focus: {
59+
_web: {
60+
outlineWidth: '2px',
61+
outlineColor: primary[400],
62+
outlineStyle: 'solid',
63+
},
64+
},
65+
_pressed: {
66+
_interactionBox: {
67+
borderWidth: '8',
68+
borderColor: `${colorScheme}.300`,
69+
},
70+
},
3971
},
4072
_dark: {
4173
bg: `${colorScheme}.500`,
74+
_hover: {
75+
_web: {
76+
outlineWidth: '4px',
77+
outlineColor: primary[800],
78+
outlineStyle: 'solid',
79+
},
80+
},
81+
_focus: {
82+
_web: {
83+
outlineWidth: '2px',
84+
outlineColor: primary[400],
85+
outlineStyle: 'solid',
86+
},
87+
},
88+
_pressed: {
89+
_interactionBox: {
90+
borderWidth: '8',
91+
borderColor: `${colorScheme}.800`,
92+
},
93+
},
94+
},
95+
// shadow: 6,
96+
_web: {
97+
cursor: 'pointer',
4298
},
43-
shadow: 6,
4499
};
45100
},
46101
defaultProps: {
47102
colorScheme: 'primary',
48103
},
104+
sizes: {
105+
lg: {
106+
_interactionBox: '3',
107+
},
108+
md: {
109+
_interactionBox: '2',
110+
},
111+
sm: {
112+
_interactionBox: '2.5',
113+
},
114+
},
49115
};
50116

51117
export const SliderFilledTrack = {
@@ -79,9 +145,9 @@ export const SliderFilledTrack = {
79145
};
80146

81147
const sizes = {
82-
lg: { thumbSize: 6, sliderSize: 6 },
83-
md: { thumbSize: 5, sliderSize: 5 },
84-
sm: { thumbSize: 4, sliderSize: 4 },
148+
lg: { thumbSize: 6, sliderTrackHeight: 6, _interactionBox: { p: '3' } },
149+
md: { thumbSize: 5, sliderTrackHeight: 5, _interactionBox: { p: '2.5' } },
150+
sm: { thumbSize: 4, sliderTrackHeight: 4, _interactionBox: { p: '2' } },
85151
};
86152

87153
export const Slider = {

src/theme/styled-system.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ export const typography = {
566566
const extraProps = {
567567
outline: true,
568568
outlineWidth: true,
569+
outlineColor: true,
570+
outlineStyle: true,
569571
shadow: {
570572
scale: 'shadows',
571573
},

src/theme/tools/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export const stylingProps = {
104104
'order',
105105
],
106106
position: ['position', 'zIndex', 'top', 'right', 'bottom', 'left'],
107+
outline: ['outlineWidth', 'outlineColor', 'outlineStyle'],
107108
background: ['bg', 'backgroundColor', 'bgColor'],
108109
};
109110
export type Dict = Record<string, any>;

0 commit comments

Comments
 (0)