Skip to content

Kong/public-ui-components

Repository files navigation

public-ui-components

Monorepo for open-source Kong UI components and utilities.

Commitizen friendly

What goes here

Here are some criteria to help figure out if your code belongs to this mono-repository. If all of the following are true, you are welcome to create a new package:

  • Your code is open-source and/or at a minimum available to the public, and UI-related. If you are writing the code to be used privately at Kong, then shared-ui-components is the better choice.

Creating a package

View the guide on creating a new package within the monorepo here

Package Publishing

View the reference on how packages are versioned and published independently within the monorepo here

Development

All packages must be created utilizing the pnpm run create-package CLI. See here for more details.

Be sure to familiarize yourself with the Component Requirements, including style rules.

If you need to bump a version of a dependency for ALL consuming packages in this repo, use this command:

pnpm --recursive update {package-name}@{version}

Note that it will bump version of said dependency ONLY for those packages that have it as a dependency or devDependency, it won't add said dependency to package dependencies if it doesn't already have it.

Requirements

It is recommended to also globally install lerna with pnpm (though not absolutely required)

Setup

To get started, install dependencies

pnpm install

Next, make sure all dependent packages (from the monorepo itself) are built and available

pnpm run build

You can also run pnpm install-completion to integrate pnpm autocompletion into your command line tools.

Dev Server

Run the dev server in your packages/{workspace}/{package-name}/sandbox/ directory with hot-module reload

pnpm --filter "@kong-ui-public/{package-name}" run dev

Stylelint

Stylelint package files

# Lint only
pnpm --filter "@kong-ui-public/{package-name}" run stylelint

# Lint and fix
pnpm --filter "@kong-ui-public/{package-name}" run stylelint:fix

ESLint

Lint package files

# Lint only
pnpm --filter "@kong-ui-public/{package-name}" run lint

# Lint and fix
pnpm --filter "@kong-ui-public/{package-name}" run lint:fix

Type Checking

Type check your package

pnpm --filter "@kong-ui-public/{package-name}" run typecheck

Testing

Run Component or Unit tests.

File naming convensions

  • Unit test files should be named *.spec.ts and will be run with Vitest
  • Component test files should be named *.cy.ts and will be run with Cypress component test runner.
# Component tests
pnpm --filter "@kong-ui-public/{package-name}" run test:component

# Component tests (with UI)
pnpm --filter "@kong-ui-public/{package-name}" run test:open

# Unit tests
pnpm --filter "@kong-ui-public/{package-name}" run test:unit

# Unit tests (with UI)
pnpm --filter "@kong-ui-public/{package-name}" run test:unit:open

Preview sandbox build

Build your packages/{package-name}/sandbox/ directory for production and serve locally

pnpm --filter "@kong-ui-public/{package-name}" run build:sandbox

pnpm --filter "@kong-ui-public/{package-name}" run preview

Build for production

pnpm --filter "@kong-ui-public/{package-name}" run build

Committing Changes

This repo uses Conventional Commits. Commitizen and Commitlint are used to help build and enforce commit messages.

It is highly recommended to use the following command in order to create your commits:

pnpm commit

For more information on different components that compose our commit messages, please reference the Package Publishing docs

Enforcing Commit Format

Lefthook is used to manage Git Hooks within the repo.

  • A commit-msg hook is automatically setup that enforces commit message stands with commitlint, see lefthook.yml
  • A pre-push hook is used that runs stylelint and eslint before allowing you to push your changes to the repository

Additionally, CI will use commitlint to validate the commits associated with a PR in the Lint and Validate job.

Generating type interface documentation

This only applies to TypeScript-only packages

If your package generates types, then add a build:docs script to your package.json file similar to the one in @kong-ui-public/analytics-utilities

"scripts": {
  ... other scripts
  "build:docs": "{your command for generating docs}"
}

Please run the build:docs command manually to generate the docs and then commit them to your PR.

