Canonical React Components

repository·main·Indexed 41 days ago

https://github.com/canonical/react-components

A collection of React components version 0.47.3 designed for consuming the Vanilla Framework. It provides a way to implement Canonical's design system within React applications, featuring components like ApplicationLayout, Accordion, and ActionButton, with support for both CJS and ESM builds.

Tokens
38.5K
Snippets
161
Records
256
Agent score
96%

What's inside Canonical React Components

  1. Override SCSS variables in @canonical/react-components

    main

    If your project uses custom Vanilla SCSS variables, you can inject them into @canonical/react-components during the build process using the additionalData option in your bundler configuration. This ensures your custom definitions are processed before the component styles.

    // Vite configuration
    export default defineConfig({
      css: {
        preprocessorOptions: {
          scss: {
            additionalData: `
              $color-brand: #bada55;
              $breakpoint-large: 1234px;
            `,
          },
        },
      },
    });
    
    // Webpack configuration
    module.exports = {
      module: {
        rules: [
          {
            test: /\.scss$/,
            use: [
              'style-loader',
              'css-loader',
              {
                loader: 'sass-loader',
                options: {
                  additionalData: `
                    $color-brand: #bada55;
                    $breakpoint-large: 1234px;
                  `,
                },
              },
            ],
          },
        ],
      },
    };
  2. Develop components with Storybook

    main

    You can run Storybook locally to develop and preview new components. It is recommended to use dotrun for managing the environment, but you can also use Yarn directly.

    To ensure quality, always run dotrun test and dotrun lint after making changes.

    # Using dotrun
    dotrun
    
    # Using Yarn directly
    yarn install
    yarn docs
    
    # Quality checks
    dotrun test
    dotrun lint
  3. Inject SCSS variables from an external file

    main

    To avoid duplicating variable definitions in your build config, create a dedicated SCSS file (e.g., _settings.scss) containing only variable definitions. Use your build tool's configuration to read this file and pass its contents to the additionalData option.

    // Read the file contents
    const scssSettings = fs.readFileSync("templates/sass/_settings.scss", "utf-8").trim();
    
    // Pass to Vite or Webpack configuration
    {
      additionalData: scssSettings,
    }
  4. Run Cypress integration tests

    main

    You can run Cypress integration tests against a local Storybook instance or directly in a CI environment.

    Against local Storybook:

    1. Start Storybook on a specific port: PORT=<PORT> yarn docs.
    2. Open Cypress: yarn cypress:open --env port=<PORT>.

    In CI: Run PORT=<PORT> yarn test-cypress.

    # Local Storybook + Cypress
    PORT=7007 yarn docs
    yarn cypress:open --env port=7007
    
    # CI
    PORT=7007 yarn test-cypress
  5. Link @canonical/react-components to a project using Yarn 3

    main

    To use a local version of @canonical/react-components in a project running Yarn 3, both projects must reside on the same machine.

    1. In react-components, clean, install, build, and start the build watcher.
    2. In your project, clean, install, and link to the local path.
    3. Resolve dependency mismatches by aligning versions in react-components with your project.
    4. Add resolutions to your project's package.json to ensure react, react-dom, formik, and @canonical/react-components all point to the local node_modules of the library.
    # In react-components
    yarn clean
    yarn install
    yarn build
    yarn build-watch
    
    # In your project
    yarn clean
    yarn install
    yarn link path_to_react_components

    In your project's package.json

    "resolutions": { "@canonical/react-components": "portal:path_to_react_components", "formik": "portal:path_to_react_components/node_modules/formik", "react": "portal:path_to_react_components/node_modules/react", "react-dom": "portal:path_to_react_components/node_modules/react-dom" }

  6. Develop locally with linked packages

    main

    If you want to test changes from this repository in a local project without publishing to NPM, you can link the packages using a local registry.

    1. Clone the repository:
      git clone https://github.com/canonical/react-components
    2. In the `react-components` folder, run the link command to add the library, `react`, and `react-dom` to a local registry:
     ```shell
    yarn run link-packages
    1. In your own project folder, install dependencies and link the local versions:
      yarn install
      yarn link react
      yarn link react-dom
      yarn link @canonical/react-components
    4. (Optional) Run `yarn build-watch` in the `react-components` folder to enable hot module reloading in your project.
    
    **Important:** When finished, revert the links in the `react-components` folder:
    ```shell
    cd react-components
    yarn run unlink-packages
    git clone https://github.com/canonical/react-components
    cd react-components
    yarn run link-packages
  7. Link @canonical/react-components to a project using older Yarn versions

    main

    For projects using older versions of Yarn, use dotrun to manage the linking process. This prevents errors like 'multiple copies of React being loaded'.

    Workflow:

    1. In react-components, run dotrun link-package and dotrun build-watch.
    2. In your project, use dotrun exec yarn link for both the library and react, then run yarn install.
    3. Start your project using yarn (do not use ./run).
    4. When finished, unlink the packages in your project and run dotrun unlink-package in react-components.
    # In react-components
    dotrun link-package
    dotrun build-watch
    
    # In your project
    dotrun clean
    dotrun exec yarn link "@canonical/react-components"
    dotrun exec yarn link "react"
    dotrun exec yarn install
    dotrun
    
    # Cleanup in your project
    dotrun exec yarn unlink react
    dotrun exec yarn unlink "@canonical/react-components"
    
    # Cleanup in react-components
    dotrun unlink-package
  8. Configure Vite to work with linked @canonical/react-components

    main

    When using yarn link within a Vite project, you may encounter issues with duplicate dependencies. Update your vite.config.ts to deduplicate react, react-dom, and formik, and enable preserveSymlinks.

    // vite.config.ts
    export default defineConfig({
      resolve: {
        dedupe: ["react", "react-dom", "formik"],
        preserveSymlinks: true,
      },
    });
  9. Configure Panel header modes

    main

    The Panel component uses an exclusive prop pattern for its header. You must choose one of the following approaches:

    1. Default Header: Uses logo or title. If logo is provided, it takes precedence over title. You can also provide controls and toggle to augment this header.
    2. Custom Header: Provide a header prop (a ReactNode) to completely replace the default header implementation.

    Header Props Reference:

    • logo: A ReactNode or a configuration object containing icon, iconAlt, name, nameAlt, and an optional component (defaults to a).
    • title: A ReactNode for the panel title.
    • titleComponent: The element used for the title (defaults to h4).
    • titleClassName: CSS classes for the title element.
    • titleId: An ID for the title element.
    • controls: A ReactNode to be displayed in the controls area.
    • controlsClassName: CSS classes for the controls element.
    • stickyHeader: Boolean to make the header sticky.
    • toggle: An object { label: string, onClick: () => void } to render a panel toggle button.
    • header: A ReactNode that replaces the entire header area.
    // Example of a Panel with a title, controls, and a toggle
    <Panel 
      title="Settings"
      toggle={{ label: 'Collapse', onClick: () => console.log('toggled') }}
      controls={<button>Action</button>}
    >
      <p>Settings content</p>
    </Panel>