Skip to content

Commit e0c3541

Browse files
authored
chore: 🤖 distribution unbundled (#773)
* chore: 🤖 update required packages * chore: 🤖 provide styled components types * fix: 🐛 linter should ignore d.ts files * fix: 🐛 use double quotes * fix: 🐛 vite > v2 separates vitest config * chore: 🤖 reorder package * chore: 🤖 remove side property (deprecated) * fix: 🐛 dropdown amends * fix: 🐛 theme prop * fix: 🐛 type * chore: 🤖 TIAS build version supported on next v16 RSC * chore: 🤖 WIP ongoing styled-component v6.1.11 (non experimental) support * chore: 🤖 strict react version for dev * fix: 🐛 missing ref on forwardRef, might have plenty of these * chore: 🤖 update lockfile * chore: 🤖 remove optional flag from ref (typo) * chore: 🤖 add comment for future ref * refactor: 💡 banner * chore: 🤖 lint amends (double quotes) * refactor: 💡 removes style prop as typed prop * chore: 🤖 remove ajv * chore: 🤖 format * test: 💍 add aria pressed to ButtonGroup * chore: 🤖 format * test: 💍 use local getByText * chore: 🤖 update lockfile * chore: 🤖 add changeset * chore: 🤖 small text amend to trigger vercel deploy * chore: 🤖 prevent running on CI * chore: 🤖 add HUSKY to preven husky runnig pre-commit hook * fix: 🐛 conflict resolution * chore: 🤖 bump rc number * docs: 📝 build esm, how to use * chore: 🤖 ESM vite builder (wip) * fix: 🐛 remove .tsx extension from import statements * fix: 🐛 remove .tsx extension from import statements * fix: 🐛 remove .tsx extension from import statements * fix: 🐛 remove .ts extension from import statements * fix: 🐛 remove .ts extension from import statements * chore: 🤖 add eslint to assess import extensions not required * chore: 🤖 format * chore: 🤖 temporary custom resolve tsconfig path * refactor: 💡 export from correct theme boundary * chore: 🤖 node externals in vite, remove alias * chore: 🤖 use relative paths * chore: 🤖 use externalize deps * chore: 🤖 for ESM compatibility, tweak/handle CJS components * chore: revert ts alias rewrite to relative * chore: lint do not allow barrel imports * chore: remove excludes from tsconfig * chore: set vite settings to preserve file struct in output * fix: solve import cycles * fix: solve import cycles in stories * fix: build amends * fix: add .js extension * chore: analyze and visualise bundle * chore: split ESM, CJS distribution * chore: format * fix: 🐛 lint code block * fix: 🐛 import Separator * chore: format * fix: 🐛 import Separator * chore: 🤖 add changeset * chore: 🤖 use 0.0.251-rc.62 * chore: 🤖 resolve conflict resolution, deleted files which were removed in main branch * chore: 🤖 resolve conflict resolution, middle truncator * chore: 🤖 resolve conflict resolution, missing container changes * refactor: 💡 FileMultiUpload to follow FileUpload due to middle truncator * fix: 🐛 prevent icon success pushed right * fix: 🐛 remove file size from multiple file upload * chore: 🤖 merge conflict amend for ButtonGroup * chore: 🤖 remove comment * chore: 🤖 missing typecheck call on build * chore: 🤖 missing import * chore: 🤖 checkout datedetails from main * chore: 🤖 remove comment * docs: 📝 prefer american english * chore: 🤖 add note * chore: 🤖 update package.json * fix: 🐛 merge latest conflicts amends * docs: 📝 conflict amends
1 parent f70e04f commit e0c3541

95 files changed

Lines changed: 757 additions & 381 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/chatty-chairs-drop.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@clickhouse/click-ui": minor
3+
---
4+
5+
Makes the distributed files "unbundled", effectively moving optimisation to a consumer app concern, e.g. obfuscation, compression, bundling MUST be consumer concerns, the library SHOULD NOT make the consumer bundling process more difficult, it MUST facilitate it! It resolves cyclic imports or circular dependencies, enhances linting to prevent imports from barrel files, making the barrel files more of a public API than an internal API to help prevent circular dependencies.
6+
7+
From now on, bundling preserves the file tree, externalises packages based on the package.json dependency declaration automatically, instead of managing them manually as the current version does. It allows deep imports, e.g. @clickhouse/click-ui/components/Button.
8+
9+
Exports files are placed by target resolution, e.g. dist/esm|cjs. It has removed UMD until further notice (why is the original version providing UMD, what's the use-case?). As a component library, in principle, it should be ESM and CJS (due to NodeJS SSR) compatible in the worse case scenarios.
10+
11+
It reduces build times from > 1 minute to < 22 seconds.
12+
13+
More importantly, this initial revision provides tree-shaking support, helping reduce file size. Which can now be assessed with an optional builder feature to analyse and visualise the package dependency graph, file sizes, etc.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ storybook-static
88
**/.DS_Store
99
vite.config.ts.timestamp*
1010
.storybook/out
11+
tmp/*
1112

1213
.yarn/*
1314
!.yarn/releases

README.md

Lines changed: 108 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ You can find the official docs for the Click UI design system and component libr
2828
* [Storybook](#storybook)
2929
- [Stories development server](#stories-development-server)
3030
- [Public static site](#public-static-site)
31+
* [Distribution](#distribution)
32+
- [Build](#build)
33+
- [Use Click UI](#use-click-ui)
34+
- [Deep imports support](#deep-imports-support)
35+
- [Examples](#examples)
3136
* [Assets Management](#assets-management)
3237
- [Add a new SVG logo or icon](#add-new-svg-logo-or-icon)
3338
* [Releases and Versions](#releases-and-versions)
@@ -96,6 +101,7 @@ You can start the Storybook development server by:
96101
yarn dev
97102
```
98103

104+
99105
We do NOT maintain a separate development environment; our Storybook stories serve as the source of truth for component implementation.
100106

101107
> [!IMPORTANT]
@@ -142,7 +148,6 @@ Once ready, you can run tests by:
142148
```sh
143149
yarn test:chromatic
144150
```
145-
146151
> [!NOTE]
147152
> Chromatic does NOT generate a report in the terminal due to its cloud nature, which only outputs:
148153
> - Build status, e.g. uploading or testing
@@ -179,50 +184,12 @@ Once built, you can serve the static files by:
179184
yarn storybook:serve
180185
```
181186

182-
### Public static site
187+
### Public Static Site
183188

184189
The latest static version's built and deployed automatically when contributing to `main` of [Click UI](https://github.com/ClickHouse/click-ui).
185190

186191
Once deployed it's available publicly at [clickhouse.design/click-ui](https://clickhouse.design/click-ui).
187192

188-
## How-to use
189-
190-
Click UI has been tested in NextJS, Gatsby, and Vite. If you run into problems using it in your app, please create an issue and our team will try to answer.
191-
192-
1. Navigate to your app's route and run
193-
`npm i @clickhouse/click-ui`
194-
or
195-
`yarn add @clickhouse/click-ui`
196-
2. Make sure to wrap your application in the Click UI `ClickUIProvider`, without doing this, you may run into issues with styled-components. Once that's done, you'll be able to import the individual components that you want to use on each page. Here's an example of an `App.tsx` in NextJS.
197-
198-
```typescript
199-
import { ClickUIProvider, Text, ThemeName, Title, Switch } from '@clickhouse/click-ui'
200-
import { useState } from 'react'
201-
202-
function App() {
203-
const [theme, setTheme] = useState<ThemeName>('dark')
204-
205-
const toggleTheme = () => {
206-
theme === 'dark' ? setTheme('light') : setTheme('dark')
207-
}
208-
209-
return (
210-
<ClickUIProvider theme={theme} config={{tooltip:{ delayDuration: 0 }}}>
211-
<Switch
212-
checked={theme === 'dark'}
213-
onCheckedChange={() => toggleTheme()}
214-
label="Dark mode"
215-
/>
216-
217-
<Title type='h1'>Click UI Example</Title>
218-
<Text>Welcome to Click UI. Get started here.</Text>
219-
</ClickUIProvider>
220-
)
221-
}
222-
223-
export default App
224-
```
225-
226193
## Changeset
227194

228195
Learn to manage the versioning of changelog entries.
@@ -269,6 +236,107 @@ To consume all changesets, and update to the most appropriate semver version and
269236
yarn changeset:version
270237
```
271238

239+
## Distribution
240+
241+
The package is distributed as ESM.
242+
243+
### Build
244+
245+
To build the distribution version of the package run:
246+
247+
```sh
248+
yarn build
249+
```
250+
251+
> [!NOTE]
252+
> Optimizations are responsability of consumer or host apps, e.g. they can't remove unused code if already minified it! We ship unminified code so their build tools can: analyse and remove what they don't need or dead code, debug more easily, compress everything together in one go instead of handling conflicting compression algorithms, etc.
253+
254+
### Use Click UI
255+
256+
Navigate to your app's work directory and add the package.
257+
258+
Here, we use `yarn` but you can use your favorite package manager, e.g. pnpm.
259+
260+
```sh
261+
yarn add @clickhouse/click-ui
262+
```
263+
> [!NOTE]
264+
> Click UI should be supported by react frameworks.
265+
> If you run into any issues consuming it in your react app, report it [here](https://github.com/ClickHouse/click-ui/issues/new). Provide all important details, including information on how to replicate the issue!
266+
267+
Once installed, wrap the application with Click UI provider:
268+
269+
```js
270+
import { ClickUIProvider } from '@clickhouse/click-ui'
271+
272+
export default () => {
273+
return (
274+
<ClickUIProvider theme='light'>
275+
<p>Hello world!</p>
276+
</ClickUIProvider>
277+
);
278+
}
279+
```
280+
281+
After, you are able to import your favorite [Click UI components](https://clickhouse.design/click-ui).
282+
283+
```js
284+
import { ClickUIProvider, Title } from '@clickhouse/click-ui'
285+
286+
export default () => {
287+
return (
288+
<ClickUIProvider theme='light'>
289+
<Title type='h1'>Click UI Example</Title>
290+
</ClickUIProvider>
291+
);
292+
}
293+
```
294+
295+
To learn more about individual components, visit [Click UI components](https://clickhouse.design/click-ui).
296+
297+
### Deep imports support
298+
299+
Deep imports are supported, you can import directly from path.
300+
301+
> [!WARNING]
302+
> At time of writing, there are components that consume from theme provider, which means that these will fail when unwrapped. This will change in future versions.
303+
304+
```ts
305+
import { Button } from '@clickhouse/click-ui/Button';
306+
```
307+
308+
### Examples
309+
310+
Here's a quick copy and paste NextJS example with interactive components you can play:
311+
312+
```ts
313+
import { ClickUIProvider, Text, ThemeName, Title, Switch } from '@clickhouse/click-ui'
314+
import { useState } from 'react'
315+
316+
function App() {
317+
const [theme, setTheme] = useState<ThemeName>('dark')
318+
319+
const toggleTheme = () => {
320+
theme === 'dark' ? setTheme('light') : setTheme('dark')
321+
}
322+
323+
return (
324+
<ClickUIProvider theme={theme} config={{tooltip:{ delayDuration: 0 }}}>
325+
<Switch
326+
checked={theme === 'dark'}
327+
onCheckedChange={() => toggleTheme()}
328+
label="Dark mode"
329+
/>
330+
331+
<Title type='h1'>Click UI Example</Title>
332+
<Text>Welcome to Click UI. Get started here.</Text>
333+
</ClickUIProvider>
334+
)
335+
}
336+
337+
export default App
338+
```
339+
272340
## Assets management
273341

274342
The Click UI has image asset files, such as icons or logos.

eslint.config.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,23 @@ export default tseslint.config(
7777
tsx: 'never',
7878
},
7979
],
80+
'no-restricted-imports': [
81+
'error',
82+
{
83+
paths: [
84+
{
85+
name: '@/components',
86+
message:
87+
'Do not import from the components barrel inside the library. Import from leaf modules (e.g., ../Icon/Icon) to avoid cycles.',
88+
},
89+
{
90+
name: '@/index',
91+
message:
92+
'Do not import from the package entry internally. Import from leaf modules instead.',
93+
},
94+
],
95+
},
96+
],
8097
'@typescript-eslint/no-deprecated': 'warn',
8198
},
8299
},

package.json

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,36 @@
77
"files": [
88
"dist"
99
],
10+
"main": "./dist/cjs/index.cjs",
11+
"module": "./dist/esm/index.js",
12+
"types": "./dist/types/index.d.ts",
13+
"sideEffects": false,
1014
"exports": {
1115
".": {
12-
"types": "./dist/index.d.ts",
13-
"import": "./dist/click-ui.es.js",
14-
"require": "./dist/click-ui.umd.js"
16+
"types": "./dist/types/index.d.ts",
17+
"import": "./dist/esm/index.js",
18+
"require": "./dist/cjs/index.cjs"
1519
},
16-
"./bundled": {
17-
"types": "./dist/index.d.ts",
18-
"import": "./dist/click-ui.bundled.es.js",
19-
"require": "./dist/click-ui.bundled.umd.js"
20+
"./*": {
21+
"types": "./dist/types/*.d.ts",
22+
"import": "./dist/esm/*.js",
23+
"require": "./dist/cjs/*.cjs"
2024
}
2125
},
22-
"main": "./dist/click-ui.umd.js",
23-
"module": "./dist/click-ui.es.js",
24-
"types": "./dist/index.d.ts",
2526
"keywords": [
2627
"click-ui",
2728
"clickhouse",
2829
"design system"
2930
],
3031
"repository": {
3132
"type": "git",
32-
"url": "https://github.com/ClickHouse/click-ui.git"
33+
"url": "git+https://github.com/ClickHouse/click-ui.git"
3334
},
3435
"homepage": "https://clickhouse.com",
3536
"scripts": {
36-
"build": "tsc && vite build && yarn build:bundled",
37+
"build": "yarn typecheck && vite build",
38+
"build:analyze": "ANALYZE=true vite build",
3739
"build-storybook": "storybook build",
38-
"build:bundled": "vite build -- bundled",
3940
"build:watch": "watch 'yarn build' ./src",
4041
"changeset:add": "yarn changeset",
4142
"changeset:status": "yarn changeset status",
@@ -81,7 +82,8 @@
8182
"@radix-ui/react-tabs": "1.1.1",
8283
"@radix-ui/react-toast": "1.2.2",
8384
"@radix-ui/react-tooltip": "1.1.2",
84-
"lodash": "^4.17.21",
85+
"dayjs": "1.11.19",
86+
"lodash-es": "^4.17.23",
8587
"react-sortablejs": "^6.1.4",
8688
"react-syntax-highlighter": "^16.1.0",
8789
"react-virtualized-auto-sizer": "^1.0.20",
@@ -102,7 +104,7 @@
102104
"@testing-library/user-event": "^14.5.2",
103105
"@tokens-studio/sd-transforms": "^1.2.0",
104106
"@types/eslint-plugin-react-refresh": "^0.4.0",
105-
"@types/lodash-es": "^4.17.7",
107+
"@types/lodash-es": "^4.17.12",
106108
"@types/node": "^24.10.1",
107109
"@types/react": "18.3.1",
108110
"@types/react-dom": "18.3.1",
@@ -115,7 +117,6 @@
115117
"babel-plugin-styled-components": "^2.1.4",
116118
"chromatic": "^13.3.4",
117119
"date-fns": "4.1.0",
118-
"dayjs": "1.11.13",
119120
"eslint": "^9",
120121
"eslint-import-resolver-typescript": "^4.4.4",
121122
"eslint-plugin-import": "^2.32.0",
@@ -130,6 +131,7 @@
130131
"prop-types": "^15.8.1",
131132
"react": "18.3.1",
132133
"react-dom": "18.3.1",
134+
"rollup-plugin-visualizer": "^6.0.5",
133135
"storybook": "^10.1.10",
134136
"storybook-addon-pseudo-states": "^10.1.10",
135137
"style-dictionary": "^5.0.0",
@@ -139,6 +141,8 @@
139141
"typescript-eslint": "^8",
140142
"vite": "^7.3.0",
141143
"vite-plugin-dts": "^4.3.0",
144+
"vite-plugin-externalize-deps": "^0.10.0",
145+
"vite-tsconfig-paths": "^6.0.5",
142146
"vitest": "^2.1.8",
143147
"watch": "^1.0.2"
144148
},

src/components/Accordion/Accordion.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import * as RadixAccordion from '@radix-ui/react-accordion';
22
import { styled } from 'styled-components';
33
import { IconSize } from '@/components/Icon/types';
4-
import { Icon, IconName, Spacer, Text } from '@/components';
4+
import { Icon } from '@/components/Icon/Icon';
5+
import { IconName } from '@/components/Icon/types';
6+
import { Spacer } from '@/components/Spacer/Spacer';
7+
import { Text } from '@/components/Typography/Text/Text';
58
import { ReactNode } from 'react';
69

710
type Size = 'sm' | 'md' | 'lg';

src/components/Alert/Alert.stories.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Meta, StoryObj } from '@storybook/react-vite';
22

3-
import { Alert, Container, Link } from '@/components';
3+
import { Alert } from '@/components/Alert/Alert';
4+
import { Container } from '@/components/Container/Container';
5+
import { Link } from '@/components/Link/Link';
46
import { ICON_NAMES } from '@/components/Icon/IconCommon';
57

68
const meta: Meta<typeof Alert> = {

src/components/Alert/Alert.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Icon } from '@/components';
1+
import { Icon } from '@/components/Icon/Icon';
22
import { IconName } from '@/components/Icon/types';
33
import { useState, ReactNode, useCallback } from 'react';
44
import { styled } from 'styled-components';

src/components/AutoComplete/AutoComplete.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { act, fireEvent } from '@testing-library/react';
2-
import { AutoComplete, AutoCompleteProps } from '@/components';
2+
import { AutoComplete } from '@/components/AutoComplete/AutoComplete';
3+
import type { AutoCompleteProps } from '@/components/AutoComplete/AutoComplete';
34
import { renderCUI } from '@/utils/test-utils';
45
import { selectOptions } from '../Select/selectOptions';
56
describe('AutoComplete', () => {

0 commit comments

Comments
 (0)