To develop components, after cloning the repo, make sure you install the dependencies:
npm i
Run storybook by running
npm start
Run next.js if needed by running
npm run next:dev
Now you can create components and its related stories.
prestart
- The command that runs before the start scriptstart
- Starts the development environmentnext:dev
- Runs next.js' development environmentnext:build
- Builds next.js' development environmentnext:start
- Runs next.js' production environment (but you need to build first)prettier
- Runs prettier CLI to clean up fileslints
- Runs eslint CLI to check for declared ruleslints:fix
- Runs eslint CLI to check for declared rules and tries to automatically fix issues if possibletype-check
- Runs the typescript type checked to check if there is any type errorcheck-commit
- Runs all required checks to create a commitstorybook
- Runs storybookbuild-storybook
- Builds a static html version of storybook so it can be deployedrollup:build
- Builds the project and outputs the dist files to generate a npm packagerollup:watch
- Watch for file changes and builds the project if a file has been changedprepare
- The command that runs automatically by npm, before a npm package upload
The architecture is how we setup the repository structure:
** This project must not have any element/template/layout components because we should only have pure, ui components, with no business logic, only the logic for the component to function
./src/components/UI
= Duck pattern for each component, with each in its own folder./src/styles
= Styles for the Next/Storybook setup.src/pages
= Container components and routes for Next.js
- You'll need github cli, there are different ways of doing the same thing but I think it's just easier to make the release with the github cli: https://cli.github.com/. Note that it is not the same thing as the
git
cli
It is recommended that you read and understand all of these before starting, they are tailwind's core concepts:
- Preflight
- Optimizing for Production
- Utility-First
- Responsive Design
- Hover, Focus, & Other States
- Adding Base Styles
- Extracting Components
- Adding New Utilities
- Functions & Directives
-
Split the commits in small chunks of logic. For example, a single component per commit, or a single fix per commit. If you made all the changes before the commit. You can split those using the staging strategy, and then only committing the staged files.
-
Make your changes in a branch.
- Make sure to update it with master first. You can run the command:
git checkout {BRANCH_NAME} && git fetch && git merge origin/master && git push
before working in a branch that might not be up to date. (Remember to update{BRANCH_NAME}
to your branch name)
- Make sure to update it with master first. You can run the command:
-
Don't commit yet. It is nice to update the
CHANGELOG.md
file in the same commit of your current change. -
Change the
CHANGELOG.md
file, under[Unreleased]
, and add a simple text explaining the change for the current commit. Also make sure to put it in the correct category, for exampleFixes
, orChanges
, orAdded
. Do this for each commit separately -
Now you can push the change with both the code +
CHANGELOG.md
- This is done in your branch and not
master
- After you pushed all the changes and decided you're done. Raise the
version
in package.json accordingly. Following the semver strategy. - Don't push yet.
- Update the
CHANGELOG.md
file by adding the new version title right before the previous version but under[Unreleased]
, date it today, copy the contents of[Unreleased]
, remove the unused/empty headers, and add back(or delete the duplicated content in) the[Unreleased]
template. (There's a commented version in the beginning of the file that you can copy/paste if needed). - Now you commit/push it with the message:
build: bumping version: {VERSION_NUMBER}
(Remember to update{VERSION_NUMBER}
to the current version, and to remove the square brackets{}
) - This way you have a separate commit only for the changes, which could be 1 or more or whatever. And a separate commit only for the version bump.
- Now you can push it.
- Make PR to master
- On your branch, do a
gh pr create -B master
command or just create it in the browser - You can name the PR the name of the current version for example:
1.1.9
- On your branch, do a
- Read the instructions in the PR message, check the boxes accordingly
- Ask for a code review.
- After having your branch merged into
master
- Create a
RELEASE.md
file in the project root if you don't have one. - Copy only the latest version content from
CHANGELOG.md
and paste in yourRELEASE.md
, then save. So it has the contents for the current but not other versions, unlike the changelog file.- Examples: https://github.com/perimetre/ui/releases
- Go to this page and find the latest merge commit, which should be the merge that just happened: https://github.com/perimetre/ui/commits/master
- Copy the commit SHA code for that commit, the SHA code is the little number/string in the commit's right side.
- You can click the clipboard icon which will copy the entire code
- Now you'll need to checkout to master, pull, generate the tag, push the tag and make a release for that tag:
- You can use this chain command:
git add . && git stash && git checkout master && git pull && git tag -a v{VERSION} {COMMIT_SHA} -m "v{VERSION}" && git push origin v{VERSION} && gh release create v{VERSION} -F RELEASE.md
- Note the
{VERSION}
and{COMMIT_SHA}
. You need to replace it with the version number, example1.1.9
, the commit sha, and remove the brackets{}
. - Note that if you have uncommited changes, they'll get stashed.
- Example:
git add . && git stash && git checkout master && git pull && git tag -a v1.1.7 a4e0d64 -m "v1.1.7" && git push origin v1.1.7 && gh release create v1.1.7 -F RELEASE.md
- You can use this chain command:
- The github action will start right when the tag is pushed to
master
, and a new package will be generated. After it's finished you can install the new version.
- Create a folder in
./src/components/UI
with your component name - Create either the
index.tsx
orindex.css
file, or both depending in your case. - If it's a CSS component, make sure to import it in ./src/components/index.css, like it's being done with other components.
- If it's a Base CSS style, make sure to import it in ./src/components/base.css, like it's being done with other base styles.
- If it's a React component, make sure to export it in ./src/components/index.tsx, like it's being done with other components.
- Make sure to wrap your css with the
@layer
directive, like it's being done with other components. - Make sure to append
pui-
as a prefix to all css classes, css variables, tailwind variables/values, mostly everything that is not related to react, like it's being done with other components. - Make sure to add as much (reasonable) comments as possible
- Make sure to create a compelling story in storybook for your component, providing the variants, default values and available options for different properties of your component. Check out other stories for components with css only and also stories for react components, and do something similar.
- Look at other components, simple and complex ones, for example: WYSIWYGInput, TextInput, Button, Drawer, Badge, Link, Modal, FontFamily. To make sure you're following the same pattern
- Run the command
npm run next:dev
- Go to http://localhost:3000/optimize
- In your svg string, change any
fill
attributes that sets a color, tofill="currentColor"
. (Only change ones that sets a color. Other fill attributes likefill="none"
can remain intact) - In your svg string, make sure to not include any React
{}
tags, you have to convert those to html tags, you must paste a plain html svg, not a react component/svg. - Then, paste your SVG string in the first input
- Preview your svg in the top section, your svg should be visible and working in all modes: Original, Optimized and CSS
- If your svg is broken:
- Check if there are any
<defs>
tags in your svg, first. Then move them to their correlated<use>
tags. - If it's still broken, uncheck "Remove color attributes" (Uncheck only if it's broken)
- Check if there are any
- There shouldn't have any red text under the preview icons. If there is, follow the instructions of the text to fix the issue before continuing
- Copy an existing icon file in ./src/components/icons
- Update the icon name everywhere in the file, and the filename itself.
- Update the svg icon in the file you just copied, replacing it with what's in "Optimized SVG" in http://localhost:3000/optimize
- Add the
{...props}
statement before the end of the first svg tag (look at how it's done in other icons) - Make sure to add a class name according to the icon type.
fill-current
orstroke-current
(look at how it's done in other icons). To know which one you need to add. You will need to test the icon using the icon story in storybook. - Update the URL icon version in the file you just copied, replacing it with what's in "uri() version" in http://localhost:3000/optimize
- Insert a new import in ./src/components/icons/index.tsx that references your new icon
- Go to ./src/components/icons/index.css, and copy the latest icon class, at the bottom
- Paste your copied icon class, rename the last part of the class name, which contains the icon name, to your icon name, following the other classes pattern
- Update the
url('
replacing it with what's in "uri() version". - Make sure
--pui-absolute-icon-size
, has the correct icon size. You can look at the svg tag width/height/viewbox attribute to get the correct size - Run the command
npm run dev
- Go to the icons story
- Select your icon in the dropdown
- Make sure your icon works with any color and any size by changing the controls and looking at the output, using the story
- Creating a React component library - Initial instructions in how the project was set up
- The complete guide to publishing a React package to npm - another resource on setting up rollup