Skip to content

Commit

Permalink
feat(motion.ts): add refreshed tokens and internal components migrati…
Browse files Browse the repository at this point in the history
…on (#2356)

* feat: init motion presets rfc

* docs: add poc video

* docs: add comparison table and pocs

* feat: add gsap poc

* add layout animations poc with blade components

* feat: add basic API decision

* feat: add api decisions and memes

* feat: add api decisions and memes

* feat: remove unrelated changes

* docs: add morph note

* feat: add video example

* docs: add note for previews

* docs: add more videos

* fix: images

* fix: code alignments

* docs: fix widths of cols

* feat: add chat interface demo

* typo

* fix: width of previews

* feat: update all token values

* feat: motion, migrate internal motion tokens

* fix: ts check

* fix: ts

* fix: switch delay

* fix: durations map

* docs: update animationInteractions docs

* feat: add view transitions API note

* feat: add view transitions API note

* feat: rename framer motion to motion/react

* feat: add framer motion name change note in library table

* docs: add new open questions and conclusions

* fix: change misleading scale heading
  • Loading branch information
saurabhdaware authored Dec 6, 2024
1 parent 3b5d17e commit d432350
Show file tree
Hide file tree
Showing 63 changed files with 304 additions and 285 deletions.
14 changes: 5 additions & 9 deletions packages/blade/docs/tokens/Motion.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ import MovingDiv from '../components/MovingDiv';
const colorScheme = context.store.globals.globals.colorScheme;
return (
<DocsContainer context={context}>
<BladeProvider
key={colorScheme}
themeTokens={bladeTheme}
colorScheme={colorScheme}
>
<BladeProvider key={colorScheme} themeTokens={bladeTheme} colorScheme={colorScheme}>
{children}
</BladeProvider>
</DocsContainer>
Expand Down Expand Up @@ -113,7 +109,7 @@ export const MotionExample = () => {
background-color: ${(props) => props.theme.colors.surface.background.primary.subtle};
animation: ${(props) =>
`resize ${makeMotionTime(props.theme.motion.duration.xgentle)} ${
props.theme.motion.easing.standard.effective
props.theme.motion.easing.standard
} infinite`};
@keyframes resize {
0% {
Expand All @@ -127,7 +123,7 @@ export const MotionExample = () => {
}
}
`;
return <ExampleDiv theme={theme} easing={theme.motion.easing.standard.effective} />;
return <ExampleDiv theme={theme} easing={theme.motion.easing.standard} />;
};

<Motion />
Expand All @@ -153,7 +149,7 @@ const ExampleDiv = styled.div`
props.theme.colors.surface.background.primary.subtle};
animation: ${(props) =>
`resize ${makeMotionTime(props.theme.motion.duration.xgentle)} ${
props.theme.motion.easing.standard.effective
props.theme.motion.easing.standard
} infinite`};
@keyframes resize {
0% {
Expand All @@ -177,7 +173,7 @@ import { makeMotionTime } from '@razorpay/blade/utils';

const CustomComponent = () => {
const { theme } = useTheme();
const easing = theme.motion.easing.standard.effective;
const easing = theme.motion.easing.standard;
const duration = makeMotionTime(theme.motion.duration.xgentle);
const delay = makeMotionTime(theme.motion.delay.short);

Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Accordion/commonStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { makeMotionTime } from '~utils';
const getTransitionDuration = (theme: Theme) => makeMotionTime(theme.motion.duration['2xquick']);

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const getTransitionEasing = (theme: Theme) => theme.motion.easing.standard.effective;
const getTransitionEasing = (theme: Theme) => theme.motion.easing.standard;

const getBackgroundColor = ({
theme,
Expand Down
2 changes: 2 additions & 0 deletions packages/blade/src/components/ActionList/ActionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ const _ActionList = ({ children, testID }: ActionListProps): React.ReactElement
[children],
);

console.log({ actionListOptions });

React.useEffect(() => {
setOptions(actionListOptions);
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,13 @@ const bladeLightTheme: Theme = {
motion: {
...bladeTheme.motion,
easing: {
standard: {
attentive: Easing.bezier(0.5, 0, 0.3, 1.5),
effective: Easing.bezier(0.3, 0, 0.2, 1),
revealing: Easing.bezier(0.5, 0, 0, 1),
wary: Easing.bezier(1, 0.5, 0, 0.5),
},
entrance: {
attentive: Easing.bezier(0.5, 0, 0.3, 1.5),
effective: Easing.bezier(0, 0, 0.2, 1),
revealing: Easing.bezier(0, 0, 0, 1),
},
exit: {
attentive: Easing.bezier(0.7, 0, 0.5, 1),
effective: Easing.bezier(0.17, 0, 1, 1),
revealing: Easing.bezier(0.5, 0, 1, 1),
},
linear: Easing.bezier(0, 0, 0, 0),
entrance: Easing.bezier(0, 0, 0.2, 1),
exit: Easing.bezier(0.17, 0, 1, 1),
standard: Easing.bezier(0.3, 0, 0.2, 1),
emphasized: Easing.bezier(0.5, 0, 0, 1),
overshoot: Easing.bezier(0.5, 0, 0.3, 1.5),
shake: Easing.bezier(1, 0.5, 0, 0.5),
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const StyledBottomSheetBackdrop = styled(BaseBox)<{ isOpen: boolean }>(({ theme,
return {
transitionDuration: `${makeMotionTime(theme.motion.duration.moderate)}`,
transitionTimingFunction: isOpen
? castWebType(theme.motion.easing.entrance.revealing)
: castWebType(theme.motion.easing.exit.revealing),
? castWebType(theme.motion.easing.entrance)
: castWebType(theme.motion.easing.exit),
pointerEvents: isOpen ? 'all' : 'none',
transitionProperty: 'opacity',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ const getProps = ({
borderWidth: variant == 'secondary' ? makeBorderSize(theme.border.width.thin) : '0px',
borderRadius: makeBorderSize(theme.border.radius.medium),
motionDuration: 'duration.xquick',
motionEasing: 'easing.standard.effective',
motionEasing: 'easing.standard',
};

if (isDisabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const StyledButton = styled.button<StyledButtonProps>((props) => {
: theme.colors.interactive.icon[emphasisColor].muted,
transitionProperty: 'color, box-shadow',
transitionDuration: castWebType(makeMotionTime(motionToken.duration.xquick)),
transitionTimingFunction: motionToken.easing.standard.effective as string,
transitionTimingFunction: motionToken.easing.standard as string,

'&:hover:not([disabled])': {
color: theme.colors.interactive.icon[emphasisColor].subtle,
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Card/CardRoot.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const CardRoot = ({
const { theme } = useTheme();
const [isPressed, setIsPressed] = React.useState(false);
const duration = castNativeType(makeMotionTime(theme.motion.duration.xquick));
const easing = castNativeType(theme.motion.easing.standard.effective);
const easing = castNativeType(theme.motion.easing.standard);

const styles = useAnimatedStyle(() => {
return {
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Card/CardRoot.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const StyledCardRoot = styled(BaseBox)<CardRootProps & { isPressed: boolean; isM
// Selected state
boxShadow: `${selectedBorder}${focusRing}`,
transitionDuration: castWebType(makeMotionTime(theme.motion.duration.xquick)),
transitionTimingFunction: castWebType(theme.motion.easing.standard.effective),
transitionTimingFunction: castWebType(theme.motion.easing.standard),
transitionProperty: 'transform, box-shadow',
cursor: as === 'label' ? 'pointer' : 'initial',

Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Carousel/Carousel.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const CarouselContainer = styled(BaseBox)<{
width: '100px',
height: '100%',
transitionDuration: castWebType(makeMotionTime(theme.motion.duration.gentle)),
transitionTimingFunction: castWebType(theme.motion.easing.standard.effective),
transitionTimingFunction: castWebType(theme.motion.easing.standard),
transitionProperty: 'opacity',
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const StyledIndicatorButton = ({
...props
}: IndicatorButtonProps & { accessibilityLabel?: string }): React.ReactElement => {
const { theme } = useTheme();
const easing = castNativeType(theme.motion.easing.standard.effective);
const easing = castNativeType(theme.motion.easing.standard);
const duration = castNativeType(makeMotionTime(theme.motion.duration.gentle));

const style = useAnimatedStyle(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const getIndicatorButtonStyles = ({
blue: theme.colors.interactive.icon.primary.subtle,
};

const easing = castWebType(theme.motion.easing.standard.effective);
const easing = castWebType(theme.motion.easing.standard);
const duration = castWebType(makeMotionTime(theme.motion.duration.gentle));

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const getNavigationButtonStyles = (props: {
: {
transitionProperty: 'color, box-shadow',
transitionDuration: castWebType(makeMotionTime(motionToken.duration.xquick)),
transitionTimingFunction: castWebType(motionToken.easing.standard.effective),
transitionTimingFunction: castWebType(motionToken.easing.standard),
boxShadow: variant === 'filled' ? castWebType(theme.elevation.midRaised) : undefined,

'&:hover': {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const StyledFade = styled(Animated.View)<{ styles: CSSObject }>(({ styles }) =>
const Fade = ({ children, show, styles }: FadeProps) => {
const { theme } = useTheme();

const fadeInEasing = (theme.motion.easing.entrance.effective as unknown) as EasingFn;
const fadeOutEasing = (theme.motion.easing.exit.effective as unknown) as EasingFn;
const fadeInEasing = (theme.motion.easing.entrance as unknown) as EasingFn;
const fadeOutEasing = (theme.motion.easing.exit as unknown) as EasingFn;
const fadeIn = new Keyframe({
from: {
transform: [{ scale: 0.6 }],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ const Fade = ({ show, children, styles }: FadeProps) => {

const duration = theme.motion.duration.xquick;
const enter = css`
animation: ${fadeIn} ${makeMotionTime(duration)}
${theme.motion.easing.entrance.effective as string};
animation: ${fadeIn} ${makeMotionTime(duration)} ${theme.motion.easing.entrance as string};
`;

const exit = css`
animation: ${fadeOut} ${makeMotionTime(duration)}
${theme.motion.easing.exit.effective as string};
animation: ${fadeOut} ${makeMotionTime(duration)} ${theme.motion.easing.exit as string};
`;

// if show is undefined do not initialize the animation to prevent flash of animation
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Chip/chipTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ const chipTextSizes = {

const chipMotionTokens: Record<'duration' | 'easing', DurationString | EasingString> = {
duration: 'duration.xquick',
easing: 'easing.standard.effective',
easing: 'easing.standard',
};

export {
Expand Down
4 changes: 2 additions & 2 deletions packages/blade/src/components/Collapsible/commonStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ const getCollapsibleBodyContentBoxProps = ({
const getOpacity = ({ isExpanded }: { isExpanded: boolean }): number => (isExpanded ? 1 : 0.8);

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const getTransitionDuration = (theme: Theme) => makeMotionTime(theme.motion.duration.xmoderate);
const getTransitionDuration = (theme: Theme) => makeMotionTime(theme.motion.duration.moderate);

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const getTransitionEasing = (theme: Theme) => theme.motion.easing.standard.effective;
const getTransitionEasing = (theme: Theme) => theme.motion.easing.standard;

const getCollapsibleChevronIconTransforms = (): {
transformExpanded: number;
Expand Down
12 changes: 6 additions & 6 deletions packages/blade/src/components/Drawer/Drawer.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ const AnimatedDrawerContainer = styled(BaseBox)<{
isVisible: boolean;
}>(({ theme, isFirstDrawerInStack, isVisible }) => {
const entranceTransition: CSSProperties['transition'] = `all ${castWebType(
castWebType(makeMotionTime(theme.motion.duration.gentle)),
)} ${castWebType(theme.motion.easing.entrance.revealing)}`;
castWebType(makeMotionTime(theme.motion.duration.xmoderate)),
)} ${castWebType(theme.motion.easing.entrance)}`;

const exitTransition: CSSProperties['transition'] = `all
${castWebType(makeMotionTime(theme.motion.duration.xmoderate))}
${castWebType(theme.motion.easing.exit.revealing)}`;
${castWebType(makeMotionTime(theme.motion.duration.moderate))}
${castWebType(theme.motion.easing.exit)}`;

return {
opacity: isVisible ? 1 : 0,
Expand All @@ -52,13 +52,13 @@ const DrawerOverlay = styled(FloatingOverlay)(({ theme }) => {
opacity: 0,
transition: `opacity
${makeMotionTime(theme.motion.duration.xmoderate)}
${castWebType(theme.motion.easing.exit.revealing)}`,
${castWebType(theme.motion.easing.exit)}`,
backgroundColor: theme.colors.overlay.background.subtle,

[`&.${SHOW_DRAWER}`]: {
opacity: 1,
transition: `opacity ${makeMotionTime(theme.motion.duration.gentle)} ${castWebType(
theme.motion.easing.entrance.revealing,
theme.motion.easing.entrance,
)}`,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const getFileUploadInputHoverTokens = (): SelectorInputHoverTokens => {

const fileUploadMotionTokens: Record<'duration' | 'easing', DurationString | EasingString> = {
duration: 'duration.2xquick',
easing: 'easing.standard.effective',
easing: 'easing.standard',
};

const fileUploadHeightTokens = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const getHoverStyles = ({
return {
borderColor: borderColor ? getIn(theme, borderColor) : undefined,
backgroundColor: getIn(theme, backgroundColor),
transitionTimingFunction: theme.motion.easing.standard.effective as string,
transitionTimingFunction: theme.motion.easing.standard as string,
transitionDuration: castWebType(makeMotionTime(theme.motion.duration['2xquick'])),
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const _AnimatedBaseInputWrapper: React.ForwardRefRenderFunction<
showAllTags ? baseInputWrapperMaxHeight[rest.size] : baseInputHeight[rest.size],
{
duration: theme.motion.duration.xquick,
easing: castNativeType(theme.motion.easing.exit.effective),
easing: castNativeType(theme.motion.easing.exit),
},
(isComplete) => {
if (isComplete && !showAllTags) {
Expand Down Expand Up @@ -122,11 +122,10 @@ const _AnimatedBaseInputWrapper: React.ForwardRefRenderFunction<
),
),
easing: castNativeType(
getIn(
theme.motion.easing,
theme.motion.easing[
baseInputBorderBackgroundMotion[rest.currentInteraction === 'focus' ? 'enter' : 'exit']
.easing,
),
.easing
],
),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const StyledBaseInputWrapper = styled(BaseBox)<
}),
transitionProperty: 'background-color',
transitionDuration: castWebType(makeMotionTime(props.theme.motion.duration.xquick)),
transitionTimingFunction: castWebType(props.theme.motion.easing.standard.effective),
transitionTimingFunction: castWebType(props.theme.motion.easing.standard),
},
':focus-within': {
...getInputBackgroundAndBorderStyles({
Expand Down Expand Up @@ -113,12 +113,12 @@ to {

const expandTransition = css`
animation: ${expandAnimation} ${makeMotionTime(motion.duration.quick)}
${String(motion.easing.entrance.effective)};
${String(motion.easing.entrance)};
`;

const collapseTransition = css`
animation: ${collapseAnimation} ${makeMotionTime(motion.duration.quick)}
${String(motion.easing.exit.effective)};
${String(motion.easing.exit)};
`;

const noTransition = css`
Expand Down
7 changes: 3 additions & 4 deletions packages/blade/src/components/Input/BaseInput/BaseInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -752,11 +752,10 @@ const FocusRingWrapper = styled(BaseBox)<{
),
),
transitionTimingFunction: castWebType(
getIn(
theme.motion.easing,
theme.motion.easing[
baseInputBorderBackgroundMotion[currentInteraction === 'focus' ? 'enter' : 'exit']
.easing,
),
.easing
],
),
}
: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export const baseInputBorderWidth = {
} as const;

export const baseInputBorderBackgroundMotion = {
enter: { duration: 'xgentle', easing: 'standard.revealing' },
exit: { duration: 'gentle', easing: 'standard.effective' },
enter: { duration: 'xgentle', easing: 'emphasized' },
exit: { duration: 'gentle', easing: 'standard' },
} as const;

export const baseInputPaddingTokens = {
Expand Down
Loading

0 comments on commit d432350

Please sign in to comment.