Skip to content
Merged
12 changes: 10 additions & 2 deletions .storybook/main.js → .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
module.exports = {
import type {StorybookConfig} from '@storybook/core-common';

type Main = {
managerHead: (head: string) => string;
} & StorybookConfig;

const main: Main = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also for this there is a built in type
import { StorybookConfig } from '@storybook/core-common';

stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: ['@storybook/addon-essentials', '@storybook/addon-a11y', '@storybook/addon-react-native-web'],
staticDirs: ['./public', {from: '../assets/css', to: 'css'}, {from: '../assets/fonts/web', to: 'fonts'}],
core: {
builder: 'webpack5',
},
managerHead: (head) => `
managerHead: (head: string) => `
${head}
${process.env.ENV === 'staging' ? '<meta name="robots" content="noindex">' : ''}
`,
};

export default main;
File renamed without changes.
21 changes: 11 additions & 10 deletions .storybook/preview.js → .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import {PortalProvider} from '@gorhom/portal';
import type {Parameters} from '@storybook/addons';
import React from 'react';
import Onyx from 'react-native-onyx';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import ComposeProviders from '../src/components/ComposeProviders';
import HTMLEngineProvider from '../src/components/HTMLEngineProvider';
import {LocaleContextProvider} from '../src/components/LocaleContextProvider';
import OnyxProvider from '../src/components/OnyxProvider';
import {EnvironmentProvider} from '../src/components/withEnvironment';
import {KeyboardStateProvider} from '../src/components/withKeyboardState';
import {WindowDimensionsProvider} from '../src/components/withWindowDimensions';
import ONYXKEYS from '../src/ONYXKEYS';
import ComposeProviders from '@src/components/ComposeProviders';
import HTMLEngineProvider from '@src/components/HTMLEngineProvider';
import {LocaleContextProvider} from '@src/components/LocaleContextProvider';
import OnyxProvider from '@src/components/OnyxProvider';
import {EnvironmentProvider} from '@src/components/withEnvironment';
import {KeyboardStateProvider} from '@src/components/withKeyboardState';
import {WindowDimensionsProvider} from '@src/components/withWindowDimensions';
import ONYXKEYS from '@src/ONYXKEYS';
import './fonts.css';

Onyx.init({
Expand All @@ -20,7 +21,7 @@ Onyx.init({
});

const decorators = [
(Story) => (
(Story: React.ElementType) => (
<ComposeProviders
components={[OnyxProvider, LocaleContextProvider, HTMLEngineProvider, SafeAreaProvider, PortalProvider, EnvironmentProvider, KeyboardStateProvider, WindowDimensionsProvider]}
>
Expand All @@ -29,7 +30,7 @@ const decorators = [
),
];

const parameters = {
const parameters: Parameters = {
controls: {
matchers: {
color: /(background|color)$/i,
Expand Down
6 changes: 5 additions & 1 deletion .storybook/theme.js → .storybook/theme.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type {ThemeVars} from '@storybook/theming';
import {create} from '@storybook/theming';
// eslint-disable-next-line @dword-design/import-alias/prefer-alias
import colors from '../src/styles/theme/colors';

export default create({
const theme: ThemeVars = create({
brandTitle: 'New Expensify UI Docs',
brandImage: 'logomark.svg',
fontBase: 'ExpensifyNeue-Regular',
Expand All @@ -21,3 +23,5 @@ export default create({
appBorderRadius: 8,
inputBorderRadius: 8,
});

export default theme;
54 changes: 0 additions & 54 deletions .storybook/webpack.config.js

This file was deleted.

81 changes: 81 additions & 0 deletions .storybook/webpack.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* eslint-disable no-underscore-dangle */

/* eslint-disable no-param-reassign */

/* eslint-disable @typescript-eslint/naming-convention */
Comment thread
ruben-rebelo marked this conversation as resolved.
Resolved
import dotenv from 'dotenv';
import path from 'path';
import {DefinePlugin} from 'webpack';
import type {Configuration, RuleSetRule} from 'webpack';

type CustomWebpackConfig = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you check if there is already some webpack type we can use for it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We are already using Configuration from webpack. CustomWebpackConfig was created to workaround some type issues, without this type we would need to have a lot of condition to TS comply with the correct typing.
I find Configuration from webpack a bit too generic for this specific case.

resolve: {
alias: Record<string, string>;
extensions: string[];
};
module: {
rules: RuleSetRule[];
};
};

let envFile: string;
switch (process.env.ENV) {
case 'production':
envFile = '.env.production';
break;
case 'staging':
envFile = '.env.staging';
break;
default:
envFile = '.env';
}

const env = dotenv.config({path: path.resolve(__dirname, `../${envFile}`)});
const custom: CustomWebpackConfig = require('../config/webpack/webpack.common')({
envFile,
});

const webpackConfig = ({config}: {config: Configuration}) => {
if (config.resolve && config.plugins && config.module) {
config.resolve.alias = {
'react-native-config': 'react-web-config',
'react-native$': 'react-native-web',
'@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'),
'@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'),
...custom.resolve.alias,
};

// Necessary to overwrite the values in the existing DefinePlugin hardcoded to the Config staging values
const definePluginIndex = config.plugins.findIndex((plugin) => plugin instanceof DefinePlugin);
if (definePluginIndex !== -1 && config.plugins[definePluginIndex] instanceof DefinePlugin) {
const definePlugin = config.plugins[definePluginIndex] as DefinePlugin;
if (definePlugin.definitions) {
definePlugin.definitions.__REACT_WEB_CONFIG__ = JSON.stringify(env);
}
}
config.resolve.extensions = custom.resolve.extensions;

const babelRulesIndex = custom.module.rules.findIndex((rule) => rule.loader === 'babel-loader');
const babelRule = custom.module.rules[babelRulesIndex];
if (babelRule) {
config.module.rules?.push(babelRule);
}

const fileLoaderRule = config.module.rules?.find(
(rule): rule is RuleSetRule =>
typeof rule !== 'boolean' && typeof rule !== 'string' && typeof rule !== 'number' && !!rule?.test && rule.test instanceof RegExp && rule.test.test('.svg'),
);
if (fileLoaderRule) {
fileLoaderRule.exclude = /\.svg$/;
}
config.module.rules?.push({
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('@svgr/webpack'),
});
}

return config;
};

export default webpackConfig;