From c7c05cd9eac77614bf4e7320dee695fb8a77ca58 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 31 Jan 2023 11:05:45 -0800 Subject: [PATCH 01/18] Working preact example project that swaps react with preact downstream of us --- examples/preact-app/Gulpfile.js | 18 +++++++++ examples/preact-app/README.md | 9 +++++ examples/preact-app/babel.config.js | 26 ++++++++++++ examples/preact-app/index.html | 24 ++++++++++++ examples/preact-app/package.json | 24 ++++++++++++ examples/preact-app/src/scripts/index.js | 50 ++++++++++++++++++++++++ examples/preact-app/webpack.config.js | 41 +++++++++++++++++++ 7 files changed, 192 insertions(+) create mode 100644 examples/preact-app/Gulpfile.js create mode 100644 examples/preact-app/README.md create mode 100644 examples/preact-app/babel.config.js create mode 100644 examples/preact-app/index.html create mode 100644 examples/preact-app/package.json create mode 100644 examples/preact-app/src/scripts/index.js create mode 100644 examples/preact-app/webpack.config.js diff --git a/examples/preact-app/Gulpfile.js b/examples/preact-app/Gulpfile.js new file mode 100644 index 0000000000..4212166338 --- /dev/null +++ b/examples/preact-app/Gulpfile.js @@ -0,0 +1,18 @@ +const gulp = require('gulp'); + +/** + * Copy the static assets from the design system, such as the fonts and images. + * We could do this manually, but why not automate it so it's easy to do + * as things are updated :) + */ +gulp.task('copy-design-system', function () { + return gulp + .src([ + 'node_modules/@cmsgov/design-system/dist/**/fonts/*', + 'node_modules/@cmsgov/design-system/dist/**/images/*', + 'node_modules/@cmsgov/design-system/dist/css/*.css', + ]) + .pipe(gulp.dest('./dist/')); +}); + +gulp.task('default', gulp.series('copy-design-system')); diff --git a/examples/preact-app/README.md b/examples/preact-app/README.md new file mode 100644 index 0000000000..a784294466 --- /dev/null +++ b/examples/preact-app/README.md @@ -0,0 +1,9 @@ +## Example: react-app + +This example shows how you can incorporate the design system into your build process. It uses [Webpack](https://webpack.js.org) to bundle and optimize JavaScript files, [Babel](https://babeljs.io/) to transpile JSX, and [Gulp](http://gulpjs.com/) to transpile Sass and copy static assets from the design system. + +## Getting started + +1. Install packages: `npm install` or `yarn install` +1. Compile and bundle assets: `npm run build` or `yarn run build` +1. Open `index.html` in a browser. diff --git a/examples/preact-app/babel.config.js b/examples/preact-app/babel.config.js new file mode 100644 index 0000000000..30d757e5dd --- /dev/null +++ b/examples/preact-app/babel.config.js @@ -0,0 +1,26 @@ +module.exports = function (api) { + api.cache(true); + + const presets = [ + [ + '@babel/preset-env', + { + useBuiltIns: 'entry', + corejs: '3.0.0', + }, + ], + ]; + + return { + presets, + plugins: [ + [ + '@babel/plugin-transform-react-jsx', + { + pragma: 'h', + pragmaFrag: 'Fragment', + }, + ], + ], + }; +}; diff --git a/examples/preact-app/index.html b/examples/preact-app/index.html new file mode 100644 index 0000000000..fb2d038d6f --- /dev/null +++ b/examples/preact-app/index.html @@ -0,0 +1,24 @@ + + + + + Design System + + + + +
+

Build assets before viewing

+

Seeing this message in the browser? Make sure to run the following command first:

+

+ yarn run build +
+ or +
+ npm run build +

