Skip to content

Commit

Permalink
feat(Sandbox): Integrate StackBlitz (#1796)
Browse files Browse the repository at this point in the history
* kinda working stackblitz example

* customized sandbox

* refactor(Sandbox): make baseCode reusable across stackblitz and sandpack

* feat: add broken console

* feat: replace default sandbox

* feat: skip peer installation

* feat: use pnpm instead of npm

* feat: add pnpm-lock code

* feat: rollback lockfile change
  • Loading branch information
saurabhdaware authored Nov 17, 2023
1 parent 1532208 commit 4f8c780
Show file tree
Hide file tree
Showing 26 changed files with 518 additions and 140 deletions.
11 changes: 11 additions & 0 deletions packages/blade/.storybook/react/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ module.exports = {
}),
];

// config.module.rules[0].exclude = new RegExp('/node_modules/(?!(@stackblitz)).*/');

config.module.rules.push({
test: /@stackblitz\/sdk[\\/].*\.m?js$/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-optional-chaining'],
},
});

// Return the altered config
return {
...config,
Expand Down
1 change: 1 addition & 0 deletions packages/blade/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
"@rollup/plugin-node-resolve": "15.2.1",
"@rollup/plugin-replace": "5.0.2",
"@size-limit/preset-big-lib": "8.2.4",
"@stackblitz/sdk": "1.9.0",
"@storybook/addon-a11y": "6.5.16",
"@storybook/addon-actions": "6.5.16",
"@storybook/addon-controls": "6.5.16",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ActionList, ActionListItem, ActionListSection, Playground } from './sto
import { actionListPropsTables } from './propsTable';
import StoryPageWrapper from '~utils/storybook/StoryPageWrapper';
import { Code, Text, Title } from '~components/Typography';
import { Sandbox, VerticalSandbox } from '~utils/storybook/Sandbox';
import { Sandbox, VerticalSandbox } from '~utils/storybook/Sandbox/SandpackEditor';
import { Box } from '~components/Box';
import BaseBox from '~components/Box/BaseBox';
import { ArgsTable } from '~utils/storybook/ArgsTable';
Expand Down
55 changes: 22 additions & 33 deletions packages/blade/src/components/Alert/Alert.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,32 @@ const Page = (): ReactElement => {
<Title>Usage</Title>
<Sandbox editorHeight={500}>
{`
import { useState } from 'react';
import { Alert, Button, Box } from '@razorpay/blade/components';
import { Alert } from '@razorpay/blade/components';
function App() {
const [showAlert, setShowAlert] = useState(false);
return (
<Box>
<Button onClick={() => setShowAlert(!showAlert)}>
Click to be alerted!
</Button>
{
showAlert
? <Alert
title="The Button is Clicked 👀"
description="Click the Button again to hide alert"
marginTop="spacing.4"
actions={{
primary: {
onClick: () => {
alert('Alert from the alert hehe')
},
text: 'Primary Action'
},
secondary: {
href: 'https://razorpay.com',
target: '_blank',
text: 'Go to Razorpay.com'
}
}}
/>
: null
}
</Box>
)
<Alert
title="Alert Title"
description="Add your description message here"
marginTop="spacing.4"
actions={{
primary: {
onClick: () => {
alert('Alert from the alert hehe');
},
text: 'Primary Action',
},
secondary: {
href: 'https://razorpay.com',
target: '_blank',
text: 'Go to Razorpay.com',
},
}}
/>
);
}
export default App;
export default App;
`}
</Sandbox>
</StoryPageWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const Page = (): React.ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole editorHeight={600}>
<Sandbox editorHeight={600}>
{`
import React from 'react';
import {
Expand Down
6 changes: 5 additions & 1 deletion packages/blade/src/components/Box/LayoutPrimitivesDocs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import BaseBox from './BaseBox';
import { Box } from '.';
import StoryPageWrapper from '~utils/storybook/StoryPageWrapper';
import { Code, Heading, Text, Title } from '~components/Typography';
import { Sandbox, SandboxProvider, SandboxHighlighter } from '~utils/storybook/Sandbox';
import {
Sandbox,
SandboxProvider,
SandboxHighlighter,
} from '~utils/storybook/Sandbox/SandpackEditor';
import { List, ListItem, ListItemCode, ListItemLink } from '~components/List';
import { Link } from '~components/Link';
import { castWebType } from '~utils';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const Page = (): React.ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole editorHeight={400} editorWidthPercentage={60}>
<Sandbox showConsole editorHeight={400}>
{`
import { CheckboxGroup, Checkbox } from '@razorpay/blade/components';
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Chip/ChipGroup.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const Page = (): React.ReactElement => {
}
>
<Title>Usage</Title>
<Sandbox showConsole editorHeight={400} editorWidthPercentage={60}>
<Sandbox showConsole editorHeight={400}>
{`
import { Box, Chip, ChipGroup, Text } from '@razorpay/blade/components';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { getSimpleAutoComplete } from './autoCompleteStories';
import StoryPageWrapper from '~utils/storybook/StoryPageWrapper';
import { Code, Heading, Text, Title } from '~components/Typography';
import { Sandbox, VerticalSandbox } from '~utils/storybook/Sandbox';
import { Sandbox, VerticalSandbox } from '~utils/storybook/Sandbox/SandpackEditor';
import { Box } from '~components/Box';
import { ArgsTable } from '~utils/storybook/ArgsTable';
import { List, ListItem, ListItemLink } from '~components/List';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const Page = (): ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole>
<Sandbox>
{`
import { PasswordInput } from '@razorpay/blade/components';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export default {
}}
>
<Title>Usage</Title>
<Sandbox showConsole>
<Sandbox>
{`
import { TextInput } from '@razorpay/blade/components';
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Popover/Popover.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const Page = (): React.ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole>
<Sandbox>
{`
import { Popover, Button } from '@razorpay/blade/components'
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Radio/Radio.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const Page = (): React.ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole editorHeight={400} editorWidthPercentage={60}>
<Sandbox showConsole editorHeight={400}>
{`
import { RadioGroup, Radio } from '@razorpay/blade/components';
Expand Down
17 changes: 10 additions & 7 deletions packages/blade/src/components/Switch/Switch.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,21 @@ const Page = (): React.ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole>
<Sandbox>
{`
import { Switch } from '@razorpay/blade/components'
import { Switch } from '@razorpay/blade/components';
function App(): React.ReactElement {
return (
// Check console
<Switch onChange={(e) => console.log(e.isChecked)} accessibilityLabel="Toggle DarkMode" />
)
<Switch
onChange={(e) => console.log(e.isChecked)}
accessibilityLabel="Toggle DarkMode"
/>
);
}
export default App;
export default App;
`}
</Sandbox>
</StoryPageWrapper>
Expand Down
2 changes: 1 addition & 1 deletion packages/blade/src/components/Tooltip/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const Page = (): React.ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox showConsole>
<Sandbox>
{`
import { Tooltip, Button } from '@razorpay/blade/components'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Page = (): ReactElement => {
}}
>
<Title>Usage</Title>
<Sandbox editorWidthPercentage={60}>
<Sandbox>
{`
import { Code, Text } from '@razorpay/blade/components';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import dedent from 'dedent';
import type { CodeViewerProps } from '@codesandbox/sandpack-react';
import { ScrollView } from 'react-native';
import type { RecipeSandboxProps, SandboxProps } from './types';
import type { RecipeSandboxProps, SandboxProps } from '../types';
import { BaseText } from '~components/Typography/BaseText';
import { Link } from '~components/Link';
import { Text } from '~components/Typography';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,15 @@ import {
} from '@codesandbox/sandpack-react';
import { DocsContext } from '@storybook/addon-docs';
import dedent from 'dedent';
import type { RecipeSandboxProps, SandboxProps } from './types';
import type { RecipeSandboxProps, SandboxProps } from '../types';
// @ts-expect-error We don't resolve JSON files right now. didn't want to change TS config for single JSON
import packageJson from '../../../../package.json'; // eslint-disable-line
import { getIndexTSX, getReactScriptsJSDependencies } from '../baseCode';
import BaseBox from '~components/Box/BaseBox';
import { castWebType } from '~utils';
import { Box } from '~components/Box';
import { Button } from '~components/Button';

const getBladeVersion = (): string => {
// We don't publish codesandbox ci on master so version is not present
const isMaster = process.env.GITHUB_REF === 'refs/heads/master';
const sha = process.env.GITHUB_SHA;
if (sha && !isMaster) {
const shortSha = sha.slice(0, 8);
return `https://pkg.csb.dev/razorpay/blade/commit/${shortSha}/@razorpay/blade`;
}

return '*';
};

const bladeVersion = getBladeVersion();

const useSandpackSetup = ({
code,
language = 'tsx',
Expand All @@ -49,77 +36,10 @@ const useSandpackSetup = ({
return {
template: 'react-ts',
files: {
'/index.tsx': dedent`import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createGlobalStyle } from "styled-components";
import { BladeProvider, Box, Theme } from "@razorpay/blade/components";
import { ${themeTokenName}, createTheme } from "@razorpay/blade/tokens";
import App from "./App";
// Only way to load font correctly in sandbpack. Use @fontsource/lato in your actual projects
document.head.innerHTML += \`
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet">
\`
const GlobalStyles = createGlobalStyle\`
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: 'Lato', sans-serif;
}
\`;
const rootElement = document.getElementById("root");
if (!rootElement) {
throw new Error("root is null");
}
const root = createRoot(rootElement);
const getTheme = () => {
if(${Boolean(brandColor)}){
return createTheme({
brandColor: "${brandColor}",
});
}
return ${themeTokenName};
}
root.render(
<StrictMode>
<BladeProvider themeTokens={getTheme()} colorScheme="${colorScheme}">
<GlobalStyles />
<Box
backgroundColor="surface.background.level1.lowContrast"
minHeight="100vh"
padding={['spacing.4', 'spacing.7']}
>
<App />
</Box>
</BladeProvider>
</StrictMode>
);
console.clear(); // There could be some codesandbox warnings, clearing them here on init
`,
'/index.tsx': getIndexTSX({ themeTokenName, brandColor, colorScheme }),
[`/App.${language}`]: dedent(code),
},
customSetup: {
dependencies: {
react: packageJson.peerDependencies.react,
'react-dom': packageJson.peerDependencies['react-dom'],
'react-scripts': '4.0.3',
'@razorpay/blade': bladeVersion,
'styled-components': packageJson.peerDependencies['styled-components'],
},
},
customSetup: getReactScriptsJSDependencies(),
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Sandbox';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import dedent from 'dedent';
import { ScrollView } from 'react-native';
import type { SandboxProps } from '../types';
import { BaseText } from '~components/Typography/BaseText';
import { Link } from '~components/Link';

// In React Native, the codesandbox doesn't work. So replacing it with normal text display for native
function Sandbox({ children, uri }: SandboxProps): JSX.Element {
return (
<ScrollView>
{uri ? <Link href={uri}>Open Story in Web</Link> : null}
<BaseText marginTop="spacing.5" fontFamily="code">
{dedent(children)}
</BaseText>
</ScrollView>
);
}

export { Sandbox };
Loading

0 comments on commit 4f8c780

Please sign in to comment.