Skip to content

feat(Motion): motion integration branch #2435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .changeset/fluffy-bikes-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@razorpay/blade": major
---

feat(Motion): Release Motion Presets

- Check out [Blade v12 Upgrade Guide](https://github.com/razorpay/blade/blob/master/packages/blade/docs/migration-docs/upgrade-v12.md) for codemod and migration steps
53 changes: 35 additions & 18 deletions packages/blade/.storybook/react/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { DocsContainer } from '@storybook/addon-docs';
import React from 'react';
import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport';
import './global.css';
import { domMax, LazyMotion } from 'framer-motion';

export const parameters = {
// disable snapshot by default and then enable it only for kitchen sink
Expand Down Expand Up @@ -73,6 +74,17 @@ export const parameters = {
],
'Components',
['*', 'Interaction Tests', 'KitchenSink'],
'Motion',
[
'Introduction to Motion',
'Fade',
'Move',
'Slide',
'*',
'AnimateInteractions',
'Stagger',
'Recipes',
],
'Recipes',
],
},
Expand All @@ -95,13 +107,15 @@ export const parameters = {
}
return (
<DocsContainer context={context}>
<BladeProvider
key={`${context.store.globals.globals.themeTokenName}-${context.store.globals.globals.colorScheme}`}
themeTokens={getThemeTokens()}
colorScheme={context.store.globals.globals.colorScheme}
>
{children}
</BladeProvider>
<LazyMotion strict features={domMax}>
<BladeProvider
key={`${context.store.globals.globals.themeTokenName}-${context.store.globals.globals.colorScheme}`}
themeTokens={getThemeTokens()}
colorScheme={context.store.globals.globals.colorScheme}
>
{children}
</BladeProvider>
</LazyMotion>
</DocsContainer>
);
},
Expand Down Expand Up @@ -147,7 +161,8 @@ const StoryCanvas = styled.div<{ context }>(
context.kind.includes('/Carousel') ||
context.kind.includes('/TopNav') ||
context.kind.includes('/Examples') ||
context.kind.includes('/SideNav')
context.kind.includes('/SideNav') ||
context.kind.includes('/Recipes')
? '0rem'
: '2rem'
};
Expand Down Expand Up @@ -180,15 +195,18 @@ export const decorators = [
return (
<ErrorBoundary>
<GlobalStyle />
<BladeProvider
key={`${context.globals.themeTokenName}-${context.globals.colorScheme}`}
themeTokens={getThemeTokens()}
colorScheme={context.globals.colorScheme}
>
<StoryCanvas context={context}>
<Story />
</StoryCanvas>
</BladeProvider>
{/* strict in LazyMotion will make sure we don't use excessive `motion` component in blade components and instead use light weight `m` */}
<LazyMotion strict features={domMax}>
<BladeProvider
key={`${context.globals.themeTokenName}-${context.globals.colorScheme}`}
themeTokens={getThemeTokens()}
colorScheme={context.globals.colorScheme}
>
<StoryCanvas context={context}>
<Story />
</StoryCanvas>
</BladeProvider>
</LazyMotion>
</ErrorBoundary>
);
},
Expand Down Expand Up @@ -228,7 +246,6 @@ export const globalTypes = {
showName: true,
},
},
// TODO: Rebranding - Uncomment this when we fix white-labeling
brandColor: {
name: 'Brand Color',
description: 'Brand Color (You can pass any valid color to BladeProvider)',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { applyTransform } from '@hypermod/utils';
import transformer from '..';

it('should update token for dashboard sidebar example', async () => {
const result = await applyTransform(
transformer,
`
export const SidebarContainer = styled.div<SidebarContainerProps>(
({ theme, isRTUXHomepage, isVisible, isMobile }) => \`
display: flex;
flex-direction: column;
position: fixed;
top: 0;
bottom: 0;
background-color: \${
isRTUXHomepage
? isMobile
? theme.colors.surface.background.cloud.subtle
: 'transparent'
: '#2e3345'
};
transform: translate(-100%,0);
transition: transform \${makeMotionTime(theme.motion.delay.short)} \${
theme.motion.easing.standard.effective
};
\`);
`,
{ parser: 'tsx' },
);

expect(result).toMatchInlineSnapshot(`
"export const SidebarContainer = styled.div<SidebarContainerProps>(
({ theme, isRTUXHomepage, isVisible, isMobile }) => \`
display: flex;
flex-direction: column;
position: fixed;
top: 0;
bottom: 0;
background-color: \${
isRTUXHomepage
? isMobile
? theme.colors.surface.background.cloud.subtle
: 'transparent'
: '#2e3345'
};
transform: translate(-100%,0);
transition: transform \${makeMotionTime(theme.motion.delay.short)} \${
theme.motion.easing.standard
};
\`);"
`);
});

it('should update token when used as prop', async () => {
const result = await applyTransform(
transformer,
`
function App() {
const { theme } = useTheme();

return <Box easing={theme.motion.easing.standard.wary} />
}
`,
{ parser: 'tsx' },
);

expect(result).toMatchInlineSnapshot(`
"function App() {
const { theme } = useTheme();

return <Box easing={theme.motion.easing.shake} />
}"
`);
});

it('should update token as used in X payroll', async () => {
const result = await applyTransform(
transformer,
`
export const AnimatedContainer = styled.div<{ delay?: number }>(({ theme, delay = 0 }) => {
return css\`
animation: \${entry} \${makeMotionTime(theme.motion.duration['2xgentle'])}
\${theme.motion.easing.entrance.revealing} forwards;
animation-delay: \${delay}ms;
opacity: 0;
\`;
});
`,
{ parser: 'tsx' },
);

expect(result).toMatchInlineSnapshot(`
"export const AnimatedContainer = styled.div<{ delay?: number }>(({ theme, delay = 0 }) => {
return css\`
animation: \${entry} \${makeMotionTime(theme.motion.duration['2xgentle'])}
\${theme.motion.easing.entrance} forwards;
animation-delay: \${delay}ms;
opacity: 0;
\`;
});"
`);
});

it('should update token when variable name is not "theme"', async () => {
const result = await applyTransform(
transformer,
`
export const AnimatedContainer = styled.div<{ delay?: number }>(({ theme, delay = 0 }) => {
return css\`
animation: \${entry} \${makeMotionTime(paymentTheme.motion.duration['2xgentle'])}
\${paymentTheme.motion.easing.exit.effective} forwards;
animation-delay: \${delay}ms;
opacity: 0;
\`;
});
`,
{ parser: 'tsx' },
);

expect(result).toMatchInlineSnapshot(`
"export const AnimatedContainer = styled.div<{ delay?: number }>(({ theme, delay = 0 }) => {
return css\`
animation: \${entry} \${makeMotionTime(paymentTheme.motion.duration['2xgentle'])}
\${paymentTheme.motion.easing.exit} forwards;
animation-delay: \${delay}ms;
opacity: 0;
\`;
});"
`);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './migrate-motion';
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { FileInfo } from 'jscodeshift';
// eslint-disable-next-line import/extensions
import * as tokenMapping from './motionTokenMapping.json';

const transformer = (file: FileInfo): string => {
// Fairly simple usecases of motion tokens in razorpay files so this works.
// .replace has also worked well during rebranding
// eslint-disable-next-line no-useless-escape
const newSource = file.source.replace(/motion\.easing\.[\w\.]+/g, (matchingToken) => {
const match = Object.entries(tokenMapping).find(
([oldToken, _newToken]) => oldToken === matchingToken,
);

if (match) {
return match[1];
}

return matchingToken;
});

return newSource;
};

export default transformer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"motion.easing.entrance.effective": "motion.easing.entrance",
"motion.easing.standard.effective": "motion.easing.standard",
"motion.easing.exit.effective": "motion.easing.exit",
"motion.easing.entrance.revealing": "motion.easing.entrance",
"motion.easing.standard.revealing": "motion.easing.emphasized",
"motion.easing.exit.revealing": "motion.easing.exit",
"motion.easing.entrance.attentive": "motion.easing.overshoot",
"motion.easing.exit.attentive": "motion.easing.exit",
"motion.easing.standard.wary": "motion.easing.shake"
}
17 changes: 15 additions & 2 deletions packages/blade/docs/guides/Installation.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
Box,
} from '../../src/components';

import MotionInstallation from '../../src/components/BaseMotion/docs/MotionInstallation.mdx';

<Meta title="Guides/Installation" />

# Installation
Expand Down Expand Up @@ -77,7 +79,8 @@ Before you install the package, make sure that you have performed the following
<TabList>
<TabItem value="basic">1. Basic Setup</TabItem>
<TabItem value="fonts">2. Install Fonts</TabItem>
<TabItem value="ts">3. TypeScript</TabItem>
<TabItem value="motion">3. Setup Motion React</TabItem>
<TabItem value="ts">4. TypeScript</TabItem>
</TabList>
</Box>
<TabPanel value="basic">
Expand All @@ -90,7 +93,7 @@ Before you install the package, make sure that you have performed the following
<Text>Blade has a few peer dependencies that you may already have installed in your project. If so, you can skip adding them again.</Text>

```shell
yarn add @razorpay/blade styled-components@5.3.11 @razorpay/i18nify-js@1.9.3 @razorpay/i18nify-react@4.0.8
yarn add @razorpay/blade styled-components@5.3.11 @razorpay/i18nify-js@1.9.3 @razorpay/i18nify-react@4.0.8 motion@11.12.0
```
<List>
<ListItem>
Expand Down Expand Up @@ -248,6 +251,16 @@ Before you install the package, make sure that you have performed the following
```

</TabPanel>

<TabPanel value="motion">
<Heading size="large" marginTop="spacing.7">Add motion to your application</Heading>

Assuming you've followed the first step and installed `motion` in your project, Here's how we recommend you to setup the project-

<MotionInstallation />

</TabPanel>

<TabPanel value="ts">
<Heading size="large" marginY="spacing.7">TypeScript Setup</Heading>

Expand Down
Loading
Loading