mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
dbeaver/pro#6968 feat: add storybook (#3767)
* dbeaver/pro#6968 feat: add storybook * chore: remove duplicate * fix: ladle * chore: remove storybook onboarding * adds task to run storybook --------- Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
This commit is contained in:
co-authored by
sergeyteleshev
parent
4f53ece164
commit
d1c2d6547f
Vendored
+9
@@ -136,6 +136,15 @@
|
||||
"cwd": "${workspaceFolder}/webapp/common-react/@dbeaver/ui-kit"
|
||||
},
|
||||
"args": ["docs"]
|
||||
},
|
||||
{
|
||||
"label": "Run Storybook",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/webapp/packages/storybook"
|
||||
},
|
||||
"args": ["storybook"]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { assetResolverPlugin } from '@wroud/vite-plugin-asset-resolver';
|
||||
import { tscPlugin } from '@wroud/vite-plugin-tsc';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
/** @type {import('vite').UserConfig} */
|
||||
export default {
|
||||
export default defineConfig({
|
||||
server: {
|
||||
fs: {
|
||||
strict: false,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
svgr(),
|
||||
tailwindcss(),
|
||||
@@ -15,4 +28,4 @@ export default {
|
||||
prebuild: true,
|
||||
}),
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import cloudbeaverPlugin from '@cloudbeaver/eslint-plugin';
|
||||
import pluginReact from 'eslint-plugin-react';
|
||||
import reactHooks from 'eslint-plugin-react-hooks';
|
||||
@@ -12,8 +13,10 @@ import tseslint from 'typescript-eslint';
|
||||
import eslint from '@eslint/js';
|
||||
import stylistic from '@stylistic/eslint-plugin';
|
||||
import eslintConfigPrettier from 'eslint-config-prettier';
|
||||
import storybook from 'eslint-plugin-storybook';
|
||||
|
||||
export default tseslint.config(
|
||||
export default defineConfig(
|
||||
storybook.configs['flat/recommended'],
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
pluginReact.configs.flat.recommended,
|
||||
@@ -238,6 +241,6 @@ export default tseslint.config(
|
||||
},
|
||||
{
|
||||
files: ['**/*.cjs'],
|
||||
ignores: ['**/lib'],
|
||||
ignores: ['**/lib', '!.storybook'],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"eslint-config-prettier": "^10",
|
||||
"eslint-plugin-react": "^7",
|
||||
"eslint-plugin-react-hooks": "^5",
|
||||
"eslint-plugin-storybook": "^9",
|
||||
"typescript-eslint": "^8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*storybook.log
|
||||
storybook-static
|
||||
@@ -0,0 +1,132 @@
|
||||
@import 'tailwindcss' layer(base) prefix(tw);
|
||||
|
||||
@layer theme {
|
||||
main {
|
||||
color: var(--dbv-kit-color-foreground);
|
||||
background-color: var(--tw-color-gray-50);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--tw-color-blue-600);
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: var(--tw-color-blue-700);
|
||||
text-decoration-thickness: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
color: var(--tw-color-orange-700);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h3,
|
||||
h5 {
|
||||
font-weight: var(--tw-font-weight-semibold);
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 0.5em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--tw-text-2xl);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--tw-text-xl);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: var(--tw-text-lg);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: var(--tw-text-base);
|
||||
margin-block-start: 0.5em;
|
||||
margin-block-end: 0.5em;
|
||||
}
|
||||
|
||||
kbd {
|
||||
background-color: #eee;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #b4b4b4;
|
||||
box-shadow:
|
||||
0 1px 1px rgba(0, 0, 0, 0.2),
|
||||
0 2px 0 0 rgba(255, 255, 255, 0.7) inset;
|
||||
color: #333;
|
||||
display: inline-block;
|
||||
font-size: 0.85em;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
padding: 2px 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.codeblock {
|
||||
background-color: var(--tw-color-gray-100);
|
||||
padding: 1em;
|
||||
border-radius: 0.25em;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
}
|
||||
|
||||
.comment {
|
||||
color: var(--tw-color-gray-500);
|
||||
}
|
||||
|
||||
.color-sample {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] {
|
||||
--dbv-kit-color-foreground: var(--tw-color-gray-200);
|
||||
--dbv-kit-color-background: var(--tw-color-gray-900);
|
||||
--dbv-kit-btn-loader-base-color: var(--tw-color-gray-900);
|
||||
|
||||
/* Primary Button */
|
||||
--dbv-kit-btn-primary-foreground: var(--tw-color-gray-100);
|
||||
--dbv-kit-btn-primary-background: var(--dbv-kit-color-primary-700);
|
||||
--dbv-kit-btn-primary-background-hover: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-primary-background-active: var(--dbv-kit-color-primary-500);
|
||||
|
||||
/* Secondary Button */
|
||||
--dbv-kit-btn-secondary-foreground: var(--tw-color-gray-100);
|
||||
--dbv-kit-btn-secondary-background: transparent;
|
||||
--dbv-kit-btn-secondary-background-hover: var(--tw-color-gray-800);
|
||||
--dbv-kit-btn-secondary-background-active: var(--tw-color-gray-700);
|
||||
--dbv-kit-btn-secondary-border-color: var(--tw-color-gray-200);
|
||||
|
||||
/* Danger Button */
|
||||
--dbv-kit-btn-danger-foreground: var(--tw-color-gray-100);
|
||||
--dbv-kit-btn-danger-background: var(--tw-color-red-700);
|
||||
--dbv-kit-btn-danger-background-hover: var(--tw-color-red-600);
|
||||
--dbv-kit-btn-danger-background-active: var(--tw-color-red-500);
|
||||
|
||||
/* Input */
|
||||
--dbv-kit-input-background: var(--tw-color-gray-800);
|
||||
--dbv-kit-input-border-color: var(--tw-color-gray-700);
|
||||
--dbv-kit-input-color: var(--tw-color-gray-100);
|
||||
--dbv-kit-input-placeholder-foreground: var(--tw-color-gray-400);
|
||||
|
||||
main {
|
||||
background-color: var(--tw-color-gray-900);
|
||||
}
|
||||
|
||||
code {
|
||||
color: var(--tw-color-orange-400);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--tw-color-blue-300);
|
||||
}
|
||||
|
||||
.codeblock {
|
||||
background-color: var(--tw-color-gray-800);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { StorybookConfig } from '@storybook/react-vite';
|
||||
|
||||
import { join, dirname } from 'path';
|
||||
|
||||
/**
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
|
||||
*/
|
||||
function getAbsolutePath(value: string): any {
|
||||
return dirname(require.resolve(join(value, 'package.json')));
|
||||
}
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
addons: [getAbsolutePath('@storybook/addon-docs')],
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/react-vite'),
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
export default config;
|
||||
@@ -0,0 +1,15 @@
|
||||
import './global.css';
|
||||
import type { Preview } from '@storybook/react-vite';
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@cloudbeaver/storybook",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dbeaver/ui-kit": "workspace:^",
|
||||
"react": "^19",
|
||||
"react-dom": "^19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudbeaver/tsconfig": "workspace:*",
|
||||
"@storybook/addon-docs": "^9",
|
||||
"@storybook/react-vite": "^9",
|
||||
"@tailwindcss/vite": "4.0.7",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@vitejs/plugin-react": "^5",
|
||||
"@wroud/vite-plugin-asset-resolver": "^0",
|
||||
"@wroud/vite-plugin-tsc": "^0",
|
||||
"globals": "^16",
|
||||
"storybook": "^9",
|
||||
"tailwindcss": "4.0.7",
|
||||
"typescript": "^5",
|
||||
"vite": "^7"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
# Button
|
||||
|
||||
The Button component is a simple button that can be used in different contexts. It has several visual parameters that can be customized.
|
||||
|
||||
## Class names
|
||||
|
||||
- `.dbv-kit-button` - the main class name for the button component.
|
||||
- `.dbv-kit-button--primary` - the class name for the primary variant.
|
||||
- `.dbv-kit-button--secondary` - the class name for the secondary variant.
|
||||
- `.dbv-kit-button--danger` - the class name for the danger variant.
|
||||
- `.dbv-kit-button--small` - the class name for the small size.
|
||||
- `.dbv-kit-button--medium` - the class name for the medium size.
|
||||
- `.dbv-kit-button--large` - the class name for the large size.
|
||||
- `.dbv-kit-button--xlarge` - the class name for the extra large size.
|
||||
|
||||
---
|
||||
|
||||
- `.dbv-kit-button__icon` - the class name for the icon component.
|
||||
- `.dbv-kit-button__icon--start` - the class name for the icon with placement="start".
|
||||
- `.dbv-kit-button__icon--end` - the class name for the icon with placement="end".
|
||||
|
||||
Underlying components docs:
|
||||
[https://ariakit.org/reference/button](https://ariakit.org/reference/button)
|
||||
|
||||
### Props:
|
||||
|
||||
**variant**
|
||||
primary | secondary | danger
|
||||
|
||||
**size**
|
||||
small | medium | large | xlarge
|
||||
|
||||
**loading**
|
||||
boolean
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
|
||||
# Button CSS Tokens
|
||||
|
||||
This UI kit uses several CSS tokens to style buttons.
|
||||
|
||||
## Common buttons tokens
|
||||
|
||||
### Size and space
|
||||
|
||||
- `--dbv-kit-btn-height:` var(--dbv-kit-control-height-medium) - Default button height
|
||||
- `--dbv-kit-btn-padding-inline:` --spacing(2.5) - Medium button inline paddings, other sizes are calculated based on that variable
|
||||
- `--dbv-kit-btn-gap:` calc(var(--dbv-kit-btn-padding-inline) /4) - Gap between button elements (mostly text and icon)
|
||||
- `--dbv-kit-btn-outline-offset:` 1px - Button outline offset
|
||||
|
||||
### Basic colors
|
||||
|
||||
- `--dbv-kit-btn-foreground:` var(--color-white) - Default button text color
|
||||
- `--dbv-kit-btn-background:` var(--dbv-kit-color-primary-600) - Default button background color
|
||||
- `--dbv-kit-btn-background-hover:` var(--dbv-kit-color-primary-700) - Button hover background color
|
||||
- `--dbv-kit-btn-background-active:` var(--dbv-kit-color-primary-800) - Button active background color
|
||||
|
||||
### Border
|
||||
|
||||
- `--dbv-kit-btn-border-width:` 1px - Button border width
|
||||
- `--dbv-kit-btn-border-color:` transparent; --dbv-kit-btn-border-style: solid - Button border color and style
|
||||
- `--dbv-kit-btn-border-radius:` var(--radius-md) - Button border radius
|
||||
|
||||
### Font
|
||||
|
||||
- `--dbv-kit-btn-font-weight:` var(--font-weight-normal) - Button font weight
|
||||
- `--dbv-kit-btn-font-size:` calc(var(--dbv-kit-font-size-base) * 0.875) - Button font size, default for medium-sized button, other sizes calculated based on that value
|
||||
|
||||
### Loader
|
||||
|
||||
- `--dbv-kit-btn-loader-base-color:` var(--tw-color-white) - This color used in loader to mix with other button colors like `color: color-mix(in srgb, var(--dbv-kit-btn-foreground) 25%, var(--dbv-kit-btn-loader-base-color))`. It should be light in light mode and one of the dark colors for dark theme.
|
||||
- `--dbv-kit-btn-loader-animation:` var(--animate-spin) - Button loader animation
|
||||
|
||||
### Others
|
||||
|
||||
- `--dbv-kit-btn-disabled-opacity:` 0.5 - Button opacity when disabled
|
||||
|
||||
## Specific buttons tokens
|
||||
|
||||
### Button Sizes
|
||||
|
||||
The `--dbv-kit-btn-*-height` tokens are used to define the height of buttons for different size variants. Default buttons use `--control-height-*` variable as the base height.
|
||||
|
||||
- Small button height: `--dbv-kit-btn-small-height`
|
||||
- Medium button height: `--dbv-kit-btn-medium-height`
|
||||
- Large button height: `--dbv-kit-btn-large-height`
|
||||
- Extra large button height: `--dbv-kit-btn-xlarge-height`
|
||||
|
||||
### Button Padding
|
||||
|
||||
The `--dbv-kit-btn-*-padding-inline` tokens are used to define the padding of buttons for different size variants.
|
||||
|
||||
- Small button padding: `--dbv-kit-btn-small-padding-inline`
|
||||
- Medium button padding: `--dbv-kit-btn-medium-padding-inline`
|
||||
- Large button padding: `--dbv-kit-btn-large-padding-inline`
|
||||
- Extra large button padding: `--dbv-kit-btn-xlarge-padding-inline`
|
||||
|
||||
### Button Colors
|
||||
|
||||
- Primary button background: `--dbv-kit-btn-primary-background`
|
||||
- Primary button background (hover): `--dbv-kit-btn-primary-background-hover`
|
||||
- Primary button background (active): `--dbv-kit-btn-primary-background-active`
|
||||
- Secondary button background: `--dbv-kit-btn-secondary-background`
|
||||
- Secondary button background (hover): `--dbv-kit-btn-secondary-background-hover`
|
||||
- Secondary button background (active): `--dbv-kit-btn-secondary-background-active`
|
||||
- Secondary button border color: `--dbv-kit-btn-secondary-border-color`
|
||||
- Danger button background: `--dbv-kit-btn-danger-background`
|
||||
- Danger button background (hover): `--dbv-kit-btn-danger-background-hover`
|
||||
- Danger button background (active): `--dbv-kit-btn-danger-background-active`
|
||||
|
||||
The `--dbv-kit-btn-*-background` and `--dbv-kit-btn-*-foreground` tokens are used to define the background and text color of buttons for different variants (primary, secondary, danger).
|
||||
|
||||
To set another background or text color for your button, you can override the respective `--dbv-kit-btn-*` tokens in your CSS.
|
||||
|
||||
### Button Borders
|
||||
|
||||
Button border width: `--dbv-kit-btn-border-width`
|
||||
|
||||
The `--dbv-kit-btn-border-width` token is used to define the border width of buttons.
|
||||
|
||||
To change the border size of your button, you can override the `--dbv-kit-btn-border-width` token in your CSS.
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { Button, ButtonIcon } from '@dbeaver/ui-kit';
|
||||
import { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { useState } from 'react';
|
||||
|
||||
const meta = {
|
||||
component: Button,
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
options: ['primary', 'secondary', 'danger'],
|
||||
control: {
|
||||
type: 'select',
|
||||
},
|
||||
defaultValue: 'primary',
|
||||
},
|
||||
size: {
|
||||
options: ['small', 'medium', 'large', 'xlarge'],
|
||||
control: {
|
||||
type: 'select',
|
||||
},
|
||||
defaultValue: 'medium',
|
||||
},
|
||||
loading: {
|
||||
control: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Variants = () => (
|
||||
<div>
|
||||
<h3 className="tw:text-lg tw:my-2">Variants</h3>
|
||||
<p>Button component has 3 predefined variants: primary, secondary, and danger.</p>
|
||||
<div className="codeblock tw:bg-gray-100 tw:p-4 tw:my-4">
|
||||
<code><Button variant="primary"/></code>
|
||||
</div>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button loading>Loading</Button>
|
||||
<Button>Primary</Button>
|
||||
<Button disabled>Disabled</Button>
|
||||
</div>
|
||||
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button variant="secondary" loading>
|
||||
Secondary
|
||||
</Button>
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="secondary" disabled>
|
||||
Disabled
|
||||
</Button>
|
||||
</div>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button variant="danger" loading>
|
||||
Danger
|
||||
</Button>
|
||||
<Button variant="danger">Danger</Button>
|
||||
<Button variant="danger" disabled>
|
||||
Disabled
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="tw:my-4">
|
||||
<h3>Design tokens for variants</h3>
|
||||
<p className="tw:text-base">
|
||||
Primary button background: <code>--dbv-kit-btn-primary-background</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Primary button background (hover): <code>--dbv-kit-btn-primary-background-hover</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Primary button background (active): <code>--dbv-kit-btn-primary-background-active</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Secondary button background: <code>--dbv-kit-btn-secondary-background</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Secondary button background (hover): <code>--dbv-kit-btn-secondary-background-hover</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Secondary button background (active): <code>--dbv-kit-btn-secondary-background-active</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Secondary button border color: <code>--dbv-kit-btn-secondary-border-color</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Danger button background: <code>--dbv-kit-btn-danger-background</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Danger button background (hover): <code>--dbv-kit-btn-danger-background-hover</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Danger button background (active): <code>--dbv-kit-btn-danger-background-active</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Sizes = () => (
|
||||
<div>
|
||||
<h2 className="tw:text-lg tw:my-2">Sizes</h2>
|
||||
<p>Button component has 4 predefined sizes: small, medium, large, and extra large. Check the examples below:</p>
|
||||
<div className="tw:flex tw:flex-col tw:gap-4">
|
||||
<Button size="small">Small</Button>
|
||||
<Button size="medium">Medium</Button>
|
||||
<Button size="large">Large button</Button>
|
||||
<Button size="xlarge">EXTRA Large button</Button>
|
||||
</div>
|
||||
<h3>Design tokens for sizes</h3>
|
||||
<p>
|
||||
The Button component uses the following design tokens to define the sizes of the buttons. You can customize these tokens to change the button
|
||||
sizes.
|
||||
</p>
|
||||
<div className="tw:my-4">
|
||||
<p className="tw:text-base">
|
||||
Small button height: <code>--dbv-kit-btn-small-height</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Medium button height: <code>--dbv-kit-btn-medium-height</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Large button height: <code>--dbv-kit-btn-large-height</code>
|
||||
</p>
|
||||
<p className="tw:text-base">
|
||||
Extra large button height: <code>--dbv-kit-btn-xlarge-height</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Icons = () => (
|
||||
<div>
|
||||
<h2>Icons</h2>
|
||||
<h3><ButtonIcon></h3>
|
||||
<code>.dbv-kit-button__icon</code>
|
||||
<p>
|
||||
To properly place an icon inside a button, you have to use ButtonIcon component. That component will compensate outer padding to balance the
|
||||
button view. You need to specify the placement property to adjust the icon position.
|
||||
</p>
|
||||
<dl>
|
||||
<dt className="tw:font-semibold">placement</dt>
|
||||
<dd>start | end</dd>
|
||||
</dl>
|
||||
<div className="codeblock">
|
||||
<code>
|
||||
<Button> <br /> <ButtonIcon placement="start"/>
|
||||
<br />
|
||||
Text
|
||||
<br /> <Button/>
|
||||
</code>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>Compare buttons:</h4>
|
||||
<div className="tw:flex tw:gap-4 tw:items-center tw:my-4">
|
||||
<Button variant="secondary">
|
||||
<ButtonIcon placement="start">🧤</ButtonIcon>
|
||||
Text
|
||||
</Button>
|
||||
<Button variant="secondary">🧤 Text</Button>
|
||||
</div>
|
||||
<p>
|
||||
The left button uses ButtonIcon component and looks more balanced. If you feel that in your case it's not needed, feel free to not use the
|
||||
<b> ButtonIcon </b> component.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3>Tokens</h3>
|
||||
<div>
|
||||
<code>--dbv-kit-btn-icon-margin-inline</code> - the margin between the icon and the text, by default calculated based on{' '}
|
||||
<code>--dbv-kit-btn-padding-inline</code> for each size.
|
||||
</div>
|
||||
|
||||
<h3>Examples</h3>
|
||||
<p>
|
||||
Here are some examples of how to use the Button component with icons. Don't forget to check the source code by pressing <kbd>s</kbd>
|
||||
</p>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button size="small">
|
||||
Love
|
||||
<ButtonIcon placement="end">❤️</ButtonIcon>
|
||||
</Button>
|
||||
|
||||
<Button className="tw:text-lime-300">
|
||||
Have you seen
|
||||
<ButtonIcon className="w-2">
|
||||
<svg width="16" height="16" fill="none">
|
||||
<g strokeWidth="0"></g>
|
||||
<g strokeLinecap="round" strokeLinejoin="round"></g>
|
||||
<g>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M8 16L3.54223 12.3383C1.93278 11.0162 1 9.04287 1 6.96005C1 3.11612 4.15607 0 8 0C11.8439 0 15 3.11612 15 6.96005C15 9.04287 14.0672 11.0162 12.4578 12.3383L8 16ZM3 6H5C6.10457 6 7 6.89543 7 8V9L3 7.5V6ZM11 6C9.89543 6 9 6.89543 9 8V9L13 7.5V6H11Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</ButtonIcon>
|
||||
UFO?
|
||||
</Button>
|
||||
|
||||
<Button size="large">
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
|
||||
<Button size="xlarge">
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis is Love
|
||||
<ButtonIcon placement="end">❤️</ButtonIcon>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button loading>
|
||||
<ButtonIcon className="tw:w-8 tw:h-4" placement="start">
|
||||
<svg width="16" height="16" fill="none">
|
||||
<g strokeWidth="0"></g>
|
||||
<g strokeLinecap="round" strokeLinejoin="round"></g>
|
||||
<g>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M8 16L3.54223 12.3383C1.93278 11.0162 1 9.04287 1 6.96005C1 3.11612 4.15607 0 8 0C11.8439 0 15 3.11612 15 6.96005C15 9.04287 14.0672 11.0162 12.4578 12.3383L8 16ZM3 6H5C6.10457 6 7 6.89543 7 8V9L3 7.5V6ZM11 6C9.89543 6 9 6.89543 9 8V9L13 7.5V6H11Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</ButtonIcon>
|
||||
UFO
|
||||
</Button>
|
||||
<Button variant="secondary" loading>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
<Button disabled>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
<Button variant="danger">
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
<Button>
|
||||
<ButtonIcon>🎾</ButtonIcon>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const CustomLoader = () => (
|
||||
<div>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="tw:animate-spin tw:p-1">
|
||||
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeDasharray="31.415, 31.415" />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Loading = () => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
function toggleLoading() {
|
||||
setLoading(prev => !prev);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Loading</h2>
|
||||
<h3>Design tokens</h3>
|
||||
<p>
|
||||
<code>--dbv-kit-btn-loader-base-color:</code> var(--tw-color-white);{' '}
|
||||
<span className="comment">
|
||||
// This color used in loader to mix with other button colors like{' '}
|
||||
<i> color: color-mix(in srgb, var(--dbv-kit-btn-foreground) 25%, var(--dbv-kit-btn-loader-base-color));</i> It should be light in light mode
|
||||
and one of the dark colors for dark theme.
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<label>
|
||||
Enable loaders <input type="checkbox" checked={loading} onChange={toggleLoading} />
|
||||
</label>
|
||||
<h3>Default loader</h3>
|
||||
<p>Button component has a default loader that appears when the loading property is set to true.</p>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button loading={loading}>Primary</Button>
|
||||
<Button variant="secondary" loading={loading}>
|
||||
Secondary
|
||||
</Button>
|
||||
<Button variant="danger" loading={loading}>
|
||||
Danger
|
||||
</Button>
|
||||
</div>
|
||||
<h3> Custom loader</h3>
|
||||
|
||||
<p>Buttons support custom loaders.</p>
|
||||
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button loading={loading} loader={<span className="tw:flex tw:items-center tw:animate-spin">⚽️</span>}>
|
||||
Loading
|
||||
</Button>
|
||||
|
||||
<Button loading={loading} loader={<span className="tw:absolute tw:animate-bounce">🚴</span>}>
|
||||
Loading
|
||||
</Button>
|
||||
|
||||
<Button loading={loading} loader={<CustomLoader />}>
|
||||
Custom SVG Loader
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const WithCustomRendering = () => {
|
||||
return (
|
||||
<div>
|
||||
<h3 className="tw:text-lg tw:my-2">Custom renders</h3>
|
||||
<p>
|
||||
Button can be rendered as different HTML element using <code>render</code> property. Read more{' '}
|
||||
<a href="https://ariakit.org/reference/button#render">in AriaKit documentation</a>
|
||||
</p>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button render={<a target="_blank" href="/" />} size="small">
|
||||
Link button
|
||||
</Button>
|
||||
<Button variant="secondary" render={<a />}>
|
||||
Link secondary
|
||||
</Button>
|
||||
<Button render={({ children, className }) => <p className={className}>{children} render</p>} size="medium">
|
||||
Paragraph
|
||||
</Button>
|
||||
</div>
|
||||
<h3 className="tw:text-lg tw:my-2">Change on focus</h3>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button onFocusVisible={e => (e.currentTarget.textContent = 'Click me!')} render={<a href="/" />} size="small">
|
||||
Link button
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"extends": "@cloudbeaver/tsconfig/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../../common-react/@dbeaver/ui-kit"
|
||||
}
|
||||
],
|
||||
"include": [
|
||||
"__custom_mocks__/**/*",
|
||||
"src/**/*",
|
||||
"src/**/*.json",
|
||||
"src/**/*.css",
|
||||
"src/**/*.scss"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
"dist/**/*",
|
||||
"lib/**/*"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../common-react/@dbeaver/ui-kit"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2023",
|
||||
"lib": [
|
||||
"ES2023"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../common-react/@dbeaver/ui-kit"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { tscPlugin } from '@wroud/vite-plugin-tsc';
|
||||
import { assetResolverPlugin } from '@wroud/vite-plugin-asset-resolver';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
tscPlugin({
|
||||
tscArgs: ['-b'],
|
||||
prebuild: true,
|
||||
enableOverlay: true,
|
||||
}),
|
||||
assetResolverPlugin(),
|
||||
tailwindcss(),
|
||||
],
|
||||
});
|
||||
+792
-15
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user