-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add support to Storybook for VA Mobile components #1499
base: main
Are you sure you want to change the base?
Changes from all commits
50cf67e
72a5f9d
bd04014
ee98fad
0f0bb2d
d618a8e
a38f2f7
a0785d8
d448aa4
7a9cd24
5048b5e
e3f7d3f
9b6e01a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React from "react"; | ||
import { StyleSheet, Text, TouchableOpacity, View } from "react-native"; | ||
|
||
export type ButtonProps = { | ||
onPress: () => void; | ||
text: string; | ||
color?: string; | ||
textColor?: string; | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
button: { | ||
paddingVertical: 8, | ||
paddingHorizontal: 16, | ||
borderRadius: 4, | ||
alignSelf: "flex-start", | ||
flexGrow: 0, | ||
backgroundColor: "#005ea2", | ||
}, | ||
buttonText: { | ||
color: "white", | ||
fontSize: 16, | ||
fontWeight: "bold", | ||
}, | ||
buttonContainer: { | ||
alignItems: "flex-start", | ||
flex: 1, | ||
}, | ||
}); | ||
|
||
export const Button = ({ text, onPress, color, textColor }: ButtonProps) => ( | ||
<View style={styles.buttonContainer}> | ||
<TouchableOpacity | ||
style={[styles.button, !!color && { backgroundColor: color }]} | ||
onPress={onPress} | ||
activeOpacity={0.8} | ||
> | ||
<Text style={[styles.buttonText, !!textColor && { color: textColor }]}> | ||
{text} | ||
</Text> | ||
</TouchableOpacity> | ||
</View> | ||
); |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { StorybookConfig } from "@storybook/react-webpack5"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I updated this file (essentially the Storybook webpack build) to |
||
import type { Configuration as WebpackConfiguration } from 'webpack'; | ||
import CopyPlugin from 'copy-webpack-plugin'; | ||
const path = require('path'); | ||
|
||
const config: StorybookConfig = { | ||
stories: ['../@(src|stories)/**/*.stories.@(js|jsx|ts|tsx|mdx)'], | ||
staticDirs: ['../public'], | ||
addons: [ | ||
'@storybook/addon-docs', | ||
'@storybook/addon-essentials', | ||
'@storybook/addon-links', | ||
'@storybook/addon-storysource', | ||
'@storybook/addon-a11y', | ||
'@storybook/addon-react-native-web', | ||
], | ||
webpackFinal: async (config: WebpackConfiguration) => { | ||
// Initialize module if it doesn't exist | ||
if (!config.module) { | ||
config.module = { | ||
rules: [] | ||
}; | ||
} | ||
|
||
// Initialize rules if they don't exist | ||
if (!config.module.rules) { | ||
config.module.rules = []; | ||
} | ||
|
||
// Initialize plugins array if it doesn't exist | ||
if (!config.plugins) { | ||
config.plugins = []; | ||
} | ||
|
||
// Add rule to handle HTML files | ||
config.module.rules.push({ | ||
test: /\.html$/, | ||
use: ['html-loader'], | ||
}); | ||
|
||
// Add rule to handle license and other text files | ||
config.module.rules.push({ | ||
test: /\.(txt|md|license)$/i, | ||
type: 'asset/source', | ||
}); | ||
|
||
// Add rule to silence log files | ||
config.module.rules.push({ | ||
test: /\.log$/, | ||
use: 'null-loader', | ||
include: path.resolve(__dirname, '../') | ||
}); | ||
|
||
// Add TypeScript handling for both .ts and .tsx files | ||
// Exclude node_modules except packages that start with @department-of-veterans-affairs/ | ||
config.module.rules.push({ | ||
test: /\.(ts|tsx)$/, | ||
use: [ | ||
{ | ||
loader: 'ts-loader', | ||
options: { | ||
transpileOnly: true, | ||
configFile: path.resolve(__dirname, '../tsconfig.json') | ||
} | ||
} | ||
], | ||
exclude: /node_modules\/(?!@department-of-veterans-affairs)/ | ||
}); | ||
|
||
// Copies fonts from mobile-assets to storybook static folder | ||
config.plugins.push( | ||
new CopyPlugin({ | ||
patterns: [ | ||
{ | ||
from: '../../node_modules/@department-of-veterans-affairs/mobile-assets/fonts', | ||
to: 'fonts', | ||
}, | ||
], | ||
}), | ||
) | ||
|
||
config.module.rules.push({ | ||
test: /\.scss$/, | ||
use: ['style-loader', 'css-loader', 'sass-loader'], | ||
include: path.resolve(__dirname, '../') | ||
}); | ||
|
||
config.module.rules.push({ | ||
test: /\.stories\.[tj]sx?$/, | ||
use: [ | ||
{ | ||
loader: require.resolve("@storybook/source-loader"), | ||
options: { | ||
sourceLoaderOptions: { | ||
injectStoryParameters: false | ||
} | ||
} | ||
}, | ||
], | ||
enforce: "pre", | ||
}); | ||
|
||
return config; | ||
}, | ||
framework: { | ||
name: '@storybook/react-webpack5', | ||
options: { | ||
builder: { | ||
useSWC: true | ||
} | ||
} | ||
}, | ||
core: { | ||
builder: '@storybook/builder-webpack5', | ||
disableWhatsNewNotifications: true, | ||
}, | ||
docs: { | ||
autodocs: true | ||
} | ||
}; | ||
|
||
export default config; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import '@department-of-veterans-affairs/formation/dist/formation.min.css'; | ||
// import '@department-of-veterans-affairs/formation/dist/formation.min.css'; | ||
import './style.scss'; | ||
import '@department-of-veterans-affairs/formation/dist/formation'; | ||
// import '@department-of-veterans-affairs/formation/dist/formation'; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
import '@department-of-veterans-affairs/component-library/dist/main.css'; | ||
import { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,39 +3,52 @@ | |
"private": true, | ||
"packageManager": "[email protected]", | ||
"scripts": { | ||
"storybook": "storybook dev -p 6006", | ||
"build-storybook": "storybook build", | ||
"static-storybook-server": "yarn build-storybook && npx http-server storybook-static", | ||
"build-storybook-chromatic": "chromatic storybook build --project-token=${env.projectToken}" | ||
"storybook": "STORYBOOK_WEB=true storybook dev -p 6006", | ||
"build-storybook": "STORYBOOK_WEB=true storybook build", | ||
"static-storybook-server": "STORYBOOK_WEB=true yarn build-storybook && npx http-server storybook-static", | ||
"build-storybook-chromatic": "STORYBOOK_WEB=true chromatic storybook build --project-token=${env.projectToken}" | ||
}, | ||
"dependencies": { | ||
"@department-of-veterans-affairs/component-library": "workspace:packages/core", | ||
"prop-types": "^15.7.2", | ||
"react": "^17.0.2" | ||
"prop-types": "^15.7.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.15.8", | ||
"@babel/preset-env": "^7.24.0", | ||
"@babel/core": "^7.25.2", | ||
"@babel/preset-env": "^7.24.8", | ||
"@babel/preset-react": "^7.23.3", | ||
"@babel/preset-typescript": "^7.23.3", | ||
"@babel/preset-typescript": "^7.24.7", | ||
"@department-of-veterans-affairs/formation": "^11.0.6", | ||
"@department-of-veterans-affairs/mobile-assets": "^0.14.0", | ||
"@department-of-veterans-affairs/mobile-component-library": "^0.30.1", | ||
"@department-of-veterans-affairs/mobile-tokens": "^0.23.0", | ||
"@mdx-js/react": "^1.6.22", | ||
"@storybook/addon-a11y": "7.6.19", | ||
"@storybook/addon-actions": "^7.6.10", | ||
"@storybook/addon-docs": "^7.6.10", | ||
"@storybook/addon-essentials": "^7.6.10", | ||
"@storybook/addon-links": "^7.6.10", | ||
"@storybook/addon-mdx-gfm": "7.6.19", | ||
"@storybook/addon-storysource": "^7.6.10", | ||
"@storybook/react": "^7.6.10", | ||
"@storybook/react-webpack5": "7.6.19", | ||
"babel-loader": "^8.2.2", | ||
"@storybook/addon-a11y": "7.6.20", | ||
"@storybook/addon-actions": "^7.6.20", | ||
"@storybook/addon-docs": "^7.6.20", | ||
"@storybook/addon-essentials": "^7.6.20", | ||
"@storybook/addon-links": "^7.6.20", | ||
"@storybook/addon-react-native-web": "^0.0.24", | ||
"@storybook/addon-storysource": "^7.6.20", | ||
"@storybook/react": "^7.6.20", | ||
"@storybook/react-webpack5": "7.6.20", | ||
"babel-loader": "^9.1.3", | ||
"babel-plugin-react-docgen-typescript": "^1.5.1", | ||
"babel-plugin-react-native-web": "^0.19.12", | ||
"chromatic": "^11.5.1", | ||
"copy-webpack-plugin": "^12.0.2", | ||
"css-loader": "^5.2.4", | ||
"html-loader": "^4.2.0", | ||
"http-server": "^14.1.1", | ||
"node-sass": "^9.0.0", | ||
"react-dom": "^17.0.2", | ||
"null-loader": "^4.0.1", | ||
"react": "^18.3.1", | ||
"react-dom": "^18.3.1", | ||
"react-native": "0.76.3", | ||
"react-native-safe-area-context": "^5.2.0", | ||
"react-native-web": "~0.19.13", | ||
"sass-loader": "^12.4.0", | ||
"storybook": "7.6.19" | ||
"storybook": "7.6.20", | ||
"ts-loader": "^9.5.2", | ||
"typescript": "~5.3.3" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// stories/MyButton.stories.tsx | ||
import React from "react"; | ||
import { Meta, StoryFn } from "@storybook/react"; | ||
import { Button } from "../../mobile-components/Button"; | ||
|
||
export default { | ||
title: "components/Button - Mobile", | ||
component: Button, | ||
parameters: { | ||
reactNative: { | ||
appNative: false | ||
} | ||
} | ||
} as Meta<typeof Button>; | ||
|
||
export const Basic: StoryFn<typeof Button> = (args) => ( | ||
<Button {...args} /> | ||
); | ||
|
||
Basic.args = { | ||
text: "React Native Button", | ||
color: "#005ea2", | ||
onPress: () => alert('Button pressed!') | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a simple react-native button to demonstrate that it renders in Storybook. We can remove this file after the discovery work is complete.