Preview components

You are working on the PR and changing component project. Let's say @kong-ui-public/i18n. You want to try to deploy consuming application (khcp-ui for example) that uses your changed code without merging your changes to main and publishing new version of @kong-ui-public/i18n. Here are the steps:

  1. Look at your PR where your changes for @kong-ui-public/i18n. Every time PR is getting built, NPM preview of package is getting deployed, and there is an updated PR comment created:
Preview components from this PR in consuming application

In consuming application project install preview versions of shared packages generated by this PR:

// we are adding the version tagged on npm with your PR number
@kong-ui-public/i18n@pr-456

Install the preview version of the package in consuming application, let that PR be deployed, and see PR preview of consuming application utilizing @kong-ui-public/i18n code from your shared-ui-components PR branch.

Never merge consuming application code that uses preview version of the package. PR versions will be deprecated and unpublished when your PR is closed.

Running consuming application with local copy of the package

You are developing shared component (let's say @kong-ui-public/forms) and you need to run consuming application with the current version of the code you have locally in your public-ui-components/packages/{workspace}/forms branch. Here is how to do it:

  1. in the folder public-ui-components/packages/{workspace}/forms run

    yarn link
  2. make sure your package is getting build in watch mode, for this in in the folder public-ui-components/packages/{workspace}/forms run:

    pnpm build:package --watch
  3. In the root folder of the host application/package run:

    yarn link "@kong-ui-public/forms"
  4. Run your consuming application as usual and enjoy your forms code changes visible in your local env immediately.

    yarn run dev

In some cases HMR (hot module reloading) is not working out of the box in this configuration, to force it you might need following changes in vite.config.ts of consuming application:

  1. add watch: ignored into the server config:

      server: {
          watch: {
            ignored: ['!**/node_modules/@kong-ui-public/forms/**']
          },
  2. add optimizeDeps into the root of the config:

        optimizeDeps: {
          exclude: ['@kong-ui-public/forms']
        },

    Please do not commit these changes

    And finally, when you done working with local (linked copy) of your public-ui-components package, unlink it:

  3. In the folder public-ui-components/packages/{workspace}/forms run

    yarn unlink
  4. In the root folder of the host application/package run:

    yarn unlink "@kong-ui-public/forms"
    yarn install --force --frozen-lockfile

Moving packages to the public/private repo

Sometimes packages are initially created in Kong/shared-ui-components where they are privately published, but need to be moved into the public Kong/public-ui-components OSS repository so that the source code and npm package can be consumed by anyone.

View the docs on how to move packages between the private/public repositories here

Host App Troubleshooting

Analytics Packages are blocked by some ad-blockers

Some ad blockers inadvertently block build files with the string analytics in the name. As a proactive measure, the vite.config.ts files in our packages utilize a sanitizePackageName utility that replaces instances of the string analytics with vitals in generated filenames and global variables.

If your host application still has issues with ad blockers, you can try adding build rules to your host application's vite.config.js (or similar) to replace instances of the strings in components and packages:

// vite.config.ts
import { defineConfig } from 'vite'

// Replace any variation of string 'Analytics' in assets and chunks. Replacements are in order to preserve capitalization.
// The third replacement is a catch-all in case a string like `ANALYTICS` is present
const replaceAnalytics = (str: string) => str.replace(/Analytics/g, 'Vitals').replace(/analytics/gi, 'vitals')

export default defineConfig({
  // ...
  build: {
    rollupOptions: {
      output: {
        chunkFileNames: (chunkInfo) => {
          const name = replaceAnalytics(chunkInfo.name || '')

          return `${name}.[hash].js`
        },
        assetFileNames: (assetInfo) => {
          // Replace any instances of `analytics` in the external package name
          const filename = replaceAnalytics(assetInfo.name || '').split('.')[0]

          return `assets/${filename}.[hash].[ext]`
        },
      },
    },
  },
})