diff --git a/.buildkite/scripts/build-storybook.sh b/.buildkite/scripts/build-storybook.sh index 28f9227cbea..046c46fb4dc 100755 --- a/.buildkite/scripts/build-storybook.sh +++ b/.buildkite/scripts/build-storybook.sh @@ -6,5 +6,5 @@ set -e corepack enable pnpm install --frozen-lockfile -pnpm turbo:storybook:build:prod +pnpm turbo @docs/storybook#build -- --docs tar -czf ./storybook.tar.gz ./storybook/public diff --git a/.buildkite/scripts/publish.sh b/.buildkite/scripts/publish.sh index 4fa7ba473bf..07f5c8ccb38 100755 --- a/.buildkite/scripts/publish.sh +++ b/.buildkite/scripts/publish.sh @@ -5,7 +5,7 @@ echo "Publishing to ${KAIZEN_DOMAIN_NAME}" # Publish to production bucket aws s3 sync --delete \ - "storybook/public" \ + "docs/storybook-static" \ "s3://${KAIZEN_DOMAIN_NAME}/storybook" aws cloudfront create-invalidation \ diff --git a/.changeset/cool-oranges-tie.md b/.changeset/cool-oranges-tie.md new file mode 100644 index 00000000000..d30b4844f84 --- /dev/null +++ b/.changeset/cool-oranges-tie.md @@ -0,0 +1,5 @@ +--- +"@kaizen/hosted-assets": minor +--- + +Deprecated hosted-assets in favour of KAIO diff --git a/.changeset/strong-apples-clap.md b/.changeset/strong-apples-clap.md new file mode 100644 index 00000000000..d0c064feded --- /dev/null +++ b/.changeset/strong-apples-clap.md @@ -0,0 +1,7 @@ +--- +"@kaizen/design-tokens": minor +"@kaizen/tailwind": minor +--- + +- Added ESM bundle +- Fixed design-tokens js entrypoint diff --git a/.changeset/strong-pigs-return.md b/.changeset/strong-pigs-return.md new file mode 100644 index 00000000000..7afa1a44aaf --- /dev/null +++ b/.changeset/strong-pigs-return.md @@ -0,0 +1,6 @@ +--- +"@kaizen/components": minor +--- + +- Exported types from LikertScale +- Deprecated `useResizeObserver` in favour of native DOM API `ResizeObserver` diff --git a/.eslintignore b/.eslintignore index bb1de5275d4..a5a8cd71305 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ /packages/**/dist /packages/components/src/Icon/bin/Template.tsx -storybook/public +/docs/storybook-static +/docs/preview.css diff --git a/.eslintrc.js b/.eslintrc.js index 74cb42e37c9..c081b89da1d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -271,7 +271,7 @@ module.exports = { overrides: [ { files: [ - "storybook/*", + ".storybook/*", "**/_docs/**/*", "**/__tests__/**/*", "*.stories.tsx", diff --git a/.github/actions/run-storybook/action.yml b/.github/actions/run-storybook/action.yml index 80c92a4caa1..e4579d784e1 100644 --- a/.github/actions/run-storybook/action.yml +++ b/.github/actions/run-storybook/action.yml @@ -16,9 +16,9 @@ runs: uses: actions/download-artifact@v3 with: name: ${{ inputs.artifactName }} - path: "./storybook/public" + path: "./docs/storybook-static" - name: Run storybook uses: Eun/http-server-action@v1 with: - directory: "./storybook/public" + directory: "./docs/storybook-static" port: 6006 diff --git a/.github/workflows/chromatic-main.yaml b/.github/workflows/chromatic-main.yaml index 9af43a0afc6..ddb9115ccef 100644 --- a/.github/workflows/chromatic-main.yaml +++ b/.github/workflows/chromatic-main.yaml @@ -18,11 +18,11 @@ jobs: fetch-depth: 0 - uses: ./.github/actions/setup - name: Build Storybook - run: pnpm turbo:storybook:build + run: pnpm turbo @docs/storybook#build:chromatic - name: Publish to Chromatic uses: chromaui/action@v1 with: token: ${{ github.token }} projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - storybookBuildDir: "./storybook/public" + storybookBuildDir: "./docs/storybook-static" autoAcceptChanges: main # 👈 Auto accept main builds (why https://www.chromatic.com/docs/github-actions#github-squashrebase-merge-and-the-main-branch) diff --git a/.github/workflows/test-stories.yaml b/.github/workflows/test-stories.yaml index fe4c489fde5..0fe7abe4b96 100644 --- a/.github/workflows/test-stories.yaml +++ b/.github/workflows/test-stories.yaml @@ -40,12 +40,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - uses: ./.github/actions/setup - - run: pnpm turbo:storybook:build:test + - run: pnpm turbo @docs/storybook#build -- --test - name: Upload Storybook build as artifact uses: actions/upload-artifact@v3 with: name: ${{ env.ARTIFACT_NAME }} - path: "./storybook/public" + path: "./docs/storybook-static" retention-days: 1 storybook-tests-1: @@ -62,7 +62,7 @@ jobs: with: artifactName: ${{ env.ARTIFACT_NAME }} - name: Storybook tests (1/3) - run: pnpm storybook:test --shard 1/3 + run: pnpm -F @docs/storybook test -- --shard 1/3 storybook-tests-2: name: "test-storybook" @@ -78,7 +78,7 @@ jobs: with: artifactName: ${{ env.ARTIFACT_NAME }} - name: Storybook tests (2/3) - run: pnpm storybook:test --shard 2/3 + run: pnpm -F @docs/storybook test -- --shard 2/3 storybook-tests-3: name: "test-storybook" @@ -94,7 +94,7 @@ jobs: with: artifactName: ${{ env.ARTIFACT_NAME }} - name: Storybook tests (3/3) - run: pnpm storybook:test --shard 3/3 + run: pnpm -F @docs/storybook test -- --shard 3/3 chromatic: needs: run-check @@ -109,14 +109,14 @@ jobs: - uses: ./.github/actions/setup - name: Build Storybook for Chromatic # We want both stories and docs for the branch preview - run: pnpm turbo:storybook:build:chromatic-turbo-snap + run: pnpm turbo @docs/storybook#build:chromatic - id: publishChromatic name: Publish to Chromatic uses: chromaui/action@v11 with: token: ${{ github.token }} projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - storybookBuildDir: "./storybook/public" + storybookBuildDir: "./docs/storybook-static" onlyChanged: "!(main)" externals: | **/!(*.module).scss diff --git a/.gitignore b/.gitignore index a286b748ce8..867078efcce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ node_modules yarn-*.log -/storybook/public/ +docs/storybook-static .DS_Store dist .cache .yalc yalc.loc .turbo +preview.css diff --git a/.prettierignore b/.prettierignore index 1771e511616..7e829838221 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,7 +16,8 @@ # Explicitly ignore... pnpm-lock.yaml **/node_modules/ -/storybook/public/ +/docs/storybook-static/ +/docs/utils/tailwind.css /packages/**/dist /packages/components/locales /packages/design-tokens/css diff --git a/.stylelintignore b/.stylelintignore index 3e9dc04ec2d..770e446ebba 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -1,4 +1,7 @@ packages/design-tokens/**/*.scss packages/design-tokens/**/*.css +packages/components/dist/* packages/components/locales/* -storybook/styles/* +docs/storybook-static/* +docs/tailwind.css +docs/preview.css diff --git a/.stylelintrc-css.mjs b/.stylelintrc-css.mjs new file mode 100644 index 00000000000..5ca791a7a6b --- /dev/null +++ b/.stylelintrc-css.mjs @@ -0,0 +1,8 @@ +/** @type {import('stylelint').Config} */ +// For CSS linting only, SCSS linting is handled in the root .stylelintrc.json +export default { + extends: "stylelint-config-standard", + rules: { + "selector-class-pattern": null, + }, +} diff --git a/.stylelintrc.json b/.stylelintrc-scss.json similarity index 100% rename from .stylelintrc.json rename to .stylelintrc-scss.json diff --git a/storybook/assets/kaizen-badge.svg b/docs/assets/kaizen-badge.svg similarity index 100% rename from storybook/assets/kaizen-badge.svg rename to docs/assets/kaizen-badge.svg diff --git a/docs/basic-component.md b/docs/basic-component.md deleted file mode 100644 index e4b059edb40..00000000000 --- a/docs/basic-component.md +++ /dev/null @@ -1,308 +0,0 @@ -# Basic component recipe - -Recipe for creating a basic component. - -- [Intro](#intro) -- [Adding a new component](#adding-a-new-component) -- [Component structure](#component-structure) - - [Documentation](#documentation) - - [Subcomponents](#subcomponents) - - [Hooks and Utils](#hooks-and-utils) - - [index.ts](#indexts-1) - - [Component.tsx](#componenttsx) - - [Styles](#styles) - - [Tests](#tests) - - [Types](#types) -- [Component.tsx template](#componenttsx-template) - - [Props](#props) - - [The component](#the-component) - - [Display name](#display-name) - -## Intro - -There are 2 types of components that live in `@kaizen/components`, `src` and `future`, both are **production safe**. - -### src components - -These are components which are essentially the "main" branch of components and only receive non-breaking changes. **Any brand new components should go here.** - -### future components - -Components which have an existing `src` component equivalent, but have any breaking changes to their API. Eventually `future` components will replace their `src` equivalent in the next major release. - -## Adding a new component - -To generate a new component or a subcomponent, -run the following command and follow the prompts: -``` -pnpm plop -``` -or run the following command to answer the name prop (replace `NewComponentName` with your component name): -``` -pnpm plop NewComponentName -``` - -## Component structure - -Given the component `PancakeStack`, the component structure will follow this: - -``` -/* Component */ -src/(__future__/) - PancakeStack/ - _docs/ - - PancakeStack.mdx - - PancakeStack.stickersheet.stories.tsx - - PancakeStack.stories.tsx - hooks/ - - index.ts - - useHook.ts - - useHook.spec.ts - subcomponents/ - - Pancake/ - - index.ts - - Pancake.tsx - - Pancake.module.scss - - Pancake.spec.tsx - - Topping/ - - index.ts - - Topping.tsx - - Topping.module.scss - - Topping.spec.tsx - utils/ - - index.ts - - groupedFunctions.ts (eg. getters) - - groupedFunctions.spec.ts - - functionName.ts - - functionName.spec.ts - - _mixins.scss - - _variables.scss - - index.ts - - PancakeStack.tsx - - PancakeStack.module.scss - - PancakeStack.spec.tsx - - types.ts -``` - -### Documentation - -The `_docs/` folder houses Storybook stories and stickersheets, and the directory is excluded from the published package. - -### Subcomponents - -Subcomponents live in the `subcomponents/` directory and should not have subcomponents of their own. If you are finding that you want subcomponents for your subcomponents, then one (or both) should be a component instead. - -Aside from the above, subcomponents should follow the same structure as a normal component. - -Subcomponents living within their own directories have the benefits of keeping files small and clean, and allows for mocking for tests. - -### Hooks and Utils - -Hooks and utils go into their own respective folders, with their filename reflective of either the function name or a collective name based on the functionality of functions within the file. - -### index.ts - -This file is used only as an entrypoint. -Anything relating to the component (eg. hooks, subcomponents) that are to be exported should be included here. - -```ts -// index.ts -export * from "./PancakeStack" -export * from "./Pancake" -export * from "./hooks" -``` - -### Component.tsx - -Component files should be named to match the component name (eg. the Pancake component will be named `Pancake.tsx`). - -See [template](#componenttsx-template) for component composition. - -### Styles - -Style files should named to match the component name (eg. the Pancake component will be named `Pancake.module.scss`) and live in the same directory. - -Keep these clean by separating styles for subcomponents in their own respective files. - -If you require scss variables or mixins to be shared between the parent and its children, add them to `_variables.scss` or `_mixins.scss` in the parent directory and import the file into the required stylesheets. Note that these do not have `.module` as part of their extension as they should not contain any classes directly used by the component. - -### Tests - -Test files should be named to match the component/function name (eg. `Pancake.spec.tsx` and `functionName.ts`) and live in the same directory. - -We should only write unit and functional tests in these files, and not snapshot tests as they do not have meaningful assertions/expectations. - -For visual regression testing, create a stickersheet story in Storybook and send it to Chromatic. - -### Types - -For any shared/useful TypeScript types that do not make sense to belong in the file it is used, create a `types.ts` file and export the types from `index.ts`. - -## Component.tsx template - -A basic component will follow this template: - -```tsx -// PancakeStack.tsx -import React, { HTMLAttributes } from "react" -import classnames from "classnames" -import { OverrideClassName } from "~types/OverrideClassName" -import styles from "./PancakeStack.module.scss" - -export type PancakeStackProps = { - children: React.ReactNode - isBooleanProp: boolean - hasOptionalBooleanProp?: boolean - onCustomFunction: () => void -} & OverrideClassName> - -export const PancakeStack = ({ - children, - isBooleanProp, - hasOptionalBooleanProp = false, - onCustomFunction, - classNameOverride, - ...restProps -}: PancakeStackProps): JSX.Element => { - const [hasSyrup, setHasSyrup] = useState(false) - - const handleCustomFunction = (): boolean => { - onCustomFunction() - setHasSyrup(!hasSyrup) - return true - } - - return ( -
- {children} - {doSomething(hasOptionalBooleanProp) && } -
- ) -} - -PancakeStack.displayName = "PancakeStack" -``` - -### Props - -```tsx -import { HTMLAttributes } from "react" -import { OverrideClassName } from "~types/OverrideClassName" - -export type PancakeStackProps = { - children: React.ReactNode - isBooleanProp: boolean - hasOptionalBooleanProp?: boolean - onCustomFunction: () => void -} & OverrideClassName> -``` - -- Create and export a`type` for your props in the format of `{PascalComponentName}Props` -- Use our custom type `OverrideClassName` to replace `className` with the alias `classNameOverride` - - The alias allows us to easier track usage (as ideally teams should not need to use this) and allows us to not be a bottleneck if the component does not meet their needs in the interim - - Previously `classNameAndIHaveSpokenToDST` -- Extend the native attributes of the HTML element of your component - -```tsx -// Extending
-import { HTMLAttributes } from "react" -export type SectionProps = OverrideClassName> - -// Extending