Skip to content

Commit 54f5764

Browse files
committed
feat(components): ✨ add useScaleAnimation hook which add scale down to tappable components
1 parent 4024544 commit 54f5764

File tree

4 files changed

+318
-288
lines changed

4 files changed

+318
-288
lines changed

src/components/button/Button.tsx

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "react-native";
88

99
import { RenderPropType } from "../../index";
10-
import { Box, Text, Touchable } from "../../primitives";
10+
import { AnimatedBox, Box, Text, Touchable } from "../../primitives";
1111
import { getTextFontFamily, useTailwind, useTheme } from "../../theme";
1212
import {
1313
createComponent,
@@ -16,6 +16,7 @@ import {
1616
styleAdapter,
1717
useOnFocus,
1818
useOnHover,
19+
useScaleAnimation,
1920
} from "../../utils";
2021
import { createIcon } from "../create-icon";
2122
import { Icon } from "../icon";
@@ -115,7 +116,7 @@ const RNButton: React.FC<Partial<ButtonProps>> = forwardRef<
115116
) => {
116117
const { ts, gc } = useTailwind();
117118
const buttonTheme = useTheme("button");
118-
119+
const { handlers, animatedStyle } = useScaleAnimation();
119120
const { onHoverIn, onHoverOut, hovered } = useOnHover();
120121
const { onFocus, onBlur, focused } = useOnFocus();
121122

@@ -266,69 +267,72 @@ const RNButton: React.FC<Partial<ButtonProps>> = forwardRef<
266267
);
267268

268269
return (
269-
<Touchable
270-
style={(touchState: PressableStateCallbackType) => {
271-
return [
272-
ts(
273-
cx(
274-
buttonTheme.base,
275-
buttonTheme.size[size]?.default,
276-
buttonTheme.themeColor[themeColor]?.[variant]?.container
277-
?.wrapper,
278-
isButtonDisabled
279-
? buttonTheme.themeColor[themeColor]?.[variant]?.container
280-
?.disabled
281-
: "",
282-
hovered.value
283-
? buttonTheme.themeColor[themeColor]?.[variant]?.container
284-
?.hover
285-
: "",
286-
touchState.pressed
287-
? buttonTheme.themeColor[themeColor]?.[variant]?.container
288-
?.pressed
289-
: "",
270+
<AnimatedBox style={animatedStyle}>
271+
<Touchable
272+
style={(touchState: PressableStateCallbackType) => {
273+
return [
274+
ts(
275+
cx(
276+
buttonTheme.base,
277+
buttonTheme.size[size]?.default,
278+
buttonTheme.themeColor[themeColor]?.[variant]?.container
279+
?.wrapper,
280+
isButtonDisabled
281+
? buttonTheme.themeColor[themeColor]?.[variant]?.container
282+
?.disabled
283+
: "",
284+
hovered.value
285+
? buttonTheme.themeColor[themeColor]?.[variant]?.container
286+
?.hover
287+
: "",
288+
touchState.pressed
289+
? buttonTheme.themeColor[themeColor]?.[variant]?.container
290+
?.pressed
291+
: "",
292+
),
290293
),
291-
),
292-
focused.value
293-
? Platform.select({
294-
web: {
295-
outline: 0,
296-
boxShadow: `${generateBoxShadow(
297-
buttonTheme.themeColor[themeColor]?.[variant]?.container
298-
?.focus?.offset,
299-
gc(
300-
cx(
301-
buttonTheme.themeColor[themeColor]?.[variant]
302-
?.container?.focus?.color,
303-
),
304-
) as string,
305-
)}`,
306-
borderColor:
307-
buttonTheme.themeColor[themeColor]?.[variant]?.container
308-
?.focus?.borderColor,
309-
},
310-
})
311-
: {},
312-
styleAdapter(style, touchState),
313-
];
314-
}}
315-
{...props}
316-
// Web Callbacks
317-
onHoverIn={onHoverIn}
318-
onHoverOut={onHoverOut}
319-
onFocus={onFocus}
320-
onBlur={onBlur}
321-
// Web Callbacks
322-
// A11y Props
323-
accessible
324-
accessibilityLabel={accesibilityLabel}
325-
accessibilityRole="button"
326-
// A11y Props
327-
ref={ref}
328-
disabled={isButtonDisabled}
329-
>
330-
{children}
331-
</Touchable>
294+
focused.value
295+
? Platform.select({
296+
web: {
297+
outline: 0,
298+
boxShadow: `${generateBoxShadow(
299+
buttonTheme.themeColor[themeColor]?.[variant]?.container
300+
?.focus?.offset,
301+
gc(
302+
cx(
303+
buttonTheme.themeColor[themeColor]?.[variant]
304+
?.container?.focus?.color,
305+
),
306+
) as string,
307+
)}`,
308+
borderColor:
309+
buttonTheme.themeColor[themeColor]?.[variant]?.container
310+
?.focus?.borderColor,
311+
},
312+
})
313+
: {},
314+
styleAdapter(style, touchState),
315+
];
316+
}}
317+
{...props}
318+
// Web Callbacks
319+
onHoverIn={onHoverIn}
320+
onHoverOut={onHoverOut}
321+
onFocus={onFocus}
322+
onBlur={onBlur}
323+
// Web Callbacks
324+
// A11y Props
325+
accessible
326+
accessibilityLabel={accesibilityLabel}
327+
accessibilityRole="button"
328+
// A11y Props
329+
ref={ref}
330+
disabled={isButtonDisabled}
331+
{...handlers}
332+
>
333+
{children}
334+
</Touchable>
335+
</AnimatedBox>
332336
);
333337
},
334338
);

