diff --git a/bun.lockb b/bun.lockb index c1b55d0..6d1df4e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/dist/package.json b/dist/package.json index 5505ab4..77e8deb 100644 --- a/dist/package.json +++ b/dist/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@lit/react": "^1.0.6", + "dompurify": "^3.2.2", "lit": "^3.2.1" }, "peerDependencies": { diff --git a/package.json b/package.json index 580a153..2836031 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,12 @@ }, "dependencies": { "@lit/react": "^1.0.6", + "dompurify": "^3.2.2", "lit": "^3.2.1" }, "devDependencies": { "@biomejs/biome": "1.9.4", "@chromatic-com/storybook": "^3.2.2", - "@computas/designsystem-breadcrumbs": "workspace:*", "@computas/designsystem-icon": "workspace:*", "@storybook/addon-essentials": "^8.4.6", "@storybook/addon-themes": "^8.4.6", diff --git a/src/components/breadcrumbs/breadcrumbs.story.ts b/src/components/breadcrumbs/breadcrumbs.story.ts deleted file mode 100644 index ffb2b66..0000000 --- a/src/components/breadcrumbs/breadcrumbs.story.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components'; -import { html } from 'lit-html'; - -import './breadcrumbs'; - -export default { - title: 'Components/Breadcrumbs (do not use this component)', -} satisfies Meta; - -export const Default: StoryObj = { - render: ({ variant }) => html`I'm a breadcrumbs`, - argTypes: { - variant: { - control: 'radio', - options: ['primary', 'secondary'], - description: 'Changes the visual appearance of the button', - }, - }, - args: { - variant: 'primary', - }, -}; diff --git a/src/components/breadcrumbs/breadcrumbs.ts b/src/components/breadcrumbs/breadcrumbs.ts deleted file mode 100644 index c80e709..0000000 --- a/src/components/breadcrumbs/breadcrumbs.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { LitElement, css, html } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; -import { classMap } from 'lit/directives/class-map.js'; - -@customElement('cx-breadcrumbs') -export class Breadcrumbs extends LitElement { - static styles = css``; - - /** - * @description Controls the appearance of the button - * @default "primary" - */ - @property() - variant: 'primary' | 'secondary' = 'primary'; - - render() { - return html` - - `; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'cx-breadcrumbs': Breadcrumbs; - } -} diff --git a/src/components/breadcrumbs/index.ts b/src/components/breadcrumbs/index.ts deleted file mode 100644 index 8d59853..0000000 --- a/src/components/breadcrumbs/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './breadcrumbs'; diff --git a/src/components/breadcrumbs/package.json b/src/components/breadcrumbs/package.json deleted file mode 100644 index f29f61b..0000000 --- a/src/components/breadcrumbs/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "@computas/designsystem-breadcrumbs", - "version": "1.0.0", - "type": "module", - "private": "true", - "scripts": { - "build": "tsup" - }, - "devDependencies": { - "tsup": "^8.3.5" - } -} diff --git a/src/components/breadcrumbs/react.ts b/src/components/breadcrumbs/react.ts deleted file mode 100644 index 6c36d79..0000000 --- a/src/components/breadcrumbs/react.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createComponent } from '@lit/react'; -import * as React from 'react'; - -import { Breadcrumbs } from './index'; - -export const CxBreadcrumbs = createComponent({ - tagName: 'cx-breadcrumbs', - elementClass: Breadcrumbs, - react: React, -}); diff --git a/src/components/icon/Overview.mdx b/src/components/icon/Overview.mdx new file mode 100644 index 0000000..c976905 --- /dev/null +++ b/src/components/icon/Overview.mdx @@ -0,0 +1,88 @@ +import { + Canvas, + Description, + IconGallery, + IconItem, + Meta, + Source, + Subtitle, + Title, +} from "@storybook/blocks"; + +import { iconNames } from "./icon-names"; +import * as stories from "./icon.stories"; + + + + + +The icon component is implemented as a web component where you manually register each icon you want to use in your application. +This is to ensure that you only include the icons that you need in your bundle. To register a an icon for use, please call the `addIcons()` +function with an object containing your icons, as such: + +<Source + code={` + import { addIcons } from '@computas/designsystem/icon'; + +// import the icon data (SVG string) +import download from '@computas/designsystem/icon/svg/download?raw'; + +addIcons({ +download: { svg: download } +}); +`} +language="ts" +dark +/> + +The registration of icons is usually done at the root level of your application, and makes the icon available globally. +After registering an icon, use it through the `cx-icon` component. Start by importing the component: + +<Source + code={` +// Web component +import '@computas/designsystem/icon'; + +// React +import { CxIcon } from '@computas/designsystem/icon/react'; +`} +language="ts" +dark +/> + +Then simply use the component and provide the name of the icon you wish to display: + +<Source + code={` +// Web component +<cx-icon name="download" /> + +// React + +<CxIcon name="download" /> +`} language="ts" dark /> + +If you try to use an icon that is not registered, the component throws an error. + +<br /> +## Icon overview + +<IconGallery> + {iconNames.map((iconName) => ( + <IconItem name={iconName} key={iconName}> + <cx-icon name={iconName} /> + </IconItem> + ))} +</IconGallery> + +## Sizing + +The icon component can be sized through the `size` prop. The prop accepts the same values as our spacing tokens, in other words a number between 1 and 20. + +<Canvas of={stories.Sizing} /> + +## Color + +The icon component can be sized through the `size` prop. The prop accepts the same values as our spacing tokens, in other words a number between 1 and 20. + +<Canvas of={stories.Color} /> diff --git a/src/components/icon/icon-names.ts b/src/components/icon/icon-names.ts new file mode 100644 index 0000000..86491d7 --- /dev/null +++ b/src/components/icon/icon-names.ts @@ -0,0 +1,69 @@ +export const iconNames = [ + 'add', + 'agenda', + 'alarm', + 'ansatte', + 'attachment', + 'baby', + 'back', + 'beer', + 'bin', + 'bookmark', + 'calendar-filled', + 'calendar', + 'check-circle', + 'check', + 'close', + 'computas', + 'default-presenter', + 'digital-cafe', + 'down', + 'download', + 'edit', + 'email', + 'error-circle', + 'event-games', + 'event-general', + 'event-social', + 'eventer', + 'external', + 'flex', + 'forward', + 'history', + 'hyperlink', + 'image', + 'info-circle', + 'kks', + 'laptop', + 'left', + 'location', + 'log-out', + 'message', + 'microphone', + 'min-side-headphones', + 'min-side', + 'multiple-actions-question', + 'phone', + 'play', + 'preview', + 'qr', + 'right', + 'search', + 'security', + 'send-email', + 'settings', + 'sick', + 'slack', + 'sort-ascending', + 'sort-descending', + 'sorting', + 'star-add', + 'star-added', + 'tech', + 'three-dot-menu-horizontal', + 'time', + 'up', + 'upload', + 'vacation', + 'warning', +]; diff --git a/src/components/icon/icon.stories.ts b/src/components/icon/icon.stories.ts new file mode 100644 index 0000000..1337452 --- /dev/null +++ b/src/components/icon/icon.stories.ts @@ -0,0 +1,56 @@ +import type { Meta, StoryObj } from '@storybook/web-components'; +import { html } from 'lit'; + +import './icon'; +import './register-demo-icons'; + +export default { + title: 'Components/Icon', +} satisfies Meta; + +export const Sizing: StoryObj = { + render: () => html` + <cx-icon name="download" size="1" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="2" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="3" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="4" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="5" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="6" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="7" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="8" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="9" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="10" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="11" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="12" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="13" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="14" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="15" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="16" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="17" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="18" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="19" class="cx-mr-4"></cx-icon> +<cx-icon name="download" size="20"></cx-icon> + `, +}; + +export const Color: StoryObj = { + render: () => html` + <style> + .danger-icon { + color: var(--cx-color-signal-danger); + } + + .info-icon { + color: var(--cx-color-signal-info); + } + + .success-icon { + color: var(--cx-color-signal-success); + } + </style> + + <cx-icon name="star-added" size="10" class="cx-mr-4 danger-icon"></cx-icon> + <cx-icon name="star-added" size="10" class="cx-mr-4 info-icon"></cx-icon> + <cx-icon name="star-added" size="10" class="cx-mr-4 success-icon"></cx-icon> + `, +}; diff --git a/src/components/icon/icon.ts b/src/components/icon/icon.ts index 1be0f85..3cd8f48 100644 --- a/src/components/icon/icon.ts +++ b/src/components/icon/icon.ts @@ -5,13 +5,33 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { getIcon } from './store'; -type IconSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; +type IconSize = + | '1' + | '2' + | '3' + | '4' + | '5' + | '6' + | '7' + | '8' + | '9' + | '10' + | '11' + | '12' + | '13' + | '14' + | '15' + | '16' + | '17' + | '18' + | '19' + | '20'; @customElement('cx-icon') export class Icon extends LitElement { static readonly styles = css` :host { - --_icon-size: 32px; + --_icon-size: 24px; display: inline-block; width: var(--_icon-size); @@ -19,33 +39,26 @@ export class Icon extends LitElement { line-height: 0; } - :host([size='xxs']) { - --_icon-size: 8px; - } - - :host([size='xs']) { - --_icon-size: 16px; - } - - :host([size='sm']) { - --_icon-size: 24px; - } - - :host([size='md']) { - --_icon-size: 32px; - } - - :host([size='lg']) { - --_icon-size: 40px; - } - - :host([size='xl']) { - --_icon-size: 48px; - } - - :host([size='xxl']) { - --_icon-size: 56px; - } + :host([size='1']) { --_icon-size: 0.25rem; } + :host([size='2']) { --_icon-size: 0.5rem; } + :host([size='3']) { --_icon-size: 0.75rem; } + :host([size='4']) { --_icon-size: 1rem; } + :host([size='5']) { --_icon-size: 1.25rem; } + :host([size='6']) { --_icon-size: 1.5rem; } + :host([size='7']) { --_icon-size: 1.75rem; } + :host([size='8']) { --_icon-size: 2rem; } + :host([size='9']) { --_icon-size: 2.25rem; } + :host([size='10']) { --_icon-size: 2.5rem; } + :host([size='11']) { --_icon-size: 2.75rem; } + :host([size='12']) { --_icon-size: 3rem; } + :host([size='13']) { --_icon-size: 3.25rem; } + :host([size='14']) { --_icon-size: 3.5rem; } + :host([size='15']) { --_icon-size: 3.75rem; } + :host([size='16']) { --_icon-size: 4rem; } + :host([size='17']) { --_icon-size: 4.25rem; } + :host([size='18']) { --_icon-size: 4.5rem; } + :host([size='19']) { --_icon-size: 4.75rem; } + :host([size='20']) { --_icon-size: 5rem; } svg { width: 100%; diff --git a/src/components/icon/package.json b/src/components/icon/package.json index f4d65af..7c917c2 100644 --- a/src/components/icon/package.json +++ b/src/components/icon/package.json @@ -4,7 +4,7 @@ "type": "module", "private": "true", "scripts": { - "build": "tsup" + "build": "tsup && cp -r svg ../../../dist/icon/svg" }, "devDependencies": { "tsup": "^8.3.5" diff --git a/src/components/icon/register-demo-icons.ts b/src/components/icon/register-demo-icons.ts new file mode 100644 index 0000000..d8286e2 --- /dev/null +++ b/src/components/icon/register-demo-icons.ts @@ -0,0 +1,7 @@ +import { iconNames } from './icon-names'; +import { addIcons } from './store'; + +iconNames.forEach(async (iconName) => { + const icon = await import(`./svg/${iconName}.svg?raw`); + addIcons({ [iconName]: { svg: icon.default } }); +}); diff --git a/tsconfig.json b/tsconfig.json index 9912d36..a9ebc1d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,5 @@ "noUncheckedSideEffectImports": true }, "include": ["src/**/*.ts"], - "exclude": ["src/**/*.stories.ts"] // <-- this is the line we need to add + "exclude": ["src/**/*.stories.ts"] } diff --git a/src/vite-env.d.ts b/vite-env.d.ts similarity index 100% rename from src/vite-env.d.ts rename to vite-env.d.ts