https://github.com/act-org/dls
Design Language System (DLS) for ACT & Encoura front-end projects.
https://github.com/act-org/dls
design-language-system dls material-ui react storyboook typescript
Last synced: 4 months ago
JSON representation
Design Language System (DLS) for ACT & Encoura front-end projects.
- Host: GitHub
- URL: https://github.com/act-org/dls
- Owner: act-org
- License: mit
- Created: 2021-02-16T16:35:26.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2024-04-08T20:53:20.000Z (about 1 year ago)
- Last Synced: 2024-04-15T03:16:40.060Z (about 1 year ago)
- Topics: design-language-system, dls, material-ui, react, storyboook, typescript
- Language: TypeScript
- Homepage: https://act-org.github.io/dls
- Size: 25.7 MB
- Stars: 4
- Watchers: 12
- Forks: 1
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Design Language System (DLS)
The Design Language System for ACT & Encoura front-end projects. View the UI components
[here](https://act-org.github.io/dls).## Project Setup
### Installation
In order to use the DLS, you must install it along with
[Material UI](https://mui.com/) version `6.x` and
[React](https://reactjs.org/) version `18.x` or `19.x`.```sh
npm install --save @actinc/dls@latest @mui/material @mui/system @mui/x-data-grid react react-dom
```### Choosing a Theme
This DLS is built on top of the
[theme engine](https://mui.com/material-ui/customization/theming/) from
Material UI, and ships with several themes out of the box:1. `"ACT"`: for ACT's "traditional" look and feel
2. `"ACT_ET"`: for ACT's "Emerging Technology" look and feel
3. `"ENCOURA"`: for the Encoura's "MyEncoura" look and feel
4. `"ENCOURA_CLASSIC"`: for Encoura's "Classic" look and feel
5. `"ENCOURAGE"`: for the Encoura's "Encourage for Students" look and feel
6. `"ENCOURAGE_E4E"`: for the Encoura's "Encourage for Educators" look and feelTo apply one of these themes to your components, simply wrap your application
in the `ThemeProvider` component and specify a theme!```jsx
import { ThemeProvider } from '@actinc/dls/components/ThemeProvider';...
const MyApp = () => (
// specify a theme here!
);
```#### Extending Themes
You can exend the core DLS themes using using our variation on the
[`createTheme`](https://mui.com/material-ui/customization/theming/#createtheme-options-args-theme)
generator from Material UI:```jsx
import deepMerge from 'deepmerge';
import { createTheme } from '@actinc/dls/styles/createTheme';
import { THEME_ACT } from '@actinc/dls/styles/themeAct';
import { ThemeProvider } from '@actinc/dls/components/ThemeProvider';const myExtendedTheme = createTheme(
deepMerge(THEME_ACT, {
// theme customizations go here!
}),
);const MyApp = () => (
);
```#### Custom Themes
Alternatively, you can build your own theme from scratch using our variation on the
[`createTheme`](https://mui.com/material-ui/customization/theming/#createtheme-options-args-theme)
generator from Material UI. Our version takes the same parameters, but will
return a strongly typed version of the theme with any customizations you may
have added.```jsx
import { ThemeProvider } from '@actinc/dls/components/ThemeProvider';
import { createTheme } from '@actinc/dls/styles/createTheme';const myCustomTheme = createTheme({
// build your theme here!
});const MyApp = () => (
);
```#### Custom Themes And Styled Components
Within your styled components, if you need to access custom a theme variable
that is not present in the default MUI `Theme` type, we provide a helper
function to generate a `styled` function that is strongly typed to your theme:```jsx
import { createThemeStyled } from '@actinc/dls/helpers/styled';
import { THEME_ACT } from '@actinc/dls/styles/themeAct';
import TableCell from '@mui/material/TableCell';const styled = createThemeStyled(THEME_ACT);
const StyledTypography = styled(TableCell)(({ theme }) => ({
// `customDims` is not available on the default theme
height: theme.customDims.heights.tableHeader,
}));
```#### Custom Themes and Module Augmentation
In cases where you want to "patch" or [augment](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
an underlying type (for example, if adding a custom color to your theme's
palette), you can create a TS definition file and include it in your project's
`tsconfig.json`.Steps:
- Create your TS definition file (must use the `.d.ts` file extension).
[Example here](./src/styles/themeEncourageE4E/augmentTheme.d.ts).
- Ensure that your definition file does **not** use import aliases.
- Do a release. The DLS will automatically include the definition file in the
build.
- In your project's repo, update your `tsconfig.json`'s `include` field to
point to the file in your `node_modules` directory. Example: `./node_modules/@actinc/dls/path/to/your/index.d.ts`.
- You may need to restart your IDE's TS server for the changes to appear.### Load Fonts
#### Montserrat
The `ACT` and `ACT_ET` themes assume that the
[Montserrat](https://fonts.google.com/specimen/Montserrat) font is available in
the browser. Therefore, it is recommended that you include the following font
reference in the `head` of your React app:```html
```
#### Museo Sans
The `ENCOURA` and `ENCOURA_CLASSIC` themes assume that the
[Museo Sans](https://fonts.adobe.com/fonts/museo-sans) font
is available in the browser. Include this embed code in the `head`
of your React app after obtaining the licensed font URL from Marketing:```html
@import url('licensed-font-url');
```
#### Work Sans, Roboto, Roboto Mono
The `ENCOURAGE` and `ENCOURAGE_E4E` themes assume that the
[Work Sans](https://fonts.google.com/specimen/Work+Sans),
[Roboto](https://fonts.google.com/specimen/Roboto), and the
[Roboto Mono](https://fonts.google.com/specimen/Roboto+Mono) fonts are available
in the browser. Therefore, it is recommended that you include the following font
reference in the `head` of your React app:```html
```
### CSS Baseline
It is recommended to inject the `CssBaseline` component from Material UI near
the root of your component tree in order to reset and normalize browser styles
for your project:```jsx
import { CssBaseline } from '@mui/material';...
const MyApp = () => (
...
...
);
```### Server-Side Rendering
If your project's React framework supports SSR, you can configure the DLS
components for server-side rendering. See the official Next.js example
[here](https://github.com/mui/material-ui/tree/master/examples/nextjs-with-typescript).### Icons
#### Option 1: Find and import from the DLS
The DLS re-exports all icons that are provided by the
[`mdi-material-ui`](https://www.npmjs.com/package/mdi-material-ui) package. This
is an expansive list of icons that are managed by the material community. You
can search for a specific icon to use on
[materialdesignicons.com](https://materialdesignicons.com). Once you've found
the perfect icon, you can use it in your project like so:```jsx
// Import the needed icon(s) directly, to avoid bundle size bloat.
import PollBox from '@actinc/dls/icons/PollBox';...
const MyComponent = () => (
...
...
);
```#### Option 2: Find and import from `@mui/icons-material`
If the DLS doesn't provide the icon you're looking for, as a second line of
defense, you can search for icons in the
[`@mui/icons-material`](https://www.npmjs.com/package/@mui/icons-material)
library. While most of these icons can be found directly in the DLS via
`mdi-material-ui`, there is some unique selection within this library that could
be useful to you. You can search for a specific icon to use on
[mui.com](https://mui.com/material-ui/material-icons/). Once you've found
the perfect icon, you can use it in your project like so:```jsx
// Import the needed icon(s) directly, to avoid bundle size bloat.
import PollIcon from '@mui/icons-material/Poll';...
const MyComponent = () => (
...
...
);
```#### Option 3: Create a custom icon
When all else fails, you can create a custom icon using the `SvgIcon` component
from Material UI. Here's an example:```jsx
import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
import React from 'react';export const CustomIcon: React.FC = (props: SvgIconProps): React.ReactElement => (
);export default CustomIcon;
```### Import Stuff
That's it! You're ready to use the DLS. Simply import the components,
constants, context, helpers, hooks, icons, styles, and types that you need:```jsx
// components
import { Alert } from '@actinc/dls/components/Alert';
// constants
import { SORT_DIRECTION_TYPES } from '@actinc/dls/constants';
// context
import { AlertContext } from '@actinc/dls/context';
// helpers
import { search } from '@actinc/dls/helpers';
// hooks
import { useLocalStorage } from '@actinc/dls/hooks';
// icons
import ChevronDown from '@actinc/dls/icons/ChevronDown';
// styles & themes
import { THEME_ACT } from '@actinc/dls/styles/themeAct';
// types
import { SortObject } from '@actinc/dls/types';
```### Transient Props and Styled Components
The DLS provides a customized styled helper which omits transient props
(those starting with $) from the rendered HTML, while still being able to use
those parameters in styled components. Use as a drop in replacement of the
`styled` function that exists in `@mui/material/styles`:```jsx
import { styled } from '@actinc/dls/helpers/styled';
import Button, { ButtonProps } from '@mui/material/Button';
import * as React from 'react';const StyledButton = styled(Button)(
({ $ultraWide, theme }) => ({
paddingLeft: $ultraWide ? theme.spacing(8) : theme.spacing(4),
paddingRight: $ultraWide ? theme.spacing(8) : theme.spacing(4),
}),
);const MyComponent: React.FC = () => {
return ;
};
```- This implementation is how Styled Components does it:
- Unfortunately emotion (the default styling engine in React) doesn't seem to
care:## ES Modules & Tree Shaking
Version <= 6 of the DLS were built and exported as
[CommonJS modules](https://nodejs.org/api/modules.html#modules-commonjs-modules).
While this allowed the simplest integration of the DLS into any
project, it also resulted in project bundles being
[larger than desired](https://web.dev/commonjs-larger-bundles/) due to
the inability of bundlers to
[tree-shake](https://www.smashingmagazine.com/2021/05/tree-shaking-reference-guide/)
the DLS.In version >= 7 of the DLS, we are now building and exporting the library as
[ECMAScript modules](https://nodejs.org/api/esm.html#modules-ecmascript-modules).
This allows your project's bundler to much more easily read and
[tree-shake](https://www.smashingmagazine.com/2021/05/tree-shaking-reference-guide/)
the DLS right out of the box. (No more need for
[`babel-plugin-transform-imports`](https://www.npmjs.com/package/babel-plugin-transform-imports)!)Furthermore, the DLS's `package.json` is also setting:
```json
"sideEffects": false,
```to instruct builders to enable even deeper tree-shaking. This should make
bundle sizes significantly smaller with less effort. However, the tradeoff
is that in certain scenarios, like
[Lazy Loading](https://nextjs.org/docs/advanced-features/dynamic-import),
if you are expecting a dependency to be there that is now removed from
tree-shaking, things will break and you may need to import that dependency
directly in a parent bundle.### SyntaxError: Unexpected token 'export'
One downside of exporting the DLS as ECMAScript modules is that the `import` and
`export` keywords are preserved, which may cause your packager/runner to throw:```sh
SyntaxError: Unexpected token 'export'
```If you see this error, you'll need to instruct your packager/runner to transpile
the DLS on-the-fly.#### Next.js
You can do this in a [Next.js](https://nextjs.org/) app by adding the DLS to the
[`transpilePackages`](https://beta.nextjs.org/docs/api-reference/next.config.js#transpilepackages)
option in your `next.config.js` file.```js
transpilePackages: ['@actinc/dls'],
```#### Jest
You can do this in the [Jest](https://jestjs.io/) test runner by omitting the
DLS from the
[`transformIgnorePatterns`](https://jestjs.io/docs/tutorial-react-native#transformignorepatterns-customization)
option in your `jest.config.js` file.```js
transformIgnorePatterns: ['/node_modules/(?!(@actinc/dls)/)'],
```## Local Development
Check out the [developer guide](./docs/GUIDE.md) to learn how to build
effectively for the DLS.To run the DLS locally:
1. Install node modules: `npm install`
2. Start the [Storybook](https://storybook.js.org) component visualizer:
`npm start`### How to Iterate Locally
#### Option 1: Creating a Local Build
When you're ready to pilot your changes to this library in your local project:
1. Run the `npm run pack` command. When it finishes running, it will generate a
`.tgz` file in the `/dist` folder with the following name format
`actinc-dls-.tgz`;
2. Access the `package.json` file of your local project in which the
`@actinc/dls` package will be tested, and make the following edit:```json
"dependencies": {
// Before (pulling from NPM via version number):
"@actinc/dls": "9.2.1",
// After (pointing to the local .tgz file):
"@actinc/dls": "file:../path/to/@actinc/dls/dist/actinc-dls-.tgz",
...
}
```3. Run `npm update @actinc/dls` to refresh your project's `node_modules` folder.
4. You can now run your project with the local changes made to this library!
5. If you want to make any further edits to this library, simply run
`npm run pack` to package up the changes, and then `npm update @actinc/dls`
in your local project to pull them in.6. When you're done piloting the changes, simply revert your project's
`package.json` file to pull this library from NPM, and run
`npm update @actinc/dls` to refresh your project's `node_modules` folder.#### Option 2: Real-time Previews
For rapid iteration, you can run a live copy of this library in your
downstream project:1. In this library, run the watch script: `npm run watch`
2. In your project, install a local build of this library: `npm install /dist`
Under the hood, this creates a symlink between the local build and your project.
When changes are detected under the `src` folder, a new build will be output
into the `dist` folder and picked up by your project.Once you are happy with the changes, you'll want to destroy this symlink
and replace the local build with a formal/hosted version of this library.
You can do that by running the following commands in your project:1. `npm uninstall @actinc/dls`
2. `npm install @actinc/dls@ --save --save-exact`
### npm Scripts
There are lots of npm scripts at your disposal during local development.
Here are some of the more important ones:| Script | Description |
| :------------------------ | :---------------------------------------------------------------------- |
| npm run build | Transpiles DLS from TypeScript (`./src`) into ES5 (`./dist`). |
| npm run build-storybook | Creates a static website for deployment (`./storybook-static`). |
| npm start | Starts the [Storybook](https://storybook.js.org) component visualizer. |
| npm test | Runs all tests. |
| npm run release | Publishes a new release of the DLS. |
| npm run release:storybook | Publishes a new release of Storybook (make sure to pull latest `main`). |
| npm run watch | Watch the `src` folder for changes and transpile on-the-fly to `dist`. |### Committing Code
semantic-release scans commits to manage package.json versions and `CHANGELOG.MD`
It is important that we accurately capture what type of development we are doing.
- For changes to storybook (i.e. no change to components), use the `docs` tag:
```bash
git commit -m "docs: Added stories for Alert"
```- For patches to existing components, use `fix`:
```bash
git commit -m "fix: Fixed Snackbar not appear in center of screen"
```- For new functionality, use `feat`:
```bash
git commit -m "feat: Added Carousel component"
```## Pinned Packages
Some npm packages are pinned to non-current versions for a specific reason:
| Package | Version | Reason |
| :------ | :------ | :----- |