@houlak/components-library
v2.1.4
Published
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. W
Downloads
565
Maintainers
Keywords
Readme
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
deepmerge
utility function from@mui/utils
, as stated in Mui's documentation. - Use a single
ThemeProvider
from@mui/material
and 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
peerDependencies
inpackage.json
. - Add those packages as
external
inrollupOptions
invite.config.js
(This also reduces the library's bundle size).