+
+ + + + diff --git a/examples/preact-app/package.json b/examples/preact-app/package.json new file mode 100644 index 0000000000..2f3a08df4e --- /dev/null +++ b/examples/preact-app/package.json @@ -0,0 +1,24 @@ +{ + "name": "react-app-example", + "version": "1.0.0", + "private": true, + "dependencies": { + "@cmsgov/design-system": "^6.0.0", + "preact": "^10.11.3" + }, + "devDependencies": { + "@babel/core": "^7.20.12", + "@babel/plugin-transform-react-jsx": "7.20.13", + "@babel/preset-env": "^7.20.2", + "babel-loader": "^8.0.0", + "gulp": "^4.0.2", + "http-server": "14.1.1", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.1" + }, + "sideEffects": false, + "scripts": { + "build": "webpack --mode production --progress && gulp", + "serve": "http-server" + } +} diff --git a/examples/preact-app/src/scripts/index.js b/examples/preact-app/src/scripts/index.js new file mode 100644 index 0000000000..1a432ff6fc --- /dev/null +++ b/examples/preact-app/src/scripts/index.js @@ -0,0 +1,50 @@ +/* eslint-disable react/react-in-jsx-scope */ + +// Named import from main entry file. This example has been configured to use Webpack's tree shaking +// to only bundle imported components. Without this optimization, all components will be imported +// your build process. + +import { Alert, Button, Drawer, UsaBanner } from '@cmsgov/design-system'; +import { render } from 'preact'; +import { useState } from 'preact/hooks'; + +const Example = function () { + const [open, setOpen] = useState(false); + return ( +
+ +
+
+ ExampleWebsite.gov +
+
+ +
+
+

CDN Example

+ +

You did it! You’ve ran the example.

+ {open && ( + Footer content

} + heading="Drawer Heading" + onCloseClick={() => setOpen(false)} + hasFocusTrap={true} + > + Test +
+ )} + +
+
+
+
+ ); +}; + +const root = document.querySelector('#jsx-root'); +root.innerHTML = ''; // Preact doesn't replace content with its `render` function +render(, root); diff --git a/examples/preact-app/webpack.config.js b/examples/preact-app/webpack.config.js new file mode 100644 index 0000000000..fc2a9e341b --- /dev/null +++ b/examples/preact-app/webpack.config.js @@ -0,0 +1,41 @@ +/** + * Use Webpack + Babel to bundle and transpile our JSX + */ +const path = require('path'); +const webpack = require('webpack'); + +const config = { + entry: './src/scripts/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist/scripts'), + }, + resolve: { + alias: { + react: 'preact/compat', + 'react-dom': 'preact/compat', + 'react/jsx-runtime': 'preact/jsx-runtime', + }, + }, + plugins: [ + new webpack.ProvidePlugin({ + h: ['preact', 'h'], + Fragment: ['preact', 'Fragment'], + }), + ], + module: { + rules: [ + { + test: /\.js$/, + exclude: [/node_modules/], + use: [ + { + loader: 'babel-loader', + }, + ], + }, + ], + }, +}; + +module.exports = config; From 07a661cce55c6f90f52a9dbd2cd3737db32d7d23 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 31 Jan 2023 11:14:22 -0800 Subject: [PATCH 02/18] Update `examples/react-app` to be a direct comparison with the preact one This simplifies it by stripping out the Sass stuff. We could possibly add some CSS back in later, but right now I'm focused on the JS part of it. Some stats: - `react-app` produces a bundle weighing 188 KB - `preact-app` produces a bundle weighing 76 KB --- examples/react-app/Gulpfile.js | 24 +---------- examples/react-app/index.html | 25 +++++------- examples/react-app/package.json | 17 ++++---- examples/react-app/src/scripts/index.js | 51 ++++++++++++++---------- examples/react-app/src/styles/index.scss | 5 --- 5 files changed, 53 insertions(+), 69 deletions(-) delete mode 100644 examples/react-app/src/styles/index.scss diff --git a/examples/react-app/Gulpfile.js b/examples/react-app/Gulpfile.js index 60d336bbac..4212166338 100644 --- a/examples/react-app/Gulpfile.js +++ b/examples/react-app/Gulpfile.js @@ -1,5 +1,4 @@ const gulp = require('gulp'); -const sass = require('gulp-sass'); /** * Copy the static assets from the design system, such as the fonts and images. @@ -11,28 +10,9 @@ gulp.task('copy-design-system', function () { .src([ 'node_modules/@cmsgov/design-system/dist/**/fonts/*', 'node_modules/@cmsgov/design-system/dist/**/images/*', + 'node_modules/@cmsgov/design-system/dist/css/*.css', ]) .pipe(gulp.dest('./dist/')); }); -/** - * Transpile Sass to CSS - */ -gulp.task('sass', function () { - const transpiler = sass({ - outputStyle: 'compressed', - }).on('error', sass.logError); - - return gulp.src('./src/styles/**/*.scss').pipe(transpiler).pipe(gulp.dest('./dist/styles')); -}); - -/** - * Copy CSS files to local dist - */ -gulp.task('css', function () { - return gulp - .src('node_modules/@cmsgov/design-system/dist/css/*.css') - .pipe(gulp.dest('./dist/styles/cmsds')); -}); - -gulp.task('default', gulp.series('copy-design-system', 'sass')); +gulp.task('default', gulp.series('copy-design-system')); diff --git a/examples/react-app/index.html b/examples/react-app/index.html index c4a299f6ee..fb2d038d6f 100644 --- a/examples/react-app/index.html +++ b/examples/react-app/index.html @@ -3,23 +3,20 @@ Design System - - + -
-
-

Build assets before viewing

-

Seeing this message in the browser? Make sure to run the following command first:

-

- yarn run build -
- or -
- npm run build -

-
+
+

Build assets before viewing

+

Seeing this message in the browser? Make sure to run the following command first:

+

+ yarn run build +
+ or +
+ npm run build +

diff --git a/examples/react-app/package.json b/examples/react-app/package.json index f5a5768a97..07d7b3fa07 100644 --- a/examples/react-app/package.json +++ b/examples/react-app/package.json @@ -3,22 +3,23 @@ "version": "1.0.0", "private": true, "dependencies": { - "@cmsgov/design-system": "file:../../packages/design-system/", + "@cmsgov/design-system": "^6.0.0", "react": "^16.14.0", "react-dom": "^16.14.0" }, "devDependencies": { - "@babel/core": "^7.8.4", - "@babel/preset-env": "^7.8.4", - "@babel/preset-react": "^7.8.3", + "@babel/core": "^7.20.12", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "7.18.6", "babel-loader": "^8.0.0", "gulp": "^4.0.2", - "gulp-sass": "^3.1.0", - "webpack": "^4.42.1", - "webpack-cli": "^3.3.11" + "http-server": "14.1.1", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.1" }, "sideEffects": false, "scripts": { - "build": "NODE_ENV=production webpack -p --progress --display-used-exports && gulp" + "build": "webpack --mode production --progress && gulp", + "serve": "http-server" } } diff --git a/examples/react-app/src/scripts/index.js b/examples/react-app/src/scripts/index.js index a52f12f017..a155832d46 100644 --- a/examples/react-app/src/scripts/index.js +++ b/examples/react-app/src/scripts/index.js @@ -1,9 +1,8 @@ // Named import from main entry file. This example has been configured to use Webpack's tree shaking // to only bundle imported components. Without this optimization, all components will be imported // your build process. -import { Alert, Drawer } from '@cmsgov/design-system'; -// Default import for individual component. No special optimizations needed. -import Button from '@cmsgov/design-system/dist/components/Button/Button'; + +import { Alert, Button, Drawer, UsaBanner } from '@cmsgov/design-system'; import React, { useState } from 'react'; import ReactDOM from 'react-dom'; @@ -11,23 +10,35 @@ const Example = function () { const [open, setOpen] = useState(false); return (
- -

You did it! You’ve ran the example.

- {open && ( - Footer content

} - heading="Drawer Heading" - onCloseClick={() => setOpen(false)} - hasFocusTrap={true} - > - Test -
- )} - -
+ +
+
+ ExampleWebsite.gov +
+
+ +
+
+

