@houlak/components-library v2.1.4
Houlak components library
Library project for reusable components across admin solutions of Houlak. Developed with React, based on mui v5 components. Using Storybook for stories, testing and documentation. Using emotion for styling as well as mui v5 styling directives. Will be using React Context in order to provide a theme to the components (with stuff as primary and secondary colors), which will be used across all components.
Will use Chromatic to publish Storybook and catch UI changes, npm for publishing package and auto combined with Github actions for automation of package versioning.
Contents:
How to consume the library
Theme augmentation
In the consumer project, create a .d.ts file with the following content:
import {
ThemedComponentNameToClassKey,
ThemedComponents,
ThemedComponentsPropsList,
} from '@houlak/components-library';
declare module '@mui/material/styles' {
interface ComponentsPropsList extends ThemedComponentsPropsList {}
interface ComponentNameToClassKey extends ThemedComponentNameToClassKey {}
interface Components extends ThemedComponents {}
}This module augmentation file is globally available (i.e. a script declaration file, not a module due to lack of export statement), and allows the consumer's MuiTheme to be in sync with the extended MuiTheme used by the library (e.g. custom themed components like LoadingButton should be type-safe for theme customization in the consumer app).
Implementing the theme
- Theme merging: Use
deepmergeutility function from@mui/utils, as stated in Mui's documentation. - Use a single
ThemeProviderfrom@mui/materialand pass the created theme.
Example:
import { themeOptions } from '@houlak/components-library';
import { ThemeOptions, ThemeProvider, createTheme } from '@mui/material';
import { deepmerge } from '@mui/utils';
import components from './theme/components';
const consumerThemeOptionsOverride: ThemeOptions = {
palette: {
primary: { main: "#fafafa" },
secondary: { main: "#eeeaaa" },
},
components: {
...components,
LoadingButton: {
defaultProps: { variant: 'outlined' }
},
},
};
const mergedTheme = createTheme(deepmerge(themeOptions as ThemeOptions, consumerThemeOptionsOverride));
function App() {
return (
<ThemeProvider theme={mergedTheme}>
{/* ... */}
</ThemeProvider>
);
}Developing the Library
Available Scripts
In the project directory, you can run:
npm run dev
Runs the app in the development mode on port 3000.
npm run storybook
Runs the Storybook of the solution on port 6006.
npm run test-storybook
Runs the Storybook test-runner, which runs all tests on the solution. Precondition: Storybook should be running on port 6006.
npm run build-storybook-docs
Builds Storybook documentation, will create a folder to put all static files
Library and application: production bundle and external packages
This project is used:
- As a library for a consumer application.
- As an application itself, for Storybook/Chromatic.
Due to being an application, there are required packages (e.g. react, @mui/material), that must be set as dependencies in package.json.
Issue: There is a known issue when the consumer uses a library, where the library code references their packages instead of the consumer's.
Example: the library has a component SidebarNavigationItems using a Link component from react-router-dom. This routing library is installed as a dependency, used by Storybook/Chromatic build. When the consumer uses this library component, an error shows: useHref() may be used only in the context of a <Router> component. This is because the library component is pointing to the transitive package, the react-router-dom of the library, instead of the consumer's installed dependency react-router-dom.
This same principle applied to @mui/material's ThemeProvider layers and created a mismatch between the library's theme and the consumer's theme.
This could also explain the error of formik's useField hook requiring a library's Formik context instead of pointing to the consumer's provider.
Solution:
- Set those required packages also under
peerDependenciesinpackage.json. - Add those packages as
externalinrollupOptionsinvite.config.js(This also reduces the library's bundle size).
Themeable components
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago