From 9f9acddeb0d9b5ae90f69ecb55ebec8c46789620 Mon Sep 17 00:00:00 2001 From: JCNoguera <88061365+VmMad@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:25:22 +0200 Subject: [PATCH] feat(apps-ui-kit): add `Button` component (#1010) * feat(ui): kickoff * feat(ui): update package name * feat(ui): update headers * refactor: move folders around and add aliases * fix: cleanup exports field in package.json * fix: update alias import to use "@" * fix: manypkg check * feat: add configs necessary for the package * fix: update styles import * fix(tooling-ui): linter * refactor!: rename folder * refactor: rename missing strings * fix!: revert and update lockfile * feat(wip): add custom tailwind palettes * feat: add necessary palettes for tailwind * fix: remove unused file * feat: add header to css files * fix: remove change * refactor: format files * fix: update import route * feat(tooling/ui): add button component * fix: add missing scales to tailwind * fix: update border radius and color tertiary * fix: update paddings to new scaling * feat(tooling-ui): add darkmode with an example button * fix: run manypkg fix * feat: add dark and light modes to `Button` * refactor: update tsconfig and use a different file for package compilation * fix: update opacity 8 to be `0.08` instead of `0.8` * manypkg fix * fix: formatting * regenerate lock file * fix: formatting * feat: add enums alias to tsconfig * feat: use tailwindcss darkmode for classes * refactor: remove unused file * fix: remove export * fix: remove outdated styling * fix: add correct export * feat: add shader color palette * fix: improve name of shaders * feat(tooling-ui): add support for darkmode in storybook (#1022) * feat(tooling-ui): add darkmode with an example button * fix: run manypkg fix * regenerate lock file * feat: use tailwindcss darkmode for classes * refactor: remove unused file * fix: remove export * chore: remove debris from story --------- Co-authored-by: marc2332 * fix: format * fix: Button story props --------- Co-authored-by: evavirseda Co-authored-by: cpl121 <100352899+cpl121@users.noreply.github.com> Co-authored-by: cpl121 Co-authored-by: Bran <52735957+brancoder@users.noreply.github.com> Co-authored-by: Marc Espin --- apps/ui-kit/.storybook/preview-head.html | 4 +- apps/ui-kit/package.json | 1 + apps/ui-kit/postcss.config.js | 1 + apps/ui-kit/src/lib/components/Button.tsx | 16 -- .../lib/components/atoms/button/Button.tsx | 72 +++++++++ .../components/atoms/button/button.classes.ts | 53 +++++++ .../components/atoms/button/button.enums.ts | 15 ++ .../src/lib/components/atoms/button/index.ts | 6 + apps/ui-kit/src/lib/components/atoms/index.ts | 4 + apps/ui-kit/src/lib/components/index.ts | 2 +- apps/ui-kit/src/lib/styles/index.css | 35 +++++ .../stories/atoms/Button.stories.tsx | 31 +++- pnpm-lock.yaml | 145 ++++++++---------- 13 files changed, 276 insertions(+), 109 deletions(-) delete mode 100644 apps/ui-kit/src/lib/components/Button.tsx create mode 100644 apps/ui-kit/src/lib/components/atoms/button/Button.tsx create mode 100644 apps/ui-kit/src/lib/components/atoms/button/button.classes.ts create mode 100644 apps/ui-kit/src/lib/components/atoms/button/button.enums.ts create mode 100644 apps/ui-kit/src/lib/components/atoms/button/index.ts create mode 100644 apps/ui-kit/src/lib/components/atoms/index.ts diff --git a/apps/ui-kit/.storybook/preview-head.html b/apps/ui-kit/.storybook/preview-head.html index 92c1aef28a0..b0c19050920 100644 --- a/apps/ui-kit/.storybook/preview-head.html +++ b/apps/ui-kit/.storybook/preview-head.html @@ -2,10 +2,10 @@ diff --git a/apps/ui-kit/package.json b/apps/ui-kit/package.json index 34508ca4016..234242b033f 100644 --- a/apps/ui-kit/package.json +++ b/apps/ui-kit/package.json @@ -32,6 +32,7 @@ }, "dependencies": { "@fontsource/inter": "^5.0.17", + "classnames": "^2.5.1", "lodash.merge": "^4.6.2", "react": "^18.3.1", "react-dom": "^18.3.1" diff --git a/apps/ui-kit/postcss.config.js b/apps/ui-kit/postcss.config.js index 0fa3edd478d..5ec04be2c17 100644 --- a/apps/ui-kit/postcss.config.js +++ b/apps/ui-kit/postcss.config.js @@ -3,6 +3,7 @@ module.exports = { plugins: { + 'tailwindcss/nesting': {}, tailwindcss: {}, autoprefixer: {}, }, diff --git a/apps/ui-kit/src/lib/components/Button.tsx b/apps/ui-kit/src/lib/components/Button.tsx deleted file mode 100644 index 2352a80effe..00000000000 --- a/apps/ui-kit/src/lib/components/Button.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import React from 'react'; - -export interface ButtonProps { - label: string; -} - -export function Button({ label }: ButtonProps): React.JSX.Element { - return ( - - ); -} diff --git a/apps/ui-kit/src/lib/components/atoms/button/Button.tsx b/apps/ui-kit/src/lib/components/atoms/button/Button.tsx new file mode 100644 index 00000000000..bd7bd268725 --- /dev/null +++ b/apps/ui-kit/src/lib/components/atoms/button/Button.tsx @@ -0,0 +1,72 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; +import { ButtonSize, ButtonType } from './button.enums'; +import { + PADDINGS, + PADDINGS_ONLY_ICON, + BACKGROUND_COLORS, + TEXT_COLORS, + TEXT_CLASSES, + TEXT_COLOR_DISABLED, + DISABLED_BACKGROUND_COLORS, +} from './button.classes'; +import cx from 'classnames'; + +interface ButtonProps { + /** + * The size of the button. + */ + size?: ButtonSize; + /** + * The type of the button + */ + type?: ButtonType; + /** + * The text of the button. + */ + text?: string; + /** + The icon of the button + */ + icon?: React.ReactNode; + /** + * The button is disabled or not. + */ + disabled?: boolean; + /** + * The onClick event of the button. + */ + onClick?: (e: React.MouseEvent) => void; +} + +export function Button({ + icon, + text, + disabled, + onClick, + size = ButtonSize.Medium, + type = ButtonType.Primary, +}: ButtonProps): React.JSX.Element { + const paddingClasses = icon && !text ? PADDINGS_ONLY_ICON[size] : PADDINGS[size]; + const textSizes = TEXT_CLASSES[size]; + const backgroundColors = disabled ? DISABLED_BACKGROUND_COLORS[type] : BACKGROUND_COLORS[type]; + const textColors = disabled ? TEXT_COLOR_DISABLED[type] : TEXT_COLORS[type]; + return ( + + ); +} diff --git a/apps/ui-kit/src/lib/components/atoms/button/button.classes.ts b/apps/ui-kit/src/lib/components/atoms/button/button.classes.ts new file mode 100644 index 00000000000..8fe776c82f7 --- /dev/null +++ b/apps/ui-kit/src/lib/components/atoms/button/button.classes.ts @@ -0,0 +1,53 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { ButtonSize, ButtonType } from './button.enums'; + +export const PADDINGS: Record = { + [ButtonSize.Small]: 'px-md py-xs', + [ButtonSize.Medium]: 'px-md py-sm', +}; + +export const PADDINGS_ONLY_ICON: Record = { + [ButtonSize.Small]: 'p-xs', + [ButtonSize.Medium]: 'p-sm', +}; + +export const BACKGROUND_COLORS: Record = { + [ButtonType.Primary]: 'bg-primary-30', + [ButtonType.Secondary]: 'bg-neutral-90 dark:bg-neutral-20', + [ButtonType.Ghost]: 'bg-transparent', + [ButtonType.Outlined]: 'bg-transparent border border-neutral-50', + [ButtonType.Destructive]: 'bg-error-90', +}; + +export const DISABLED_BACKGROUND_COLORS: Record = { + [ButtonType.Primary]: 'bg-neutral-80 dark:bg-neutral-30', + [ButtonType.Secondary]: 'bg-neutral-90 dark:bg-neutral-20', + [ButtonType.Ghost]: 'bg-transparent', + [ButtonType.Outlined]: 'bg-transparent border border-neutral-50', + [ButtonType.Destructive]: 'bg-error-90', +}; + +const DEFAULT_TEXT_COLORS: string = 'text-neutral-10 dark:text-neutral-92'; + +export const TEXT_COLORS: Record = { + [ButtonType.Primary]: 'text-primary-100', + [ButtonType.Secondary]: DEFAULT_TEXT_COLORS, + [ButtonType.Ghost]: DEFAULT_TEXT_COLORS, + [ButtonType.Outlined]: DEFAULT_TEXT_COLORS, + [ButtonType.Destructive]: 'text-error-20', +}; + +export const TEXT_CLASSES: Record = { + [ButtonSize.Small]: 'text-label-md', + [ButtonSize.Medium]: 'text-label-lg', +}; + +export const TEXT_COLOR_DISABLED: Record = { + [ButtonType.Primary]: DEFAULT_TEXT_COLORS, + [ButtonType.Secondary]: DEFAULT_TEXT_COLORS, + [ButtonType.Ghost]: DEFAULT_TEXT_COLORS, + [ButtonType.Outlined]: DEFAULT_TEXT_COLORS, + [ButtonType.Destructive]: 'text-error-20', +}; diff --git a/apps/ui-kit/src/lib/components/atoms/button/button.enums.ts b/apps/ui-kit/src/lib/components/atoms/button/button.enums.ts new file mode 100644 index 00000000000..a58bc17534b --- /dev/null +++ b/apps/ui-kit/src/lib/components/atoms/button/button.enums.ts @@ -0,0 +1,15 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +export enum ButtonSize { + Small = 'small', + Medium = 'medium', +} + +export enum ButtonType { + Primary = 'primary', + Secondary = 'secondary', + Ghost = 'ghost', + Outlined = 'outlined', + Destructive = 'destructive', +} diff --git a/apps/ui-kit/src/lib/components/atoms/button/index.ts b/apps/ui-kit/src/lib/components/atoms/button/index.ts new file mode 100644 index 00000000000..e0310d5fa03 --- /dev/null +++ b/apps/ui-kit/src/lib/components/atoms/button/index.ts @@ -0,0 +1,6 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +export * from './Button'; + +export * from './button.enums'; diff --git a/apps/ui-kit/src/lib/components/atoms/index.ts b/apps/ui-kit/src/lib/components/atoms/index.ts new file mode 100644 index 00000000000..55a1be03a07 --- /dev/null +++ b/apps/ui-kit/src/lib/components/atoms/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +export * from './button'; diff --git a/apps/ui-kit/src/lib/components/index.ts b/apps/ui-kit/src/lib/components/index.ts index 72acc235fee..116943b99c3 100644 --- a/apps/ui-kit/src/lib/components/index.ts +++ b/apps/ui-kit/src/lib/components/index.ts @@ -3,4 +3,4 @@ import '../styles/index.css'; -export * from './Button'; +export * from './atoms'; diff --git a/apps/ui-kit/src/lib/styles/index.css b/apps/ui-kit/src/lib/styles/index.css index a35cd17f147..14e4002e1c2 100644 --- a/apps/ui-kit/src/lib/styles/index.css +++ b/apps/ui-kit/src/lib/styles/index.css @@ -46,3 +46,38 @@ font-feature-settings: 'ss01' on; } } + +@layer utilities { + .state-layer, + .state-layer-inverted { + &::after { + content: ''; + border-radius: inherit; + @apply absolute; + @apply h-full w-full; + @apply left-0 top-0; + @apply opacity-0; + @apply transition-opacity duration-75; + } + + &:hover::after { + @apply opacity-8; + } + + &:active::after { + @apply opacity-12; + } + } + + .state-layer { + &::after { + @apply bg-primary-60; + } + } + + .state-layer-inverted { + &::after { + @apply bg-primary-80; + } + } +} diff --git a/apps/ui-kit/src/storybook/stories/atoms/Button.stories.tsx b/apps/ui-kit/src/storybook/stories/atoms/Button.stories.tsx index 7b7c60a6974..39d8e118302 100644 --- a/apps/ui-kit/src/storybook/stories/atoms/Button.stories.tsx +++ b/apps/ui-kit/src/storybook/stories/atoms/Button.stories.tsx @@ -3,17 +3,14 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { Button } from '@/components'; +import { Button } from '@/components/atoms/button/Button'; +import { ButtonSize, ButtonType } from '@/components/atoms/button'; const meta = { component: Button, tags: ['autodocs'], render: (props) => { - return ( -
-
- ); + return