Skip to content
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

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
43 changes: 43 additions & 0 deletions packages/mobile-components/Button.tsx
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}>
Copy link
Contributor Author

@jamigibbs jamigibbs Feb 18, 2025

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.

Screenshot 2025-02-17 at 4 35 36 PM

<TouchableOpacity
style={[styles.button, !!color && { backgroundColor: color }]}
onPress={onPress}
activeOpacity={0.8}
>
<Text style={[styles.buttonText, !!textColor && { color: textColor }]}>
{text}
</Text>
</TouchableOpacity>
</View>
);
68 changes: 0 additions & 68 deletions packages/storybook/.storybook/main.js

This file was deleted.

110 changes: 110 additions & 0 deletions packages/storybook/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { StorybookConfig } from "@storybook/react-webpack5";
Copy link
Contributor Author

@jamigibbs jamigibbs Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated this file (essentially the Storybook webpack build) to .ts so that we could use this StorybookConfig type which has helped to ferret out a few incorrect settings.

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 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;
19 changes: 19 additions & 0 deletions packages/storybook/.storybook/preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,23 @@
font-size: inherit;
font-family: var(--font-source-sans);
}

@font-face {
font-family: 'SourceSansPro-Regular';
src: url('fonts/SourceSansPro/SourceSansPro-Regular.ttf');
}

@font-face {
font-family: 'SourceSansPro-Bold';
src: url('fonts/SourceSansPro/SourceSansPro-Bold.ttf');
}

@font-face {
font-family: 'Bitter-Regular';
src: url('fonts/Bitter/Bitter-Regular.ttf');
}

.dark {
background: #333333;
}
</style>
4 changes: 2 additions & 2 deletions packages/storybook/.storybook/preview.js
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';

Copy link
Contributor Author

@jamigibbs jamigibbs Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mobile components aren't like web components with a shadow dom so we will have to deal with how global styles may bleed into elements.

For example, when these Formation imports are active, the border disappears from the secondary mobile components.

Screenshot 2025-02-18 at 4 59 30 PM

Screenshot 2025-02-19 at 1 53 24 PM

import '@department-of-veterans-affairs/component-library/dist/main.css';
import {
Expand Down
54 changes: 33 additions & 21 deletions packages/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,51 @@
"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",
"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"
}
}
24 changes: 24 additions & 0 deletions packages/storybook/stories/Button.stories.tsx
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!')
};
Loading
Loading