CDN Example

+ +

You did it! You’ve ran the example.

+ {open && ( + Footer content

} + heading="Drawer Heading" + onCloseClick={() => setOpen(false)} + hasFocusTrap={true} + > + Test +
+ )} + +
+
+
); }; diff --git a/examples/react-app/src/styles/index.scss b/examples/react-app/src/styles/index.scss deleted file mode 100644 index ad9f8d042d..0000000000 --- a/examples/react-app/src/styles/index.scss +++ /dev/null @@ -1,5 +0,0 @@ -.wrap { - margin: auto; - max-width: 800px; - width: 95%; -} From 84918dce934fa09b1c1d4476308187bbcff4ec9a Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 31 Jan 2023 11:19:50 -0800 Subject: [PATCH 03/18] Update the example names on the example pages --- examples/preact-app/src/scripts/index.js | 2 +- examples/react-app/src/scripts/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/preact-app/src/scripts/index.js b/examples/preact-app/src/scripts/index.js index 1a432ff6fc..b94ead3954 100644 --- a/examples/preact-app/src/scripts/index.js +++ b/examples/preact-app/src/scripts/index.js @@ -21,7 +21,7 @@ const Example = function () {
-

CDN Example

+

Preact Example

You did it! You’ve ran the example.

{open && ( diff --git a/examples/react-app/src/scripts/index.js b/examples/react-app/src/scripts/index.js index a155832d46..7e105d3dfa 100644 --- a/examples/react-app/src/scripts/index.js +++ b/examples/react-app/src/scripts/index.js @@ -19,7 +19,7 @@ const Example = function () {
-

CDN Example

+

React Example

You did it! You’ve ran the example.

{open && ( From bdcd14dfb9a969de2b991e6cf79724e263ba7579 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 31 Jan 2023 13:12:20 -0800 Subject: [PATCH 04/18] Build a preact CDN bundle and use it in a new `cdn-preact` example Note that the additional babel config breaks Storybook, but if we end up going this route, we can update our Storybook config to work with preact --- .gitignore | 4 --- babel.config.js | 7 ++++ examples/cdn-preact/README.md | 15 ++++++++ examples/cdn-preact/copy.sh | 4 +++ examples/cdn-preact/index.html | 65 ++++++++++++++++++++++++++++++++++ examples/cdn-preact/style.css | 4 +++ gulpfile.js | 28 +++++++++++---- package.json | 1 + yarn.lock | 5 +++ 9 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 examples/cdn-preact/README.md create mode 100644 examples/cdn-preact/copy.sh create mode 100644 examples/cdn-preact/index.html create mode 100644 examples/cdn-preact/style.css diff --git a/.gitignore b/.gitignore index b096194c35..446181f1f2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,6 @@ **/package-lock.json /examples/*/yarn.lock -/examples/cdn/js/* -/examples/cdn/css/* -/examples/cdn/fonts/* - # Code editors *.sublime-* diff --git a/babel.config.js b/babel.config.js index 9bab076529..18e1f90bd4 100644 --- a/babel.config.js +++ b/babel.config.js @@ -18,6 +18,13 @@ module.exports = function (api) { '@babel/plugin-transform-object-assign', ['babel-plugin-typescript-to-proptypes', { comments: true }], 'inline-react-svg', + [ + '@babel/plugin-transform-react-jsx', + { + pragma: 'h', + pragmaFrag: 'Fragment', + }, + ], ]; return { diff --git a/examples/cdn-preact/README.md b/examples/cdn-preact/README.md new file mode 100644 index 0000000000..41f9d069a6 --- /dev/null +++ b/examples/cdn-preact/README.md @@ -0,0 +1,15 @@ +## Example: Consuming assets from the CDN + +This shows the usage of CMS design system components from the CDN: + +- Include the core CSS bundle and theme +- Include the JS vendor files and bundle +- Use CSS layout, utility, and component classes +- Render React components from our library + +See also: https://reactjs.org/docs/add-react-to-a-website.html + +## Getting started + +1. Serve the root of this directory from a webserver, with `npx http-server` +2. View it in a browser by visiting http://localhost:8080 diff --git a/examples/cdn-preact/copy.sh b/examples/cdn-preact/copy.sh new file mode 100644 index 0000000000..e8dc957d77 --- /dev/null +++ b/examples/cdn-preact/copy.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +mkdir -p dist/js +cp -R ../../packages/design-system/dist/js/. dist/js/ \ No newline at end of file diff --git a/examples/cdn-preact/index.html b/examples/cdn-preact/index.html new file mode 100644 index 0000000000..0049b25b63 --- /dev/null +++ b/examples/cdn-preact/index.html @@ -0,0 +1,65 @@ + + + + + CDN Example + + + + + + + +
+ + +
+
+ ExampleWebsite.gov +
+
+ +
+
+

CDN Example

+

+ This is an example showing how to use the CDN. Some elements are simple and can be easily + created by applying a CSS class from the Design System. Some components are more complex + or are interactive. Our React-based component library is here for those more complex + cases. +

+ +
+ + +
+
+ + + +
+
+
+ + diff --git a/examples/cdn-preact/style.css b/examples/cdn-preact/style.css new file mode 100644 index 0000000000..a3c84f0ef8 --- /dev/null +++ b/examples/cdn-preact/style.css @@ -0,0 +1,4 @@ +body { + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 2271bf7b61..5849861f09 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -17,6 +17,7 @@ const filter = require('gulp-filter'); const log = require('fancy-log'); const svgmin = require('gulp-svgmin'); const webpack = require('webpack-stream'); +const { ProvidePlugin } = require('webpack'); /* * command line arguments and global variables @@ -237,11 +238,25 @@ const bundleJs = (cb) => { library: 'DesignSystem', }, mode: process.env.NODE_ENV || 'production', - // Don't bundle react, since we don't expose it anyway and you need to interact - // with those libraries directly in order to use our components. + // Don't bundle preact because our customers need to interact with it directly + // in order to use our components, and we don't expose it in our code. They + // should instead load the preact umd module before loading our bundle. externals: { - react: 'React', - 'react-dom': 'ReactDOM', + preact: 'preact', + }, + plugins: [ + new ProvidePlugin({ + h: ['preact', 'h'], + Fragment: ['preact', 'Fragment'], + }), + ], + resolve: { + alias: { + react: 'preact/compat', + 'react-dom/test-utils': 'preact/test-utils', + 'react-dom': 'preact/compat', // Must be below test-utils + 'react/jsx-runtime': 'preact/jsx-runtime', + }, }, }) ) @@ -258,8 +273,9 @@ const copyReactToDist = (cb) => { gulp .src([ - `${nodeModules}/react/umd/react.production.min.js`, - `${nodeModules}/react-dom/umd/react-dom.production.min.js`, + // `${nodeModules}/react/umd/react.production.min.js`, + // `${nodeModules}/react-dom/umd/react-dom.production.min.js`, + `${nodeModules}/preact/dist/preact.min.umd.js`, ]) .pipe(gulp.dest(`${distPath}/js`)) .on('end', cb); diff --git a/package.json b/package.json index 0bc8b1df0b..bfbbf6edcd 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "postcss": "^8", "postcss-import": "^15.0.0", "postcss-scss": "^4.0.3", + "preact": "10.11.3", "prettier": "^2.6.1", "react": "17.0.2", "react-app-polyfill": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index 216b5f31fd..2480970355 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20459,6 +20459,11 @@ postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12: picocolors "^1.0.0" source-map-js "^1.0.2" +preact@10.11.3: + version "10.11.3" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19" + integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg== + prebuild-install@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" From 823f56800ebcd775f73ffbe4ba507fd8a58c14a3 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 31 Jan 2023 16:18:29 -0800 Subject: [PATCH 05/18] Web components are kind of working If I were doing this for real, I'd make a separate web components bundle so there are no side effects in the npm package. Problem right now is being able to pass `children` to web components. Going to try https://github.com/jahilldev/component-elements/tree/main/packages/preactement#readme next based on [this issue thread](https://github.com/preactjs/preact-custom-element/issues/41) --- examples/cdn-preact/index.html | 4 ++++ packages/design-system/package.json | 3 ++- packages/design-system/src/components/index.ts | 2 ++ .../src/components/web-components/ds-alert.ts | 16 ++++++++++++++++ yarn.lock | 5 +++++ 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 packages/design-system/src/components/web-components/ds-alert.ts diff --git a/examples/cdn-preact/index.html b/examples/cdn-preact/index.html index 0049b25b63..d6707c88ed 100644 --- a/examples/cdn-preact/index.html +++ b/examples/cdn-preact/index.html @@ -45,6 +45,10 @@

CDN Example

); + + Weeeeeee!!! + +
- - Weeeeeee!!! + + Weeeeeee!!! diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 0d8d35e1ce..0885ad2d2e 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -40,7 +40,7 @@ "inquirer": "^9.0.2", "lodash": "^4.17.21", "ora": "^6.1.2", - "preact-custom-element": "4.2.1", + "preactement": "1.8.2", "prop-types": "^15.8.1", "react-day-picker": "^8.0.5", "react-transition-group": "^4.4.2", diff --git a/packages/design-system/src/components/web-components/ds-alert.ts b/packages/design-system/src/components/web-components/ds-alert.ts index d7dbbfb389..c6b98dc94b 100644 --- a/packages/design-system/src/components/web-components/ds-alert.ts +++ b/packages/design-system/src/components/web-components/ds-alert.ts @@ -1,16 +1,14 @@ -import register from 'preact-custom-element'; -import Alert, { AlertProps } from '../Alert/Alert'; +import { define } from 'preactement'; +import Alert from '../Alert/Alert'; -const observedAttributes: Array = [ - 'className', +const attributes = [ + 'class-name', 'heading', - 'headingId', - 'hideIcon', + 'heading-id', + 'hide-icon', 'role', 'weight', 'variation', ]; -// In order for slots to work with `preact-custom-element`, shadow dom has to be -// enabled, but unfortunately that will break the styles because they're global. -register(Alert, 'ds-alert', observedAttributes, { shadow: false }); +define('ds-alert', () => Promise.resolve(Alert), { attributes }); diff --git a/yarn.lock b/yarn.lock index 98fcdf7ec6..52bce2f8a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20459,16 +20459,16 @@ postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12: picocolors "^1.0.0" source-map-js "^1.0.2" -preact-custom-element@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/preact-custom-element/-/preact-custom-element-4.2.1.tgz#a18752ef60823ea61199d9cdc1866e51139b3f46" - integrity sha512-/fiEEAyC+MXRlCBRmv/owoN5BLpO2nF/MF3YBHLtp4C2lNqlhV+a4he74A5DhfDoRmxDHm0sYVgQzWFEyzTDsw== - preact@10.11.3: version "10.11.3" resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19" integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg== +preactement@1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/preactement/-/preactement-1.8.2.tgz#e4a81aff91ad4de50cc6ab25a838d9d371d740cf" + integrity sha512-YJHjmSc3u9bCtkueKDpNHuf3feCSCAc9R5xE2N7BsteBQB7O2cpFpK1yaFZLzmW+lDV/A4vCVFRpANmSL92Dpg== + prebuild-install@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" From 98f78f9682d5c1e7ab84ecaaa81054cf536d6275 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 31 Jan 2023 17:11:35 -0800 Subject: [PATCH 07/18] Tried a different component but same problem I've inspected the Alert render function while it's rendering the web component, and `children` does have a value (it's a rendered React/Preact element, so I can't see what's in it), but nothing ends up in the final output, and that content in between the custom element tags is just sitting there below all the rendered html --- examples/cdn-preact/index.html | 2 ++ packages/design-system/package.json | 2 +- packages/design-system/src/components/index.ts | 1 + .../design-system/src/components/web-components/ds-alert.ts | 2 +- .../design-system/src/components/web-components/ds-badge.ts | 6 ++++++ 5 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 packages/design-system/src/components/web-components/ds-badge.ts diff --git a/examples/cdn-preact/index.html b/examples/cdn-preact/index.html index b858f7eb9b..ad8b249566 100644 --- a/examples/cdn-preact/index.html +++ b/examples/cdn-preact/index.html @@ -34,6 +34,8 @@

CDN Example

cases.

+ Hello world +
- -
- -
ExampleWebsite.gov @@ -34,38 +28,20 @@

CDN Example

cases.

- Hello world - -
- - Weeeeeee!!! + Hello world +
-
+ + From c9700ea5e3155bfb3aaa00db849b99a2dee2ef34 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Thu, 2 Feb 2023 15:46:49 -0800 Subject: [PATCH 10/18] Configure jest to optionally use Preact. Nice mix of pass and fail! Some pass and a lot of snapshot tests fail, as to be expected. Will need to go through these and determine if it makes sense to even test snapshots at all for Preact if we expect so many differences in the resultant DOM ``` Test Suites: 29 failed, 55 passed, 84 total Tests: 66 failed, 636 passed, 702 total Snapshots: 56 failed, 122 passed, 178 total ``` --- babel.config.js | 7 ------- package.json | 1 + tests/unit/jest.config.js | 11 +++++++++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/babel.config.js b/babel.config.js index 18e1f90bd4..9bab076529 100644 --- a/babel.config.js +++ b/babel.config.js @@ -18,13 +18,6 @@ module.exports = function (api) { '@babel/plugin-transform-object-assign', ['babel-plugin-typescript-to-proptypes', { comments: true }], 'inline-react-svg', - [ - '@babel/plugin-transform-react-jsx', - { - pragma: 'h', - pragmaFrag: 'Fragment', - }, - ], ]; return { diff --git a/package.json b/package.json index bfbbf6edcd..850c60a41d 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "test:a11y": "yarn playwright test --config tests/a11y/playwright.config.ts", "test:unit": "yarn jest --config=tests/unit/jest.config.js", "test:unit:update": "yarn test:unit --updateSnapshot", + "test:unit:preact": "PREACT=true yarn jest --config=tests/unit/jest.config.js", "test:browser": "docker run --rm --network host -v $(pwd):/work/ -w /work/ mcr.microsoft.com/playwright:v1.25.0-focal yarn playwright test --config tests/browser/playwright.config.ts", "test:browser:update": "yarn build:storybook && docker run --rm --network host -v $(pwd):/work/ -w /work/ mcr.microsoft.com/playwright:v1.25.0-focal yarn playwright test --config tests/browser/playwright.config.ts -u", "type-check": "yarn tsc --noEmit" diff --git a/tests/unit/jest.config.js b/tests/unit/jest.config.js index f6e6aae1a2..d88b975b9f 100644 --- a/tests/unit/jest.config.js +++ b/tests/unit/jest.config.js @@ -1,3 +1,13 @@ +const usePreact = Boolean(process.env.PREACT && JSON.parse(process.env.PREACT)); +const preactModuleMapper = usePreact + ? { + '^react$': 'preact/compat', + '^react-dom/test-utils$': 'preact/test-utils', + '^react-dom$': 'preact/compat', + '^react/jsx-runtime$': 'preact/jsx-runtime', + } + : {}; + module.exports = { rootDir: '../../packages', testEnvironment: 'jsdom', @@ -18,5 +28,6 @@ module.exports = { moduleNameMapper: { // Remap imports for core to the src directory so we don't have to build first '^@cmsgov/design-system$': '/design-system/src/components/index', + ...preactModuleMapper, }, }; From cf6d1726b9163b43ebc5207e870ee722b6063537 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 16:48:55 -0800 Subject: [PATCH 11/18] Use Preact in Storybook --- .storybook/webpack.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index c102b06d83..2a6658898a 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -73,6 +73,10 @@ module.exports = async ({ config }) => { __dirname, '../packages/design-system/src/styles/' ), + react: 'preact/compat', + 'react-dom/test-utils': 'preact/test-utils', + 'react-dom': 'preact/compat', // Must be below test-utils + 'react/jsx-runtime': 'preact/jsx-runtime', }; return config; From a55788602bb1c6e707ed3088bde5129c4f183481 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 16:49:20 -0800 Subject: [PATCH 12/18] Failed attempt to mix web components into storybook instance Unfortunately I'd need to change the `framework` config for storybook, and you [can't currently mix frameworks](https://github.com/storybookjs/storybook/issues/3889). Going to revert this but wanted a record of the journey --- .../components/web-components/ds-alert.stories.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 packages/design-system/src/components/web-components/ds-alert.stories.tsx diff --git a/packages/design-system/src/components/web-components/ds-alert.stories.tsx b/packages/design-system/src/components/web-components/ds-alert.stories.tsx new file mode 100644 index 0000000000..c1776558a2 --- /dev/null +++ b/packages/design-system/src/components/web-components/ds-alert.stories.tsx @@ -0,0 +1,12 @@ +import Alert from './ds-alert'; + +export default { + title: 'Components/Alert', + component: Alert, + argTypes: {}, +}; + +export const WebComponent = (args) => + `Lorem ipsum dolor sit link text, consectetur + adipiscing elit, sed do eiusmod. Alerts can have chidren, or they can be left off and used + with just a heading prop.`; From 91038bf816b68e006f5cc47e0aa142f8dd1c9b64 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 16:50:53 -0800 Subject: [PATCH 13/18] Revert "Failed attempt to mix web components into storybook instance" This reverts commit a55788602bb1c6e707ed3088bde5129c4f183481. --- .../components/web-components/ds-alert.stories.tsx | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 packages/design-system/src/components/web-components/ds-alert.stories.tsx diff --git a/packages/design-system/src/components/web-components/ds-alert.stories.tsx b/packages/design-system/src/components/web-components/ds-alert.stories.tsx deleted file mode 100644 index c1776558a2..0000000000 --- a/packages/design-system/src/components/web-components/ds-alert.stories.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import Alert from './ds-alert'; - -export default { - title: 'Components/Alert', - component: Alert, - argTypes: {}, -}; - -export const WebComponent = (args) => - `Lorem ipsum dolor sit link text, consectetur - adipiscing elit, sed do eiusmod. Alerts can have chidren, or they can be left off and used - with just a heading prop.`; From c2600f5a98098a2b0deb4ef1fff53c5988b21f8b Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 17:06:11 -0800 Subject: [PATCH 14/18] Bundle is now just web components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until we've gone through each component to make web components versions—and ones that take complex props could be a lot of work—we probably want to have two different bundles. My next commit, therefore, will be to build two different bundles --- gulpfile.js | 8 ++++---- packages/design-system/src/components/index.ts | 3 --- .../src/components/web-components/index.ts | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 packages/design-system/src/components/web-components/index.ts diff --git a/gulpfile.js b/gulpfile.js index d272ad8798..728cbd840d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -227,7 +227,7 @@ compileTypescriptDefs.displayName = '⛓ generating typescript definition files * bundle javascript for CDN */ const bundleJs = (cb) => { - const entry = path.resolve(distPath, 'esnext', 'index.esm.js'); + const entry = path.resolve(distPath, 'esnext', 'web-components', 'index.js'); gulp .src(entry) .pipe( @@ -241,9 +241,9 @@ const bundleJs = (cb) => { // Don't bundle preact because our customers need to interact with it directly // in order to use our components, and we don't expose it in our code. They // should instead load the preact umd module before loading our bundle. - externals: { - preact: 'preact', - }, + // externals: { + // preact: 'preact', + // }, plugins: [ new ProvidePlugin({ h: ['preact', 'h'], diff --git a/packages/design-system/src/components/index.ts b/packages/design-system/src/components/index.ts index 584469d308..6c4322b6d8 100644 --- a/packages/design-system/src/components/index.ts +++ b/packages/design-system/src/components/index.ts @@ -28,9 +28,6 @@ export * from './UsaBanner'; export * from './VerticalNav'; export * from './Icons'; -import './web-components/ds-alert'; -import './web-components/ds-badge'; - export * from './analytics'; export * from './flags'; export * from './i18n'; diff --git a/packages/design-system/src/components/web-components/index.ts b/packages/design-system/src/components/web-components/index.ts new file mode 100644 index 0000000000..e5fa6cdc49 --- /dev/null +++ b/packages/design-system/src/components/web-components/index.ts @@ -0,0 +1,16 @@ +/** + * Entry point for web-components version of the component library + * + * This version necessarily has side-effects because defining custom elements + * in a web page changes the global state of JavaScript in that page; this + * module therefore needs to be marked as having side effects in the package + * file in order to let bundlers know not to remove all the web-component + * modules during tree-shaking. + */ + +export * from '../analytics'; +export * from '../flags'; +export * from '../i18n'; + +export * from './ds-alert'; +export * from './ds-badge'; From 0aa5c4d71f6a41793b7ccacb4c74fe7b5374d19a Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 17:36:08 -0800 Subject: [PATCH 15/18] Create both a preact and web-components bundle --- .../README.md | 0 .../copy.sh | 0 .../index.html | 20 ++------ .../style.css | 0 gulpfile.js | 49 ++++++++++++++----- 5 files changed, 41 insertions(+), 28 deletions(-) rename examples/{cdn-preact => cdn-web-components}/README.md (100%) rename examples/{cdn-preact => cdn-web-components}/copy.sh (100%) rename examples/{cdn-preact => cdn-web-components}/index.html (54%) rename examples/{cdn-preact => cdn-web-components}/style.css (100%) diff --git a/examples/cdn-preact/README.md b/examples/cdn-web-components/README.md similarity index 100% rename from examples/cdn-preact/README.md rename to examples/cdn-web-components/README.md diff --git a/examples/cdn-preact/copy.sh b/examples/cdn-web-components/copy.sh similarity index 100% rename from examples/cdn-preact/copy.sh rename to examples/cdn-web-components/copy.sh diff --git a/examples/cdn-preact/index.html b/examples/cdn-web-components/index.html similarity index 54% rename from examples/cdn-preact/index.html rename to examples/cdn-web-components/index.html index 50efd13371..82d32c757a 100644 --- a/examples/cdn-preact/index.html +++ b/examples/cdn-web-components/index.html @@ -9,12 +9,12 @@ href="https://design.cms.gov/cdn/design-system/6.0.0/css/core-theme.css" /> -
ExampleWebsite.gov + Hello world
@@ -22,26 +22,16 @@

CDN Example

- This is an example showing how to use the CDN. Some elements are simple and can be easily - created by applying a CSS class from the Design System. Some components are more complex - or are interactive. Our React-based component library is here for those more complex - cases. + This is an example showing how to use the CDN and our library of interactive web + components.

- + Weeeeeee!!! - -
- Hello world - -
- - -
- + diff --git a/examples/cdn-preact/style.css b/examples/cdn-web-components/style.css similarity index 100% rename from examples/cdn-preact/style.css rename to examples/cdn-web-components/style.css diff --git a/gulpfile.js b/gulpfile.js index 728cbd840d..3ad5fde0ef 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -224,26 +224,19 @@ const compileTypescriptDefs = (cb) => { compileTypescriptDefs.displayName = '⛓ generating typescript definition files'; /* - * bundle javascript for CDN + * Bundle javascript for CDN */ -const bundleJs = (cb) => { - const entry = path.resolve(distPath, 'esnext', 'web-components', 'index.js'); +const bundleJs = (options, cb) => { gulp - .src(entry) + .src(options.entryPath) .pipe( webpack({ output: { - filename: 'bundle.js', + filename: options.bundleName, // Expose all the index file's exports as a "DesignSystem" global object library: 'DesignSystem', }, mode: process.env.NODE_ENV || 'production', - // Don't bundle preact because our customers need to interact with it directly - // in order to use our components, and we don't expose it in our code. They - // should instead load the preact umd module before loading our bundle. - // externals: { - // preact: 'preact', - // }, plugins: [ new ProvidePlugin({ h: ['preact', 'h'], @@ -258,12 +251,42 @@ const bundleJs = (cb) => { 'react/jsx-runtime': 'preact/jsx-runtime', }, }, + ...(options.webpackConfig ?? {}), }) ) .pipe(gulp.dest(`${distPath}/js`)) .on('end', cb); }; -bundleJs.displayName = '💼 bundling cmsds for cdn with webpack'; + +const bundlePreactComponents = (cb) => { + bundleJs( + { + entryPath: path.resolve(distPath, 'esnext', 'index.esm.js'), + bundleName: 'preact-components.js', + webpackConfig: { + // Don't bundle preact because our customers need to interact with it directly + // in order to use our components, and we don't expose it in our code. They + // should instead load the preact umd module before loading our bundle. + externals: { + preact: 'preact', + }, + }, + }, + cb + ); +}; +bundlePreactComponents.displayName = '💼 bundling Preact components for cdn with webpack'; + +const bundleWebComponents = (cb) => { + bundleJs( + { + entryPath: path.resolve(distPath, 'esnext', 'web-components', 'index.js'), + bundleName: 'web-components.js', + }, + cb + ); +}; +bundleWebComponents.displayName = '💼 bundling web components for cdn with webpack'; /* * copies react bundles currently installed into cdn dist folder @@ -305,7 +328,7 @@ exports.build = gulp.series( cleanDist, gulp.parallel(copyThemes, copyImages, copyFonts, copyJSON), gulp.parallel(compileSass, compileJs, compileEsmJs, compileTypescriptDefs), - gulp.parallel(bundleJs, copyReactToDist) + gulp.series(bundlePreactComponents, bundleWebComponents, copyReactToDist) ); /* From 69819bb094c070a3d182ea7e1c7f635ac665f0d0 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 20:07:52 -0800 Subject: [PATCH 16/18] Update the README for the `preact-app` example --- examples/preact-app/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/preact-app/README.md b/examples/preact-app/README.md index a784294466..2b5c6b3d28 100644 --- a/examples/preact-app/README.md +++ b/examples/preact-app/README.md @@ -1,6 +1,6 @@ ## Example: react-app -This example shows how you can incorporate the design system into your build process. It uses [Webpack](https://webpack.js.org) to bundle and optimize JavaScript files, [Babel](https://babeljs.io/) to transpile JSX, and [Gulp](http://gulpjs.com/) to transpile Sass and copy static assets from the design system. +This example shows how you can incorporate the design system into a Preact application. It uses [Webpack](https://webpack.js.org) to bundle and optimize JavaScript files, [Babel](https://babeljs.io/) to transpile JSX, and [Gulp](http://gulpjs.com/) to copy static assets from the design system. ## Getting started From 8864d3e7213ce5830bf01a2c2c5116e535d6da19 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Mon, 6 Feb 2023 20:14:22 -0800 Subject: [PATCH 17/18] Restore the `cdn-preact` example and updates readmes --- examples/cdn-preact/README.md | 15 +++++++ examples/cdn-preact/copy.sh | 4 ++ examples/cdn-preact/index.html | 65 +++++++++++++++++++++++++++ examples/cdn-preact/style.css | 4 ++ examples/cdn-web-components/README.md | 4 +- 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 examples/cdn-preact/README.md create mode 100644 examples/cdn-preact/copy.sh create mode 100644 examples/cdn-preact/index.html create mode 100644 examples/cdn-preact/style.css diff --git a/examples/cdn-preact/README.md b/examples/cdn-preact/README.md new file mode 100644 index 0000000000..1d29638c16 --- /dev/null +++ b/examples/cdn-preact/README.md @@ -0,0 +1,15 @@ +## Example: Consuming assets from the CDN + +This shows the usage of CMS design system preact components from the CDN: + +- Include the core CSS bundle and theme +- Include the JS vendor files and bundle +- Use CSS layout, utility, and component classes +- Render Preact components from our library + +See also: https://reactjs.org/docs/add-react-to-a-website.html + +## Getting started + +1. Serve the root of this directory from a webserver, with `npx http-server` +2. View it in a browser by visiting http://localhost:8080 diff --git a/examples/cdn-preact/copy.sh b/examples/cdn-preact/copy.sh new file mode 100644 index 0000000000..e8dc957d77 --- /dev/null +++ b/examples/cdn-preact/copy.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +mkdir -p dist/js +cp -R ../../packages/design-system/dist/js/. dist/js/ \ No newline at end of file diff --git a/examples/cdn-preact/index.html b/examples/cdn-preact/index.html new file mode 100644 index 0000000000..271b954def --- /dev/null +++ b/examples/cdn-preact/index.html @@ -0,0 +1,65 @@ + + + + + CDN Example + + + + + + + +
+ + +
+
+ ExampleWebsite.gov +
+
+ +
+
+

CDN Example

+

+ This is an example showing how to use the CDN. Some elements are simple and can be easily + created by applying a CSS class from the Design System. Some components are more complex + or are interactive. Our React-based component library is here for those more complex + cases. +

+ +
+ + +
+
+ + + +
+
+
+ + diff --git a/examples/cdn-preact/style.css b/examples/cdn-preact/style.css new file mode 100644 index 0000000000..a3c84f0ef8 --- /dev/null +++ b/examples/cdn-preact/style.css @@ -0,0 +1,4 @@ +body { + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/examples/cdn-web-components/README.md b/examples/cdn-web-components/README.md index 41f9d069a6..42e9ec377d 100644 --- a/examples/cdn-web-components/README.md +++ b/examples/cdn-web-components/README.md @@ -1,11 +1,11 @@ ## Example: Consuming assets from the CDN -This shows the usage of CMS design system components from the CDN: +This shows the usage of CMS design system web components from the CDN: - Include the core CSS bundle and theme - Include the JS vendor files and bundle - Use CSS layout, utility, and component classes -- Render React components from our library +- Render web components from our library See also: https://reactjs.org/docs/add-react-to-a-website.html From 3e91947af22211295a54fb157b6038fb28434cb1 Mon Sep 17 00:00:00 2001 From: Patrick Wolfert Date: Tue, 7 Feb 2023 10:41:23 -0800 Subject: [PATCH 18/18] Add button to explore interactivity and non-string prop types Unfortunately we have no way as it is now to pass boolean props. I tried setting `analytics="true"`, but the Preact component receives that as a string. We will probably need a layer of abstracting components that translate between attributes and props in a more intentional way. There are also components like MonthPicker with array props that will need a lot of work in this area --- examples/cdn-web-components/index.html | 9 ++++++++- gulpfile.js | 1 + packages/design-system/package.json | 2 +- .../src/components/Button/Button.tsx | 2 +- .../components/web-components/ds-button.ts | 20 +++++++++++++++++++ .../src/components/web-components/index.ts | 1 + 6 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 packages/design-system/src/components/web-components/ds-button.ts diff --git a/examples/cdn-web-components/index.html b/examples/cdn-web-components/index.html index 82d32c757a..5eb47709e2 100644 --- a/examples/cdn-web-components/index.html +++ b/examples/cdn-web-components/index.html @@ -26,9 +26,16 @@

CDN Example

components.

- + Weeeeeee!!! + + I'm a button
diff --git a/gulpfile.js b/gulpfile.js index 3ad5fde0ef..8c83ade2ac 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -237,6 +237,7 @@ const bundleJs = (options, cb) => { library: 'DesignSystem', }, mode: process.env.NODE_ENV || 'production', + devtool: 'source-map', plugins: [ new ProvidePlugin({ h: ['preact', 'h'], diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 61b08186c0..0c35e8ab41 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -17,7 +17,7 @@ "license": "SEE LICENSE IN LICENSE.md", "main": "dist/components/index.js", "module": "dist/esnext/index.esm.js", - "sideEffects": ["./dist/esnext/web-components/ds-alert.js", "./dist/esnext/web-components/ds-badge.js"], + "sideEffects": ["./dist/esnext/web-components/ds-alert.js", "./dist/esnext/web-components/ds-badge.js", "./dist/esnext/web-components/ds-button.js"], "types": "dist/types/index.d.ts", "files": [ "dist", diff --git a/packages/design-system/src/components/Button/Button.tsx b/packages/design-system/src/components/Button/Button.tsx index abc96e459d..410af9dc9d 100644 --- a/packages/design-system/src/components/Button/Button.tsx +++ b/packages/design-system/src/components/Button/Button.tsx @@ -154,7 +154,7 @@ export const Button = (props: ButtonProps) => { Button.defaultProps = { isAlternate: false, onDark: false, - type: 'button', + type: 'button' as const, }; export default Button; diff --git a/packages/design-system/src/components/web-components/ds-button.ts b/packages/design-system/src/components/web-components/ds-button.ts new file mode 100644 index 0000000000..7e83c91c48 --- /dev/null +++ b/packages/design-system/src/components/web-components/ds-button.ts @@ -0,0 +1,20 @@ +import { define } from 'preactement'; +import Button from '../Button/Button'; + +const attributes = [ + 'class-name', + 'disabled', + 'href', + 'is-alternate', + 'on-dark', + 'size', + 'type', + 'variation', + 'analytics', + 'analytics-label-override', + 'analytics-event-type-override', + 'analytics-parent-heading', + 'analytics-parent-type', +]; + +define('ds-button', () => Button, { attributes }); diff --git a/packages/design-system/src/components/web-components/index.ts b/packages/design-system/src/components/web-components/index.ts index e5fa6cdc49..6d1df5aefa 100644 --- a/packages/design-system/src/components/web-components/index.ts +++ b/packages/design-system/src/components/web-components/index.ts @@ -14,3 +14,4 @@ export * from '../i18n'; export * from './ds-alert'; export * from './ds-badge'; +export * from './ds-button';