src/components/checkbox/Checkbox.tsx

Lines changed: 94 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ import { Platform, PressableStateCallbackType } from "react-native";
99
import { useToggleState } from "@react-stately/toggle";
1010

1111
import { Check, Dash } from "../../icons";
12-
import { Box, Text, Touchable, TouchableProps } from "../../primitives";
12+
import {
13+
AnimatedBox,
14+
Box,
15+
Text,
16+
Touchable,
17+
TouchableProps,
18+
} from "../../primitives";
1319
import { getTextFontFamily, useTailwind, useTheme } from "../../theme";
1420
import {
1521
createComponent,
@@ -18,6 +24,7 @@ import {
1824
styleAdapter,
1925
useOnFocus,
2026
useOnHover,
27+
useScaleAnimation,
2128
} from "../../utils";
2229
import { mergeRefs } from "../../utils/mergeRefs";
2330
import { createIcon } from "../create-icon";
@@ -173,6 +180,7 @@ const RNCheckbox: React.FC<Partial<CheckboxProps>> = forwardRef<
173180

174181
const { onHoverIn, onHoverOut, hovered } = useOnHover();
175182
const { onFocus, onBlur, focused } = useOnFocus();
183+
const { handlers, animatedStyle } = useScaleAnimation();
176184

177185
const children = ({
178186
pressed = false,
@@ -331,92 +339,95 @@ const RNCheckbox: React.FC<Partial<CheckboxProps>> = forwardRef<
331339
};
332340

333341
return (
334-
<Touchable
335-
onPress={handleChange}
336-
// Web Callbacks
337-
onHoverIn={onHoverIn}
338-
onHoverOut={onHoverOut}
339-
onFocus={onFocus}
340-
onBlur={onBlur}
341-
// Web Callbacks
342-
// A11y Props
343-
accessibilityLabel={accessibilityLabel}
344-
accessibilityRole="checkbox"
345-
accessibilityState={{
346-
checked: isIndeterminate ? "mixed" : checkboxToggleState.isSelected,
347-
}}
348-
accessibilityValue={{ text: props?.value }}
349-
onAccessibilityTap={handleChange}
350-
// A11y Props
351-
style={(touchState: PressableStateCallbackType) => [
352-
ts(
353-
cx(
354-
checkboxTheme?.label?.common,
355-
index !== 0
356-
? checkboxTheme?.group[checkboxGroupState?.orientation]?.spacing
357-
: "",
358-
description ? checkboxTheme?.label?.withDescription : "",
359-
checkboxTheme.size[size]?.label?.wrapper,
360-
touchState.pressed
361-
? hasOnlyLabel
362-
? checkboxTheme.themeColor[themeColor]?.press?.label
363-
: ""
364-
: "",
365-
hovered.value && hasOnlyLabel
366-
? checkboxTheme.themeColor[themeColor]?.hover?.label
367-
: "",
342+
<AnimatedBox style={animatedStyle}>
343+
<Touchable
344+
onPress={handleChange}
345+
// Web Callbacks
346+
onHoverIn={onHoverIn}
347+
onHoverOut={onHoverOut}
348+
onFocus={onFocus}
349+
onBlur={onBlur}
350+
// Web Callbacks
351+
// A11y Props
352+
accessibilityLabel={accessibilityLabel}
353+
accessibilityRole="checkbox"
354+
accessibilityState={{
355+
checked: isIndeterminate ? "mixed" : checkboxToggleState.isSelected,
356+
}}
357+
accessibilityValue={{ text: props?.value }}
358+
onAccessibilityTap={handleChange}
359+
// A11y Props
360+
style={(touchState: PressableStateCallbackType) => [
361+
ts(
362+
cx(
363+
checkboxTheme?.label?.common,
364+
index !== 0
365+
? checkboxTheme?.group[checkboxGroupState?.orientation]?.spacing
366+
: "",
367+
description ? checkboxTheme?.label?.withDescription : "",
368+
checkboxTheme.size[size]?.label?.wrapper,
369+
touchState.pressed
370+
? hasOnlyLabel
371+
? checkboxTheme.themeColor[themeColor]?.press?.label
372+
: ""
373+
: "",
374+
hovered.value && hasOnlyLabel
375+
? checkboxTheme.themeColor[themeColor]?.hover?.label
376+
: "",
377+
),
368378
),
369-
),
370-
focused.value
371-
? Platform.select({
372-
web: {
373-
outline: 0,
374-
boxShadow: hasOnlyLabel
375-
? `${generateBoxShadow(
376-
checkboxTheme.themeColor[themeColor]?.focus?.label
377-
?.boxShadow?.offset,
378-
gc(
379+
focused.value
380+
? Platform.select({
381+
web: {
382+
outline: 0,
383+
boxShadow: hasOnlyLabel
384+
? `${generateBoxShadow(
385+
checkboxTheme.themeColor[themeColor]?.focus?.label
386+
?.boxShadow?.offset,
387+
gc(
388+
cx(
389+
checkboxTheme.themeColor[themeColor]?.focus?.label
390+
?.boxShadow?.color,
391+
),
392+
) as string,
393+
)}`
394+
: "",
395+
backgroundColor: hasOnlyLabel
396+
? (gc(
379397
cx(
380398
checkboxTheme.themeColor[themeColor]?.focus?.label
381-
?.boxShadow?.color,
399+
?.default,
382400
),
383-
) as string,
384-
)}`
385-
: "",
386-
backgroundColor: hasOnlyLabel
387-
? (gc(
388-
cx(
389-
checkboxTheme.themeColor[themeColor]?.focus?.label
390-
?.default,
391-
),
392-
) as string)
393-
: "transparent",
394-
},
395-
})
396-
: {},
397-
styleAdapter(style, touchState),
398-
]}
399-
ref={checkboxRef}
400-
//@ts-ignore - Web only - Checkbox toggle on Spacebar Press
401-
onKeyDown={Platform.select({
402-
web: (e: any) => {
403-
if (e.code === "Space") {
404-
e.preventDefault();
405-
handleChange();
406-
}
407-
},
408-
default: undefined,
409-
})}
410-
disabled={isDisabled}
411-
>
412-
{(touchState: PressableStateCallbackType) =>
413-
children({
414-
pressed: touchState.pressed,
415-
isHovered: !!hovered.value,
416-
isFocussed: !!focused.value,
417-
})
418-
}
419-
</Touchable>
401+
) as string)
402+
: "transparent",
403+
},
404+
})
405+
: {},
406+
styleAdapter(style, touchState),
407+
]}
408+
ref={checkboxRef}
409+
//@ts-ignore - Web only - Checkbox toggle on Spacebar Press
410+
onKeyDown={Platform.select({
411+
web: (e: any) => {
412+
if (e.code === "Space") {
413+
e.preventDefault();
414+
handleChange();
415+
}
416+
},
417+
default: undefined,
418+
})}
419+
disabled={isDisabled}
420+
{...(description ? {} : handlers)}
421+
>
422+
{(touchState: PressableStateCallbackType) =>
423+
children({
424+
pressed: touchState.pressed,
425+
isHovered: !!hovered.value,
426+
isFocussed: !!focused.value,
427+
})
428+
}
429+
</Touchable>
430+
</AnimatedBox>
420431
);
421432
});
422433

0 commit comments

Comments
 (0)