Use nested css
This commit is contained in:
parent
ad844be552
commit
d004ba56fd
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@codex-storage/marketplace-ui-components",
|
"name": "@codex-storage/marketplace-ui-components",
|
||||||
"version": "0.0.27",
|
"version": "0.0.28",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@codex-storage/marketplace-ui-components",
|
"name": "@codex-storage/marketplace-ui-components",
|
||||||
"version": "0.0.27",
|
"version": "0.0.28",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lucide-react": "^0.453.0"
|
"lucide-react": "^0.453.0"
|
||||||
|
@ -41,6 +41,7 @@
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@codex-storage/sdk-js": ">=0.0.12",
|
"@codex-storage/sdk-js": ">=0.0.12",
|
||||||
|
"postcss-nesting": "^13.0.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^18.3.1"
|
||||||
}
|
}
|
||||||
|
@ -628,6 +629,50 @@
|
||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@csstools/selector-resolve-nested": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/csstools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/csstools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"postcss-selector-parser": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@csstools/selector-specificity": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/csstools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/csstools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"postcss-selector-parser": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.23.1",
|
"version": "0.23.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
|
||||||
|
@ -3770,6 +3815,18 @@
|
||||||
"integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
|
"integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/cssesc": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"cssesc": "bin/cssesc"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
|
@ -5558,7 +5615,6 @@
|
||||||
"version": "3.3.7",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
@ -5824,8 +5880,7 @@
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
|
@ -5939,7 +5994,6 @@
|
||||||
"version": "8.4.47",
|
"version": "8.4.47",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
|
||||||
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
|
@ -5964,6 +6018,46 @@
|
||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/postcss-nesting": {
|
||||||
|
"version": "13.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz",
|
||||||
|
"integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/csstools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/csstools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@csstools/selector-resolve-nested": "^3.0.0",
|
||||||
|
"@csstools/selector-specificity": "^5.0.0",
|
||||||
|
"postcss-selector-parser": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"postcss": "^8.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/postcss-selector-parser": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"cssesc": "^3.0.0",
|
||||||
|
"util-deprecate": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
|
@ -6673,7 +6767,6 @@
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
@ -7134,8 +7227,7 @@
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/utils-merge": {
|
"node_modules/utils-merge": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/codex-storage/codex-marketplace-ui-components"
|
"url": "https://github.com/codex-storage/codex-marketplace-ui-components"
|
||||||
},
|
},
|
||||||
"version": "0.0.27",
|
"version": "0.0.28",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepack": "npm run build",
|
"prepack": "npm run build",
|
||||||
|
@ -37,7 +37,8 @@
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@codex-storage/sdk-js": ">=0.0.12",
|
"@codex-storage/sdk-js": ">=0.0.12",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^18.3.1",
|
||||||
|
"postcss-nesting": "^13.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@chromatic-com/storybook": "^2.0.2",
|
"@chromatic-com/storybook": "^2.0.2",
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
import "./alert.css";
|
import "./alert.css";
|
||||||
import { CSSProperties, ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-color-primary"?: string;
|
|
||||||
"--codex-color-warning"?: string;
|
|
||||||
"--codex-font-family"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variant: "success" | "warning" | "toast";
|
variant: "success" | "warning" | "toast";
|
||||||
|
@ -20,21 +13,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-border-radius
|
|
||||||
* --codex-color-primary: string;
|
|
||||||
* --codex-color-warning
|
|
||||||
* --codex-font-family
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
Icon?: ReactNode;
|
Icon?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Alert({
|
export function Alert({
|
||||||
variant,
|
variant,
|
||||||
style,
|
|
||||||
title,
|
title,
|
||||||
Icon,
|
Icon,
|
||||||
children,
|
children,
|
||||||
|
@ -42,20 +25,16 @@ export function Alert({
|
||||||
...rest
|
...rest
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={`alert alert--${variant} ${className}`} {...rest}>
|
||||||
className={`alert alert--${variant} ${className}`}
|
|
||||||
style={style}
|
|
||||||
{...rest}
|
|
||||||
>
|
|
||||||
{Icon && (
|
{Icon && (
|
||||||
<span className="alert-circleIcon">
|
<span>
|
||||||
<span className="alert-icon">{Icon}</span>
|
<span>{Icon}</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="alert-body">
|
<div>
|
||||||
<b className="alert-title">{title}</b>
|
<b>{title}</b>
|
||||||
<div className="alert-message">{children}</div>
|
<div>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,34 +9,34 @@
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
|
||||||
|
|
||||||
.alert-icon {
|
b {
|
||||||
display: flex;
|
text-transform: capitalize;
|
||||||
width: 1rem;
|
margin-bottom: 0.25rem;
|
||||||
color: rgb(var(--codex-alert-color));
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-circleIcon {
|
span {
|
||||||
background: rgba(var(--codex-alert-color), 0.2);
|
background: rgba(var(--codex-alert-color), 0.2);
|
||||||
border-radius: 75px;
|
border-radius: 75px;
|
||||||
height: 1.75rem;
|
height: 1.75rem;
|
||||||
min-width: 1.75rem;
|
min-width: 1.75rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
|
||||||
|
|
||||||
.alert-title {
|
span {
|
||||||
text-transform: capitalize;
|
display: flex;
|
||||||
margin-bottom: 0.25rem;
|
width: 1rem;
|
||||||
display: inline-block;
|
color: rgb(var(--codex-alert-color));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.alert--success {
|
&.alert--success {
|
||||||
--codex-alert-color: var(--codex-color-success);
|
--codex-alert-color: var(--codex-color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert--warning {
|
&.alert--warning {
|
||||||
--codex-alert-color: var(--codex-color-warning);
|
--codex-alert-color: var(--codex-color-warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
backdrop-filter: blur(2px);
|
backdrop-filter: blur(2px);
|
||||||
display: block;
|
display: block;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
|
||||||
|
|
||||||
.backdrop[aria-expanded] {
|
&[aria-expanded] {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-noOverflow {
|
.document-noOverflow {
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
import { ComponentType, CSSProperties } from "react";
|
import { ComponentType } from "react";
|
||||||
import "./button.css";
|
import "./button.css";
|
||||||
import { attributes } from "../utils/attributes";
|
import { attributes } from "../utils/attributes";
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-color-primary"?: string;
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-border-color"?: string;
|
|
||||||
"--codex-font-family"?: string;
|
|
||||||
"--codex-color-on-primary"?: string;
|
|
||||||
"--codex-color-disabled"?: string;
|
|
||||||
"--codex-color-outline"?: string;
|
|
||||||
"--codex-button-loader"?: string;
|
|
||||||
"--codex-button-background-busy"?: string;
|
|
||||||
"--codex-button-color-box-shadow"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/**
|
/**
|
||||||
* Button style variant. Default is primary.
|
* Button style variant. Default is primary.
|
||||||
|
@ -50,21 +37,6 @@ type Props = {
|
||||||
* Apply custom classname.
|
* Apply custom classname.
|
||||||
*/
|
*/
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-color-primary
|
|
||||||
* --codex-border-radius
|
|
||||||
* --codex-border-color
|
|
||||||
* --codex-font-family
|
|
||||||
* --codex-color-on-primary: The colors when the button is primary
|
|
||||||
* --codex-color-disabled: The disabled background color
|
|
||||||
* --codex-color-outline: The color when the button is outline
|
|
||||||
* --codex-button-loader: The url svg image for the spinner
|
|
||||||
* --codex-button-background-busy: The background color image when the button is busy
|
|
||||||
* --codex-button-color-box-shadow: The shadow color on focus
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Button({
|
export function Button({
|
||||||
|
@ -75,7 +47,6 @@ export function Button({
|
||||||
onMouseLeave,
|
onMouseLeave,
|
||||||
fetching = false,
|
fetching = false,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
style,
|
|
||||||
variant = "primary",
|
variant = "primary",
|
||||||
onClick,
|
onClick,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
@ -84,7 +55,6 @@ export function Button({
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
style={style}
|
|
||||||
className={`button ${className} button--${variant}`}
|
className={`button ${className} button--${variant}`}
|
||||||
{...attributes({
|
{...attributes({
|
||||||
disabled: disabled || fetching,
|
disabled: disabled || fetching,
|
||||||
|
@ -93,11 +63,11 @@ export function Button({
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{Icon && (
|
{Icon && (
|
||||||
<div className="button-icon">
|
<div>
|
||||||
<Icon />
|
<Icon />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<span className="button-label">{label}</span>
|
<span>{label}</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,84 +14,84 @@
|
||||||
font-family: var(--codex-font-family);
|
font-family: var(--codex-font-family);
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
place-content: center;
|
place-content: center;
|
||||||
}
|
|
||||||
|
&[aria-busy] {
|
||||||
.button--primary {
|
cursor: wait;
|
||||||
background-color: var(--codex-color-primary);
|
}
|
||||||
color: var(--codex-color-on-primary);
|
|
||||||
}
|
&[aria-busy]::after {
|
||||||
|
content: " ";
|
||||||
.button:disabled {
|
display: block;
|
||||||
cursor: not-allowed;
|
background-image: var(
|
||||||
}
|
--codex-button-loader,
|
||||||
|
url('data:image/svg+xml,<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background: new 0 0 50 50" xml:space="preserve"><path fill="%23FFF" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animateTransform></path></svg>')
|
||||||
.button--primary:disabled {
|
);
|
||||||
background-color: var(--codex-color-disabled);
|
position: absolute;
|
||||||
}
|
background-color: var(
|
||||||
|
--codex-button-background-busy,
|
||||||
.button--outline:disabled {
|
var(--codex-background-backdrop)
|
||||||
color: var(--codex-color-disabled);
|
);
|
||||||
}
|
|
||||||
|
/**
|
||||||
.button-label {
|
* Set full size and add border.
|
||||||
display: flex;
|
*/
|
||||||
align-items: center;
|
width: calc(100% + 2px);
|
||||||
gap: 0.75rem;
|
height: calc(100% + 2px);
|
||||||
}
|
|
||||||
|
background-repeat: no-repeat;
|
||||||
.button--outline {
|
background-position: center;
|
||||||
color: var(--codex-color-outline, var(--codex-color-contrast));
|
background-size: 28px;
|
||||||
border-color: var(--codex-border-color);
|
left: -1px;
|
||||||
border-width: 1px;
|
right: 0;
|
||||||
border-style: solid;
|
border-radius: var(--codex-border-radius);
|
||||||
background-color: transparent;
|
}
|
||||||
}
|
|
||||||
|
&.button--primary:not(:disabled):hover {
|
||||||
.button[aria-busy] {
|
cursor: pointer;
|
||||||
cursor: wait;
|
box-shadow: 0 0 0 3px
|
||||||
}
|
var(--codex-button-color-box-shadow, var(--codex-color-primary-variant));
|
||||||
|
}
|
||||||
.button-icon {
|
|
||||||
width: 16px;
|
&.button--outline:not(:disabled):hover {
|
||||||
height: 16px;
|
cursor: pointer;
|
||||||
display: flex;
|
box-shadow: 0 0 0 2px var(--codex-border-color);
|
||||||
place-items: center;
|
}
|
||||||
}
|
|
||||||
|
&.button--primary {
|
||||||
.button[aria-busy]::after {
|
background-color: var(--codex-color-primary);
|
||||||
content: " ";
|
color: var(--codex-color-on-primary);
|
||||||
display: block;
|
}
|
||||||
background-image: var(
|
|
||||||
--codex-button-loader,
|
&:disabled {
|
||||||
url('data:image/svg+xml,<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background: new 0 0 50 50" xml:space="preserve"><path fill="%23FFF" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animateTransform></path></svg>')
|
cursor: not-allowed;
|
||||||
);
|
}
|
||||||
position: absolute;
|
|
||||||
background-color: var(
|
&.button--primary:disabled {
|
||||||
--codex-button-background-busy,
|
background-color: var(--codex-color-disabled);
|
||||||
var(--codex-background-backdrop)
|
}
|
||||||
);
|
|
||||||
|
&.button--outline:disabled {
|
||||||
/**
|
color: var(--codex-color-disabled);
|
||||||
* Set full size and add border.
|
}
|
||||||
*/
|
|
||||||
width: calc(100% + 2px);
|
&.button--outline {
|
||||||
height: calc(100% + 2px);
|
color: var(--codex-color-outline, var(--codex-color-contrast));
|
||||||
|
border-color: var(--codex-border-color);
|
||||||
background-repeat: no-repeat;
|
border-width: 1px;
|
||||||
background-position: center;
|
border-style: solid;
|
||||||
background-size: 28px;
|
background-color: transparent;
|
||||||
left: -1px;
|
}
|
||||||
right: 0;
|
|
||||||
border-radius: var(--codex-border-radius);
|
span {
|
||||||
}
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
.button--primary:not(:disabled):hover {
|
gap: 0.75rem;
|
||||||
cursor: pointer;
|
}
|
||||||
box-shadow: 0 0 0 3px
|
|
||||||
var(--codex-button-color-box-shadow, var(--codex-color-primary-variant));
|
div {
|
||||||
}
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
.button--outline:not(:disabled):hover {
|
display: flex;
|
||||||
cursor: pointer;
|
place-items: center;
|
||||||
box-shadow: 0 0 0 2px var(--codex-border-color);
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,7 @@
|
||||||
import {
|
import { AnimationEventHandler, ComponentType, useState } from "react";
|
||||||
AnimationEventHandler,
|
|
||||||
ComponentType,
|
|
||||||
CSSProperties,
|
|
||||||
useState,
|
|
||||||
} from "react";
|
|
||||||
import "./buttonIcon.css";
|
import "./buttonIcon.css";
|
||||||
import { attributes } from "../utils/attributes";
|
import { attributes } from "../utils/attributes";
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-button-icon-background"?: string;
|
|
||||||
"--codex-border-color"?: string;
|
|
||||||
"--codex-color-disabled"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
Icon: ComponentType<{
|
Icon: ComponentType<{
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -29,14 +18,6 @@ type Props = {
|
||||||
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-button-icon-background
|
|
||||||
* --codex-border-color
|
|
||||||
* --codex-color-disabled
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply custom classname.
|
* Apply custom classname.
|
||||||
*/
|
*/
|
||||||
|
@ -51,7 +32,6 @@ type Props = {
|
||||||
export function ButtonIcon({
|
export function ButtonIcon({
|
||||||
Icon,
|
Icon,
|
||||||
onClick,
|
onClick,
|
||||||
style,
|
|
||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
onMouseLeave,
|
onMouseLeave,
|
||||||
className = "",
|
className = "",
|
||||||
|
@ -74,7 +54,6 @@ export function ButtonIcon({
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
onClick={onInternalClick}
|
onClick={onInternalClick}
|
||||||
style={style}
|
|
||||||
{...attributes({ disabled: disabled, "aria-disabled": disabled })}
|
{...attributes({ disabled: disabled, "aria-disabled": disabled })}
|
||||||
>
|
>
|
||||||
<Icon className={animationClassName} onAnimationEnd={onAnimationEnd} />
|
<Icon className={animationClassName} onAnimationEnd={onAnimationEnd} />
|
||||||
|
|
|
@ -10,41 +10,52 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: box-shadow 0.35s;
|
transition: box-shadow 0.35s;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
|
||||||
|
|
||||||
.buttonIcon--big {
|
&.buttonIcon--big {
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonIcon--small {
|
&.buttonIcon--small {
|
||||||
width: 2rem;
|
width: 2rem;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonIcon svg {
|
&:not(:disabled):hover {
|
||||||
mix-blend-mode: difference;
|
cursor: pointer;
|
||||||
}
|
box-shadow: 0 0 0 2px var(--codex-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
.buttonIcon:not(:disabled):hover {
|
&:disabled {
|
||||||
cursor: pointer;
|
color: var(--codex-color-disabled);
|
||||||
box-shadow: 0 0 0 2px var(--codex-border-color);
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonIcon:disabled {
|
&.buttonIcon--buzz {
|
||||||
color: var(--codex-color-disabled);
|
-webkit-animation-name: buzz;
|
||||||
cursor: not-allowed;
|
animation-name: buzz;
|
||||||
}
|
-webkit-animation-duration: 0.45s;
|
||||||
|
animation-duration: 0.45s;
|
||||||
|
-webkit-animation-timing-function: linear;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
-webkit-animation-iteration-count: 5;
|
||||||
|
animation-iteration-count: 5;
|
||||||
|
}
|
||||||
|
|
||||||
.buttonIcon--buzz {
|
&.buttonIcon--bounce {
|
||||||
-webkit-animation-name: buzz;
|
-webkit-animation-name: bounce;
|
||||||
animation-name: buzz;
|
animation-name: bounce;
|
||||||
-webkit-animation-duration: 0.45s;
|
-webkit-animation-duration: 0.6s;
|
||||||
animation-duration: 0.45s;
|
animation-duration: 0.6s;
|
||||||
-webkit-animation-timing-function: linear;
|
-webkit-animation-timing-function: linear;
|
||||||
animation-timing-function: linear;
|
animation-timing-function: linear;
|
||||||
-webkit-animation-iteration-count: 5;
|
-webkit-animation-iteration-count: 1;
|
||||||
animation-iteration-count: 5;
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes buzz {
|
@keyframes buzz {
|
||||||
|
@ -74,17 +85,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonIcon--bounce {
|
|
||||||
-webkit-animation-name: bounce;
|
|
||||||
animation-name: bounce;
|
|
||||||
-webkit-animation-duration: 0.6s;
|
|
||||||
animation-duration: 0.6s;
|
|
||||||
-webkit-animation-timing-function: linear;
|
|
||||||
animation-timing-function: linear;
|
|
||||||
-webkit-animation-iteration-count: 1;
|
|
||||||
animation-iteration-count: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bounce {
|
@keyframes bounce {
|
||||||
0% {
|
0% {
|
||||||
-webkit-transform: translateY(0) scale(1);
|
-webkit-transform: translateY(0) scale(1);
|
||||||
|
|
|
@ -1,33 +1,19 @@
|
||||||
import { CSSProperties, ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import "./card.css";
|
import "./card.css";
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-border-color"?: string;
|
|
||||||
"--codex-font-family"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-border-radius
|
|
||||||
* --codex-border-color
|
|
||||||
* --codex-font-family
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Card({ children, style, className = "", title }: Props) {
|
export function Card({ children, className = "", title }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={`card ${className}`} style={style}>
|
<div className={`card ${className}`}>
|
||||||
<div className="card-header">{title}</div>
|
<header>{title}</header>
|
||||||
<div className="card-body">{children}</div>
|
<div>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
border: 1px solid var(--codex-border-color);
|
border: 1px solid var(--codex-border-color);
|
||||||
font-family: var(--codex-font-family);
|
font-family: var(--codex-font-family);
|
||||||
background-color: var(--codex-background-secondary);
|
background-color: var(--codex-background-secondary);
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
header {
|
||||||
border-bottom: 1px solid var(--codex-border-color);
|
border-bottom: 1px solid var(--codex-border-color);
|
||||||
padding: 1rem 1.5rem;
|
padding: 1rem 1.5rem;
|
||||||
font-size: 1.15rem;
|
font-size: 1.15rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-body {
|
div {
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,9 @@ import {
|
||||||
import "./dropdown.css";
|
import "./dropdown.css";
|
||||||
import { attributes } from "../utils/attributes";
|
import { attributes } from "../utils/attributes";
|
||||||
import { Backdrop } from "../Backdrop/Backdrop";
|
import { Backdrop } from "../Backdrop/Backdrop";
|
||||||
import { Input, InputCustomStyleCSS } from "../Input/Input";
|
import { Input } from "../Input/Input";
|
||||||
import { classnames } from "../utils/classnames";
|
import { classnames } from "../utils/classnames";
|
||||||
|
|
||||||
interface CustomStyleCSS extends InputCustomStyleCSS {
|
|
||||||
"--codex-dropdown-panel-background"?: string;
|
|
||||||
"--codex-dropdown-border"?: string;
|
|
||||||
"--codex-dropdown-option-background-hover"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DropdownOption = {
|
export type DropdownOption = {
|
||||||
/**
|
/**
|
||||||
* Dropdown option icon displayed on the left
|
* Dropdown option icon displayed on the left
|
||||||
|
@ -70,14 +64,6 @@ type Props = {
|
||||||
|
|
||||||
onMouseLeave?: () => void;
|
onMouseLeave?: () => void;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-dropdown-panel-background
|
|
||||||
* --codex-dropdown-border
|
|
||||||
* --codex-dropdown-option-background-hover
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
label: string;
|
label: string;
|
||||||
|
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -85,7 +71,6 @@ type Props = {
|
||||||
|
|
||||||
export function Dropdown({
|
export function Dropdown({
|
||||||
placeholder,
|
placeholder,
|
||||||
style,
|
|
||||||
options,
|
options,
|
||||||
label,
|
label,
|
||||||
id,
|
id,
|
||||||
|
@ -134,12 +119,10 @@ export function Dropdown({
|
||||||
const attr = attributes({ "aria-expanded": focused });
|
const attr = attributes({ "aria-expanded": focused });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={"dropdown " + className}>
|
||||||
<label className="dropdown-label" htmlFor={id}>
|
<label htmlFor={id}>{label}</label>
|
||||||
{label}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className={`dropdown ${className}`} style={style}>
|
<div>
|
||||||
<Backdrop onClose={onClose} open={focused} />
|
<Backdrop onClose={onClose} open={focused} />
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
@ -157,28 +140,20 @@ export function Dropdown({
|
||||||
id={id}
|
id={id}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="dropdown-panel" {...attr}>
|
<ul className="dropdown-panel" {...attr}>
|
||||||
{filtered.length ? (
|
{filtered.length ? (
|
||||||
filtered.map((o) => (
|
filtered.map((o) => (
|
||||||
<div
|
<li onClick={() => onSelect(o)} key={o.title}>
|
||||||
className="dropdown-option"
|
|
||||||
onClick={() => onSelect(o)}
|
|
||||||
key={o.title}
|
|
||||||
>
|
|
||||||
{o.Icon && <o.Icon />}
|
{o.Icon && <o.Icon />}
|
||||||
<div>
|
<span>{o.title}</span>
|
||||||
<span className="dropdown-title">{o.title}</span>
|
{o.subtitle && <span>{o.subtitle}</span>}
|
||||||
{o.subtitle && (
|
</li>
|
||||||
<span className="dropdown-subtitle">{o.subtitle}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<p className="dropdown-noResults">No results found</p>
|
<p>No results found</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +1,83 @@
|
||||||
.dropdown {
|
.dropdown {
|
||||||
position: relative;
|
label {
|
||||||
}
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
display: block;
|
||||||
|
color: var(--codex-color);
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-panel {
|
> div {
|
||||||
position: absolute;
|
position: relative;
|
||||||
padding: 0.5rem;
|
}
|
||||||
background-color: var(
|
|
||||||
--codex-dropdown-panel-background,
|
|
||||||
var(--codex-background-secondary)
|
|
||||||
);
|
|
||||||
border: var(--codex-dropdown-border, 1px solid var(--codex-border-color));
|
|
||||||
border-radius: var(--codex-border-radius);
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-3rem);
|
|
||||||
transition:
|
|
||||||
transform 0.35s,
|
|
||||||
opacity 0.15s,
|
|
||||||
z-index 0.35s;
|
|
||||||
max-height: 20rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-label {
|
ul {
|
||||||
margin-bottom: 0.5rem;
|
position: absolute;
|
||||||
font-weight: 500;
|
padding: 0.5rem;
|
||||||
display: block;
|
background-color: var(
|
||||||
color: var(--codex-color);
|
--codex-dropdown-panel-background,
|
||||||
}
|
var(--codex-background-secondary)
|
||||||
|
);
|
||||||
|
border: var(--codex-dropdown-border, 1px solid var(--codex-border-color));
|
||||||
|
border-radius: var(--codex-border-radius);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-3rem);
|
||||||
|
transition:
|
||||||
|
transform 0.35s,
|
||||||
|
opacity 0.15s,
|
||||||
|
z-index 0.35s;
|
||||||
|
max-height: 20rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: -1;
|
||||||
|
|
||||||
.dropdown-panel[aria-expanded] {
|
&[aria-expanded] {
|
||||||
transform: translateY(0.5rem);
|
transform: translateY(0rem);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-input {
|
li {
|
||||||
position: relative;
|
padding: 0.5rem;
|
||||||
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 4.06066C8.15829 3.8654 7.84171 3.8654 7.64645 4.06066L5.35355 6.35355C5.15829 6.54882 4.84171 6.54882 4.64645 6.35355C4.45118 6.15829 4.45118 5.84171 4.64645 5.64645L6.93934 3.35356C7.52513 2.76777 8.47487 2.76777 9.06066 3.35355L11.3536 5.64645C11.5488 5.84171 11.5488 6.15829 11.3536 6.35355C11.1583 6.54882 10.8417 6.54882 10.6464 6.35355L8.35355 4.06066Z' fill='%236b7280'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 11.9393C8.15829 12.1346 7.84171 12.1346 7.64645 11.9393L5.35355 9.64645C5.15829 9.45119 4.84171 9.45119 4.64645 9.64645C4.45118 9.84171 4.45118 10.1583 4.64645 10.3536L6.93934 12.6464C7.52513 13.2322 8.47487 13.2322 9.06066 12.6464L11.3536 10.3536C11.5488 10.1583 11.5488 9.84171 11.3536 9.64645C11.1583 9.45119 10.8417 9.45119 10.6464 9.64645L8.35355 11.9393Z' fill='%236b7280'/%3E%3C/svg%3E%0A");
|
border-radius: var(--codex-border-radius);
|
||||||
background-position: right 0.5rem center;
|
transition: background-color 0.35s;
|
||||||
background-repeat: no-repeat;
|
cursor: pointer;
|
||||||
background-size: 1.25em 1.25em;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
|
||||||
.dropdown-input:focus {
|
&:hover {
|
||||||
z-index: 11;
|
background-color: var(
|
||||||
}
|
--codex-dropdown-option-background-hover,
|
||||||
|
var(--codex-background-light)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-option {
|
span {
|
||||||
padding: 0.5rem;
|
display: block;
|
||||||
border-radius: var(--codex-border-radius);
|
word-break: break-all;
|
||||||
transition: background-color 0.35s;
|
}
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-option:hover {
|
span + span {
|
||||||
background-color: var(
|
mix-blend-mode: difference;
|
||||||
--codex-dropdown-option-background-hover,
|
font-size: 0.75rem;
|
||||||
var(--codex-background-light)
|
}
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-noResults {
|
.input {
|
||||||
padding: 0.75rem 0.25rem;
|
position: relative;
|
||||||
}
|
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 4.06066C8.15829 3.8654 7.84171 3.8654 7.64645 4.06066L5.35355 6.35355C5.15829 6.54882 4.84171 6.54882 4.64645 6.35355C4.45118 6.15829 4.45118 5.84171 4.64645 5.64645L6.93934 3.35356C7.52513 2.76777 8.47487 2.76777 9.06066 3.35355L11.3536 5.64645C11.5488 5.84171 11.5488 6.15829 11.3536 6.35355C11.1583 6.54882 10.8417 6.54882 10.6464 6.35355L8.35355 4.06066Z' fill='%236b7280'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 11.9393C8.15829 12.1346 7.84171 12.1346 7.64645 11.9393L5.35355 9.64645C5.15829 9.45119 4.84171 9.45119 4.64645 9.64645C4.45118 9.84171 4.45118 10.1583 4.64645 10.3536L6.93934 12.6464C7.52513 13.2322 8.47487 13.2322 9.06066 12.6464L11.3536 10.3536C11.5488 10.1583 11.5488 9.84171 11.3536 9.64645C11.1583 9.45119 10.8417 9.45119 10.6464 9.64645L8.35355 11.9393Z' fill='%236b7280'/%3E%3C/svg%3E%0A");
|
||||||
|
background-position: right 0.5rem center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 1.25em 1.25em;
|
||||||
|
|
||||||
.dropdown-title {
|
&:focus {
|
||||||
display: block;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-subtitle {
|
p {
|
||||||
mix-blend-mode: difference;
|
padding: 0.75rem 0.25rem;
|
||||||
font-size: 0.75rem;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-title,
|
|
||||||
.dropdown-subtitle {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
import "./failure.css";
|
import "./failure.css";
|
||||||
import { Button } from "../Button/Button";
|
import { Button } from "../Button/Button";
|
||||||
import { CSSProperties } from "react";
|
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-code-font-size"?: string;
|
|
||||||
"--codex-text-contrast"?: string;
|
|
||||||
"--codex-font-family"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/**
|
/**
|
||||||
|
@ -29,14 +22,6 @@ type Props = {
|
||||||
* The button label
|
* The button label
|
||||||
*/
|
*/
|
||||||
button?: string;
|
button?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-code-font-size
|
|
||||||
* --codex-text-contrast
|
|
||||||
* --codex-font-family
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Failure({
|
export function Failure({
|
||||||
|
@ -48,9 +33,9 @@ export function Failure({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="failure">
|
<div className="failure">
|
||||||
<h1 className="failure-code">{code}</h1>
|
<h1>{code}</h1>
|
||||||
<h2 className="failure-title">{title}</h2>
|
<h2>{title}</h2>
|
||||||
<div className="failure-message">{message}</div>
|
<div>{message}</div>
|
||||||
{onClick && <Button label={button} onClick={onClick} />}
|
{onClick && <Button label={button} onClick={onClick} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
.failure-code {
|
|
||||||
font-size: var(--codex-code-font-size, 6rem);
|
|
||||||
line-height: 1;
|
|
||||||
color: var(--codex-text-contrast);
|
|
||||||
font-family: var(--codex-font-family);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.failure {
|
.failure {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.failure-title {
|
h1 {
|
||||||
font-size: 1.875rem;
|
font-size: var(--codex-code-font-size, 6rem);
|
||||||
line-height: 2.25rem;
|
line-height: 1;
|
||||||
font-weight: 600;
|
color: var(--codex-text-contrast);
|
||||||
margin: 0.75rem 0;
|
font-family: var(--codex-font-family);
|
||||||
color: var(--codex-text-contrast);
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.failure-message {
|
h2 {
|
||||||
margin-bottom: 0.75rem;
|
font-size: 1.875rem;
|
||||||
mix-blend-mode: difference;
|
line-height: 2.25rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
color: var(--codex-text-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {
|
import {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
ComponentType,
|
ComponentType,
|
||||||
CSSProperties,
|
|
||||||
forwardRef,
|
forwardRef,
|
||||||
InputHTMLAttributes,
|
InputHTMLAttributes,
|
||||||
useState,
|
useState,
|
||||||
|
@ -9,16 +8,6 @@ import {
|
||||||
import { attributes } from "../utils/attributes";
|
import { attributes } from "../utils/attributes";
|
||||||
import { classnames } from "../utils/classnames";
|
import { classnames } from "../utils/classnames";
|
||||||
import "./input.css";
|
import "./input.css";
|
||||||
import { SimpleText } from "../SimpleText/SimpleText";
|
|
||||||
|
|
||||||
export interface InputCustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-input-background"?: string;
|
|
||||||
"--codex-color"?: string;
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-input-border"?: string;
|
|
||||||
"--codex-color-primary"?: string;
|
|
||||||
"--codex-input-background-disabled"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -80,54 +69,39 @@ export const Input = forwardRef<HTMLInputElement, Props>(
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
{label && (
|
className={classnames(
|
||||||
<label className="input-label" htmlFor={id}>
|
["input"],
|
||||||
{label}
|
["input--invalid", invalid || isInvalid],
|
||||||
</label>
|
["input--icon", !!Icon],
|
||||||
|
[inputClassName || ""]
|
||||||
)}
|
)}
|
||||||
|
>
|
||||||
|
{label && <label htmlFor={id}>{label}</label>}
|
||||||
|
|
||||||
<div
|
<div className={classnames([inputContainerClassName])}>
|
||||||
className={classnames(
|
|
||||||
["input-icon", !!Icon],
|
|
||||||
[inputContainerClassName]
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{Icon && (
|
{Icon && (
|
||||||
<div className="input-iconElement">
|
<div>
|
||||||
<Icon />
|
<Icon />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
id={id}
|
id={id}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={classnames(
|
className={classnames([inputClassName || ""])}
|
||||||
["input"],
|
|
||||||
["input--invalid", invalid || isInvalid],
|
|
||||||
["input-icon-input", !!Icon],
|
|
||||||
[inputClassName || ""]
|
|
||||||
)}
|
|
||||||
onChange={onInternalChange}
|
onChange={onInternalChange}
|
||||||
style={style}
|
style={style}
|
||||||
{...attributes({
|
{...attributes({
|
||||||
disabled,
|
disabled,
|
||||||
"aria-disabled": disabled,
|
"aria-disabled": disabled,
|
||||||
|
"aria-invalid": invalid || isInvalid,
|
||||||
})}
|
})}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{helper && (
|
{helper && <small>{helper}</small>}
|
||||||
<div>
|
</div>
|
||||||
<SimpleText
|
|
||||||
className="input-helper-text"
|
|
||||||
variant={invalid || isInvalid ? "error" : "light"}
|
|
||||||
>
|
|
||||||
{helper}
|
|
||||||
</SimpleText>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,105 +1,71 @@
|
||||||
.input {
|
.input {
|
||||||
background-color: var(--codex-input-background);
|
input {
|
||||||
color: white;
|
background-color: var(--codex-input-background);
|
||||||
border-radius: var(--codex-border-radius);
|
color: white;
|
||||||
border: 1px solid var(--codex-input-border-color);
|
border-radius: var(--codex-border-radius);
|
||||||
padding: 16px;
|
border: 1px solid var(--codex-input-border-color);
|
||||||
outline: none;
|
padding: 16px;
|
||||||
display: inline-block;
|
outline: none;
|
||||||
box-sizing: border-box;
|
display: inline-block;
|
||||||
font-weight: 500;
|
box-sizing: border-box;
|
||||||
font-size: 20px;
|
font-weight: 500;
|
||||||
height: 64px;
|
font-size: 20px;
|
||||||
}
|
height: 64px;
|
||||||
|
position: relative;
|
||||||
.input--invalid {
|
|
||||||
color: var(--codex-input-color-error);
|
|
||||||
border-color: var(--codex-input-color-error);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
display: block;
|
|
||||||
font-family: var(--codex-input-font-family, var(--codex-font-family));
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 20px;
|
|
||||||
letter-spacing: -0.006em;
|
|
||||||
text-align: left;
|
|
||||||
color: var(--codex-input-label-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input:not(.input[disabled]):active,
|
|
||||||
.input:not(.input[disabled]):focus {
|
|
||||||
box-shadow: 0 0 0 1px var(--codex-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-icon {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-iconElement {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0 0.75rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-icon-input {
|
|
||||||
padding-left: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input[disabled] {
|
|
||||||
background-color: var(--codex-input-background-disabled);
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-floating {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-spacing {
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-floating-label {
|
|
||||||
position: absolute;
|
|
||||||
font-weight: 600;
|
|
||||||
color: white;
|
|
||||||
left: 1rem;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
transition:
|
|
||||||
top 0.15s,
|
|
||||||
font-size 0.15s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-floating-input {
|
|
||||||
padding-top: 1.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input.input-floating-input:not(:placeholder-shown) ~ .input-floating-label,
|
|
||||||
.input.input-floating-input:focus ~ .input-floating-label {
|
|
||||||
top: -25px;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
mix-blend-mode: difference;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-helper-text {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* @media (min-width: 801px) {
|
|
||||||
.input {
|
|
||||||
min-width: 20rem;
|
|
||||||
}
|
}
|
||||||
} */
|
|
||||||
|
&.input--invalid input {
|
||||||
|
color: var(--codex-input-color-error);
|
||||||
|
border-color: var(--codex-input-color-error);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
display: block;
|
||||||
|
font-family: var(--codex-input-font-family, var(--codex-font-family));
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: -0.006em;
|
||||||
|
text-align: left;
|
||||||
|
color: var(--codex-input-label-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
& input:not(.input[disabled]):active,
|
||||||
|
& input:not(.input[disabled]):focus {
|
||||||
|
box-shadow: 0 0 0 1px var(--codex-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
& input[disabled] {
|
||||||
|
background-color: var(--codex-input-background-disabled);
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.input--icon input {
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--codex-input-label-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.input--invalid small {
|
||||||
|
color: var(--codex-color-error-hexa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
import { ChangeEvent, CSSProperties, LegacyRef, ReactNode } from "react";
|
import { ChangeEvent, LegacyRef, ReactNode } from "react";
|
||||||
import "./inputGroup.css";
|
import "./inputGroup.css";
|
||||||
import { Input } from "../Input/Input";
|
import { Input } from "../Input/Input";
|
||||||
import { Select } from "../Select/Select";
|
import { Select } from "../Select/Select";
|
||||||
|
|
||||||
export interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-border-color"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string;
|
label: string;
|
||||||
|
|
||||||
|
@ -63,13 +58,6 @@ type Props = {
|
||||||
|
|
||||||
step?: string;
|
step?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-border-radius
|
|
||||||
* --codex-border-color
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,7 +79,6 @@ export function InputGroup({
|
||||||
name,
|
name,
|
||||||
helper,
|
helper,
|
||||||
type = "text",
|
type = "text",
|
||||||
style,
|
|
||||||
group,
|
group,
|
||||||
className = "",
|
className = "",
|
||||||
inputClassName = "",
|
inputClassName = "",
|
||||||
|
@ -111,17 +98,17 @@ export function InputGroup({
|
||||||
extra,
|
extra,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={`inputGroup ${className}`} style={style}>
|
<div className={`inputGroup input-group ${className}`}>
|
||||||
<div className="inputGroup-container">
|
<div>
|
||||||
<div className="inputGroup-element">
|
<div>
|
||||||
<div className="inputGroup-inputContainer">
|
<div>
|
||||||
<Input
|
<Input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
id={id}
|
id={id}
|
||||||
name={name}
|
name={name}
|
||||||
label={label}
|
label={label}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
inputClassName={"inputGroup-input " + inputClassName}
|
inputClassName={inputClassName}
|
||||||
type={type}
|
type={type}
|
||||||
value={value}
|
value={value}
|
||||||
step={step}
|
step={step}
|
||||||
|
@ -149,12 +136,10 @@ export function InputGroup({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="inputGroup-helpers">
|
<p>
|
||||||
<span>
|
<span>{helper && <small>{helper}</small>}</span>
|
||||||
{helper && <small className="inputGroup-helper">{helper}</small>}
|
|
||||||
</span>
|
|
||||||
{extra}
|
{extra}
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,45 +1,48 @@
|
||||||
.inputGroup-element {
|
.input-group {
|
||||||
display: flex;
|
> div {
|
||||||
align-items: flex-end;
|
flex-grow: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.inputGroup-container {
|
> div {
|
||||||
flex-grow: 1;
|
display: flex;
|
||||||
}
|
align-items: flex-end;
|
||||||
|
|
||||||
.inputGroup-helper {
|
> div:first-child {
|
||||||
height: 15px;
|
flex: 1;
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.inputGroup-input {
|
input {
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
select.inputGroup-select {
|
select {
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
min-width: 110px;
|
min-width: 110px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.inputGroup-unit {
|
> div:nth-child(2) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1px solid var(--codex-border-color);
|
border: 1px solid var(--codex-border-color);
|
||||||
border-top-right-radius: var(--codex-border-radius);
|
border-top-right-radius: var(--codex-border-radius);
|
||||||
border-bottom-right-radius: var(--codex-border-radius);
|
border-bottom-right-radius: var(--codex-border-radius);
|
||||||
background-color: var(--codex-border-color);
|
background-color: var(--codex-border-color);
|
||||||
padding: calc(0.5rem + 0.5px);
|
padding: calc(0.5rem + 0.5px);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.inputGroup-inputContainer {
|
p {
|
||||||
flex: 1;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 0;
|
||||||
|
|
||||||
.inputGroup-helpers {
|
small {
|
||||||
display: flex;
|
height: 15px;
|
||||||
justify-content: space-between;
|
display: inline-block;
|
||||||
align-items: center;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ type Props = {
|
||||||
disableActionButton?: boolean;
|
disableActionButton?: boolean;
|
||||||
|
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
||||||
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Modal({
|
export function Modal({
|
||||||
|
@ -60,6 +62,7 @@ export function Modal({
|
||||||
onClose,
|
onClose,
|
||||||
disableActionButton,
|
disableActionButton,
|
||||||
disableCloseButton,
|
disableCloseButton,
|
||||||
|
className = "",
|
||||||
displayCloseButton = true,
|
displayCloseButton = true,
|
||||||
displayActionButton = false,
|
displayActionButton = false,
|
||||||
labelActionButton = "Action",
|
labelActionButton = "Action",
|
||||||
|
@ -79,24 +82,21 @@ export function Modal({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
|
className={classnames(
|
||||||
|
["modal"],
|
||||||
|
["modal--internalOpen", internalOpen],
|
||||||
|
["modal--open", open],
|
||||||
|
["modal--actions", !!onAction],
|
||||||
|
[className]
|
||||||
|
)}
|
||||||
|
>
|
||||||
<Backdrop open={internalOpen} onClose={internalClose} />
|
<Backdrop open={internalOpen} onClose={internalClose} />
|
||||||
|
|
||||||
<div
|
<dialog>
|
||||||
className={classnames(
|
<main>{open && children}</main>
|
||||||
["modal"],
|
|
||||||
["modal--internalOpen", internalOpen],
|
|
||||||
["modal--open", open]
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="modal-body">{open && children}</div>
|
|
||||||
|
|
||||||
<div
|
<footer>
|
||||||
className={classnames(
|
|
||||||
["modal-buttons--between", !!onAction],
|
|
||||||
["modal-buttons--center", !onAction]
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{displayCloseButton && (
|
{displayCloseButton && (
|
||||||
<Button
|
<Button
|
||||||
label={labelCloseButton}
|
label={labelCloseButton}
|
||||||
|
@ -113,8 +113,8 @@ export function Modal({
|
||||||
disabled={disableActionButton}
|
disabled={disableActionButton}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</footer>
|
||||||
</div>
|
</dialog>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +1,55 @@
|
||||||
.modal {
|
.modal {
|
||||||
transition:
|
dialog {
|
||||||
transform 0.25s,
|
transition:
|
||||||
opacity 0.25s;
|
transform 0.25s,
|
||||||
max-width: 800px;
|
opacity 0.25s;
|
||||||
overflow-y: auto;
|
max-width: 800px;
|
||||||
overflow-x: hidden;
|
overflow-y: auto;
|
||||||
opacity: 0;
|
overflow-x: hidden;
|
||||||
z-index: -1;
|
opacity: 0;
|
||||||
max-height: 100%;
|
z-index: -1;
|
||||||
left: 50%;
|
max-height: 100%;
|
||||||
top: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
top: 50%;
|
||||||
position: fixed;
|
transform: translateX(-50%);
|
||||||
display: flex;
|
position: fixed;
|
||||||
flex-direction: column;
|
display: flex;
|
||||||
background-color: var(--codex-background);
|
flex-direction: column;
|
||||||
padding: 1.5rem;
|
background-color: var(--codex-background);
|
||||||
border-radius: var(--codex-border-radius);
|
padding: 1.5rem;
|
||||||
}
|
border-radius: var(--codex-border-radius);
|
||||||
|
border: none;
|
||||||
.modal--internalOpen {
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal--open {
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-buttons--center {
|
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-buttons--between {
|
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-title {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 801px) {
|
|
||||||
.modal {
|
|
||||||
min-width: 500px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
|
||||||
.modal {
|
|
||||||
width: calc(100% - 6rem);
|
width: calc(100% - 6rem);
|
||||||
|
|
||||||
|
@media (min-width: 801px) {
|
||||||
|
& {
|
||||||
|
min-width: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.modal--internalOpen dialog {
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.modal--open dialog {
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin-top: 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.modal--actions footer {
|
||||||
|
margin-top: 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { classnames } from "../utils/classnames";
|
|
||||||
import "./networkIndicator.css";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
online: boolean;
|
|
||||||
|
|
||||||
text: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function NetworkIndicator({ online, text }: Props) {
|
|
||||||
return (
|
|
||||||
<div className="networkIndicator">
|
|
||||||
<div
|
|
||||||
className={classnames(
|
|
||||||
["networkIndicator-point"],
|
|
||||||
["networkIndicator-point--online", online],
|
|
||||||
["networkIndicator-point--offline", !online]
|
|
||||||
)}
|
|
||||||
></div>
|
|
||||||
<span>{text}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
.networkIndicator {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.networkIndicator-point {
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation-duration: 3s;
|
|
||||||
animation-name: flash;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.networkIndicator-point--online {
|
|
||||||
background-color: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.networkIndicator-point--offline {
|
|
||||||
background-color: rgb(217, 53, 38);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes flash {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
40% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { Button } from "../Button/Button";
|
import { Button } from "../Button/Button";
|
||||||
import "./placeholder.css";
|
import "./placeholder.css";
|
||||||
import { SimpleText } from "../SimpleText/SimpleText";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -35,14 +34,10 @@ export function Placeholder({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={"placeholder " + className}>
|
<div className={"placeholder " + className}>
|
||||||
<div className="placeholder-icon">{Icon}</div>
|
<div>{Icon}</div>
|
||||||
<b className="placeholder-title">{title}</b>
|
<b>{title}</b>
|
||||||
|
|
||||||
{subtitle && (
|
{subtitle && <p>subtitle</p>}
|
||||||
<div className="placeholder-subtitle">
|
|
||||||
<SimpleText variant="light">{subtitle}</SimpleText>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="placeholder-message">{message} </div>
|
<div className="placeholder-message">{message} </div>
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,25 @@
|
||||||
.placeholder {
|
.placeholder {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder-icon {
|
> div:first-child {
|
||||||
display: block;
|
display: block;
|
||||||
margin: auto auto 0.75rem;
|
margin: auto auto 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-title {
|
b {
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-subtitle {
|
p {
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
color: var(--codex-input-label-color);
|
||||||
|
}
|
||||||
|
|
||||||
.placeholder-button {
|
.button {
|
||||||
margin: 0.75rem auto 0;
|
margin: 0.75rem auto 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
import { ChangeEvent, CSSProperties } from "react";
|
import { ChangeEvent } from "react";
|
||||||
import "./select.css";
|
import "./select.css";
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-select-background"?: string;
|
|
||||||
"--codex-color"?: string;
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-select-border"?: string;
|
|
||||||
"--codex-select-icon-url"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string;
|
label: string;
|
||||||
|
|
||||||
|
@ -33,11 +25,6 @@ type Props = {
|
||||||
|
|
||||||
onMouseLeave?: () => void;
|
onMouseLeave?: () => void;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
|
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -54,36 +41,29 @@ export function Select({
|
||||||
onFocus,
|
onFocus,
|
||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
onMouseLeave,
|
onMouseLeave,
|
||||||
style,
|
|
||||||
className = "",
|
className = "",
|
||||||
defaultValue,
|
defaultValue,
|
||||||
value,
|
value,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={"select " + className}>
|
||||||
<label htmlFor={id} className="select-label">
|
<label htmlFor={id}>{label}</label>
|
||||||
{label}
|
<select
|
||||||
</label>
|
id={id}
|
||||||
<div>
|
onChange={onChange}
|
||||||
<select
|
onBlur={onBlur}
|
||||||
id={id}
|
onFocus={onFocus}
|
||||||
className={`select ${className}`}
|
onMouseEnter={onMouseEnter}
|
||||||
onChange={onChange}
|
onMouseLeave={onMouseLeave}
|
||||||
onBlur={onBlur}
|
defaultValue={defaultValue}
|
||||||
onFocus={onFocus}
|
value={value}
|
||||||
onMouseEnter={onMouseEnter}
|
>
|
||||||
onMouseLeave={onMouseLeave}
|
{options.map(([oval, text]) => (
|
||||||
style={style}
|
<option key={oval} value={oval}>
|
||||||
defaultValue={defaultValue}
|
{text}
|
||||||
value={value}
|
</option>
|
||||||
>
|
))}
|
||||||
{options.map(([oval, text]) => (
|
</select>
|
||||||
<option key={oval} value={oval}>
|
</div>
|
||||||
{text}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,46 @@
|
||||||
.select {
|
.select {
|
||||||
appearance: none;
|
select {
|
||||||
-moz-appearance: none;
|
appearance: none;
|
||||||
-webkit-appearance: none;
|
-moz-appearance: none;
|
||||||
background-color: var(
|
-webkit-appearance: none;
|
||||||
--codex-select-background,
|
background-color: var(
|
||||||
var(--codex-background-secondary)
|
--codex-select-background,
|
||||||
);
|
var(--codex-background-secondary)
|
||||||
outline: 2px solid transparent;
|
);
|
||||||
outline-offset: 2px;
|
outline: 2px solid transparent;
|
||||||
color: var(--codex-color);
|
outline-offset: 2px;
|
||||||
border-radius: var(--codex-border-radius);
|
color: var(--codex-color);
|
||||||
padding: 0.75rem 1rem;
|
border-radius: var(--codex-border-radius);
|
||||||
padding-inline-end: 2.25rem;
|
padding: 0.75rem 1rem;
|
||||||
transition: box-shadow 0.35s;
|
padding-inline-end: 2.25rem;
|
||||||
border: var(--codex-select-border, 1px solid var(--codex-border-color));
|
transition: box-shadow 0.35s;
|
||||||
background-image: var(
|
border: var(--codex-select-border, 1px solid var(--codex-border-color));
|
||||||
--codex-select-icon-url,
|
background-image: var(
|
||||||
url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 4.06066C8.15829 3.8654 7.84171 3.8654 7.64645 4.06066L5.35355 6.35355C5.15829 6.54882 4.84171 6.54882 4.64645 6.35355C4.45118 6.15829 4.45118 5.84171 4.64645 5.64645L6.93934 3.35356C7.52513 2.76777 8.47487 2.76777 9.06066 3.35355L11.3536 5.64645C11.5488 5.84171 11.5488 6.15829 11.3536 6.35355C11.1583 6.54882 10.8417 6.54882 10.6464 6.35355L8.35355 4.06066Z' fill='%236b7280'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 11.9393C8.15829 12.1346 7.84171 12.1346 7.64645 11.9393L5.35355 9.64645C5.15829 9.45119 4.84171 9.45119 4.64645 9.64645C4.45118 9.84171 4.45118 10.1583 4.64645 10.3536L6.93934 12.6464C7.52513 13.2322 8.47487 13.2322 9.06066 12.6464L11.3536 10.3536C11.5488 10.1583 11.5488 9.84171 11.3536 9.64645C11.1583 9.45119 10.8417 9.45119 10.6464 9.64645L8.35355 11.9393Z' fill='%236b7280'/%3E%3C/svg%3E%0A")
|
--codex-select-icon-url,
|
||||||
);
|
url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 4.06066C8.15829 3.8654 7.84171 3.8654 7.64645 4.06066L5.35355 6.35355C5.15829 6.54882 4.84171 6.54882 4.64645 6.35355C4.45118 6.15829 4.45118 5.84171 4.64645 5.64645L6.93934 3.35356C7.52513 2.76777 8.47487 2.76777 9.06066 3.35355L11.3536 5.64645C11.5488 5.84171 11.5488 6.15829 11.3536 6.35355C11.1583 6.54882 10.8417 6.54882 10.6464 6.35355L8.35355 4.06066Z' fill='%236b7280'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.35355 11.9393C8.15829 12.1346 7.84171 12.1346 7.64645 11.9393L5.35355 9.64645C5.15829 9.45119 4.84171 9.45119 4.64645 9.64645C4.45118 9.84171 4.45118 10.1583 4.64645 10.3536L6.93934 12.6464C7.52513 13.2322 8.47487 13.2322 9.06066 12.6464L11.3536 10.3536C11.5488 10.1583 11.5488 9.84171 11.3536 9.64645C11.1583 9.45119 10.8417 9.45119 10.6464 9.64645L8.35355 11.9393Z' fill='%236b7280'/%3E%3C/svg%3E%0A")
|
||||||
background-position: right 0.5rem center;
|
);
|
||||||
background-repeat: no-repeat;
|
background-position: right 0.5rem center;
|
||||||
background-size: 1.25em 1.25em;
|
background-repeat: no-repeat;
|
||||||
box-sizing: border-box;
|
background-size: 1.25em 1.25em;
|
||||||
}
|
box-sizing: border-box;
|
||||||
|
|
||||||
.select:hover,
|
@media (min-width: 801px) {
|
||||||
.select:focus-visible,
|
& {
|
||||||
.select:active {
|
min-width: 20rem;
|
||||||
box-shadow: 0 0 0 1px var(--codex-border-color);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-label {
|
&:hover,
|
||||||
margin-bottom: 0.5rem;
|
&:focus-visible,
|
||||||
font-weight: 500;
|
&:active {
|
||||||
display: block;
|
box-shadow: 0 0 0 1px var(--codex-border-color);
|
||||||
color: var(--codex-color);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 801px) {
|
label {
|
||||||
.select {
|
margin-bottom: 0.5rem;
|
||||||
min-width: 20rem;
|
font-weight: 500;
|
||||||
|
display: block;
|
||||||
|
color: var(--codex-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,10 @@ export function Sheets({ open, onClose, children }: Props) {
|
||||||
const attr = attributes({ "aria-expanded": open });
|
const attr = attributes({ "aria-expanded": open });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={classnames(["sheets"], ["sheets--open", open])}>
|
||||||
className={classnames(
|
<Backdrop onClose={onClose} open={open} />
|
||||||
["sheets-container"],
|
|
||||||
["sheets-container--open", open]
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Backdrop onClose={onClose} open={open} className={"sheets-backdrop"} />
|
|
||||||
|
|
||||||
<div className="sheets" {...attr}>
|
<aside {...attr}>{children}</aside>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,53 @@
|
||||||
.sheets {
|
.sheets {
|
||||||
position: fixed;
|
|
||||||
transition: transform 0.25s;
|
|
||||||
background-color: var(--codex-background-secondary);
|
|
||||||
z-index: 2;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sheets-container {
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
|
||||||
|
|
||||||
.sheets-container--open {
|
&.sheets--open {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
|
||||||
|
|
||||||
.sheets-backdrop {
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1000px) {
|
|
||||||
.sheets {
|
|
||||||
width: 300px;
|
|
||||||
height: 100%;
|
|
||||||
bottom: 0;
|
|
||||||
top: 0;
|
|
||||||
transform: translatex(1300px);
|
|
||||||
right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sheets[aria-expanded] {
|
aside {
|
||||||
transform: translatex(0);
|
position: fixed;
|
||||||
z-index: 10;
|
transition: transform 0.25s;
|
||||||
}
|
background-color: var(--codex-background-secondary);
|
||||||
}
|
z-index: 2;
|
||||||
|
justify-content: space-between;
|
||||||
@media (max-width: 999px) {
|
|
||||||
.sheets {
|
@media (min-width: 1000px) {
|
||||||
width: 100%;
|
& {
|
||||||
height: auto;
|
width: 300px;
|
||||||
bottom: 0;
|
height: 100%;
|
||||||
top: auto;
|
bottom: 0;
|
||||||
transform: translatey(1300px);
|
top: 0;
|
||||||
left: 0;
|
transform: translatex(1300px);
|
||||||
padding-bottom: 1.5rem;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sheets[aria-expanded] {
|
&[aria-expanded] {
|
||||||
transform: translatey(0);
|
transform: translatex(0);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 999px) {
|
||||||
|
& {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
bottom: 0;
|
||||||
|
top: auto;
|
||||||
|
transform: translatey(1300px);
|
||||||
|
left: 0;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[aria-expanded] {
|
||||||
|
transform: translatey(0);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
import { CSSProperties, ReactNode } from "react";
|
|
||||||
import "./simpleText.css";
|
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-color"?: string;
|
|
||||||
"--codex-color-primary"?: string;
|
|
||||||
"--codex-color-light"?: string;
|
|
||||||
"--codex-color-error"?: string;
|
|
||||||
"--codex-color-warning"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
/**
|
|
||||||
* Default variant is normal
|
|
||||||
*/
|
|
||||||
variant?: "normal" | "primary" | "light" | "error" | "warning";
|
|
||||||
|
|
||||||
className?: string;
|
|
||||||
|
|
||||||
children: string | ReactNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-color
|
|
||||||
* --codex-color-primary
|
|
||||||
* --codex-color-light
|
|
||||||
* --codex-color-error
|
|
||||||
* --codex-color-warning
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
size?: "normal" | "small";
|
|
||||||
|
|
||||||
center?: boolean;
|
|
||||||
|
|
||||||
bold?: boolean;
|
|
||||||
|
|
||||||
onClick?: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function SimpleText({
|
|
||||||
variant = "normal",
|
|
||||||
className = "",
|
|
||||||
center,
|
|
||||||
size = "normal",
|
|
||||||
onClick,
|
|
||||||
style,
|
|
||||||
children,
|
|
||||||
bold,
|
|
||||||
}: Props) {
|
|
||||||
const c = `text text--${variant} ${className} ${center ? "text--center" : ""} ${bold ? "text--bold" : ""}`;
|
|
||||||
|
|
||||||
if (size === "small") {
|
|
||||||
return (
|
|
||||||
<small onClick={onClick} className={c} style={style}>
|
|
||||||
{children}
|
|
||||||
</small>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span onClick={onClick} className={c} style={style}>
|
|
||||||
{children}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
.text--normal {
|
|
||||||
color: var(--codex-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--primary {
|
|
||||||
color: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--light {
|
|
||||||
color: var(--codex-input-label-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--error {
|
|
||||||
color: rgb(var(--codex-color-error));
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--warning {
|
|
||||||
color: rgb(var(--codex-color-warning));
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { SimpleText } from "../SimpleText/SimpleText";
|
|
||||||
import { PrettyBytes } from "../utils/bytes";
|
import { PrettyBytes } from "../utils/bytes";
|
||||||
import "./spaceAllocation.css";
|
import "./spaceAllocation.css";
|
||||||
|
|
||||||
|
@ -25,36 +24,31 @@ export function SpaceAllocation({ data }: Props) {
|
||||||
const total = data.reduce((acc, val) => acc + val.size, 0);
|
const total = data.reduce((acc, val) => acc + val.size, 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="space-allocation">
|
||||||
<div className="nodeSpaceAllocation-bar">
|
<header>
|
||||||
{data.map((d) => (
|
{data.map((d) => (
|
||||||
<span
|
<span
|
||||||
key={d.title}
|
key={d.title}
|
||||||
className={`nodeSpaceAllocation-barItem nodeSpaceAllocation-barQuota ${d.className || ""}`}
|
className={`${d.className || ""}`}
|
||||||
style={{
|
style={{
|
||||||
width: (d.size / total) * 100 + "%",
|
width: (d.size / total) * 100 + "%",
|
||||||
backgroundColor: d.color,
|
backgroundColor: d.color,
|
||||||
}}
|
}}
|
||||||
></span>
|
></span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<div className="nodeSpaceAllocation-legend">
|
<ul className="nodeSpaceAllocation-legend">
|
||||||
{data.map((d) => (
|
{data.map((d) => (
|
||||||
<div key={d.title} className={"nodeSpaceAllocation-legendRow"}>
|
<li key={d.title}>
|
||||||
<div
|
<span style={{ backgroundColor: d.color }}></span>
|
||||||
className={`nodeSpaceAllocation-legendItem nodeSpaceAllocation-quota`}
|
<p>
|
||||||
style={{ backgroundColor: d.color }}
|
<span>{d.title}</span>
|
||||||
></div>
|
<small> {PrettyBytes(d.size)}</small>
|
||||||
<div className="nodeSpaceAllocation-legendItem-text">
|
</p>
|
||||||
<small>{d.title}</small>
|
</li>
|
||||||
<SimpleText variant="light" size="small">
|
|
||||||
{PrettyBytes(d.size)}
|
|
||||||
</SimpleText>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</ul>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,46 @@
|
||||||
.nodeSpaceAllocation-bar {
|
.space-allocation {
|
||||||
height: 10px;
|
header {
|
||||||
display: flex;
|
height: 10px;
|
||||||
gap: 0.75rem;
|
display: flex;
|
||||||
margin-bottom: 0.5rem;
|
gap: 0.75rem;
|
||||||
}
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
.nodeSpaceAllocation-barQuota {
|
span {
|
||||||
width: 10%;
|
display: inline-block;
|
||||||
}
|
height: 100%;
|
||||||
|
border-radius: var(--codex-border-radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.nodeSpaceAllocation-barItem {
|
ul {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
height: 100%;
|
gap: 0.75rem;
|
||||||
border-radius: var(--codex-border-radius);
|
flex-wrap: wrap;
|
||||||
}
|
padding-left: 0;
|
||||||
|
|
||||||
.nodeSpaceAllocation-barQuota-used {
|
li {
|
||||||
border-top-left-radius: var(--codex-border-radius);
|
display: flex;
|
||||||
border-bottom-left-radius: var(--codex-border-radius);
|
align-items: center;
|
||||||
border-radius: var(--codex-border-radius);
|
justify-content: space-between;
|
||||||
}
|
gap: 0.5rem;
|
||||||
|
|
||||||
.nodeSpaceAllocation-legend {
|
> span {
|
||||||
display: flex;
|
width: 1rem;
|
||||||
gap: 0.75rem;
|
height: 1rem;
|
||||||
flex-wrap: wrap;
|
border-radius: var(--codex-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeSpaceAllocation-legendItem {
|
p {
|
||||||
width: 1rem;
|
display: flex;
|
||||||
height: 1rem;
|
flex-direction: column;
|
||||||
border-radius: var(--codex-border-radius);
|
line-height: 1rem;
|
||||||
}
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
.nodeSpaceAllocation-legendRow {
|
small {
|
||||||
display: flex;
|
color: var(--codex-input-label-color);
|
||||||
align-items: center;
|
}
|
||||||
justify-content: space-between;
|
}
|
||||||
margin-bottom: 0.75rem;
|
}
|
||||||
gap: 0.5rem;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.nodeSpaceAllocation-legendItem-text {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
line-height: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
.step {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
transition: opacity 0.35s;
|
||||||
|
|
||||||
|
&:not([disabled]):not(.step--active):hover {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 801px) {
|
||||||
|
&:not(:last-child) {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div:first-child {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
transition: opacity 0.35s;
|
||||||
|
|
||||||
|
width: 1.75rem;
|
||||||
|
height: 1.75rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: background-color 0.35s;
|
||||||
|
background-color: var(
|
||||||
|
--codex-stepper-background,
|
||||||
|
var(--codex-background-light)
|
||||||
|
);
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.step--active > div:first-child,
|
||||||
|
&.step--done > div:first-child {
|
||||||
|
background-color: var(--codex-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
div:nth-child(2) {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
place-items: center;
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
flex: 1;
|
||||||
|
background-color: var(
|
||||||
|
--codex-stepper-background,
|
||||||
|
var(--codex-background-light)
|
||||||
|
);
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
& {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background-color: var(--codex-color-primary);
|
||||||
|
height: 1px;
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-name: step-back;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
opacity: 0;
|
||||||
|
/* animation-direction: reverse; */
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
& {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.step--done {
|
||||||
|
div:nth-child(2) {
|
||||||
|
&::before {
|
||||||
|
background-color: var(--codex-color-primary);
|
||||||
|
display: inline-block;
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-name: step;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.step--mounted {
|
||||||
|
div:nth-child(2) {
|
||||||
|
&::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { Check } from "lucide-react";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { attributes } from "../utils/attributes";
|
import { attributes } from "../utils/attributes";
|
||||||
import { classnames } from "../utils/classnames";
|
import { classnames } from "../utils/classnames";
|
||||||
|
import "./Step.css";
|
||||||
|
|
||||||
type StepProps = {
|
type StepProps = {
|
||||||
/**
|
/**
|
||||||
|
@ -52,36 +53,22 @@ export function Step({
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames(
|
className={classnames(
|
||||||
["stepper-step", true],
|
["step", true],
|
||||||
["stepper-step-active", isActive]
|
["step--active", isActive],
|
||||||
|
["step--done", isDone],
|
||||||
|
["step--,mounted", mounted.current]
|
||||||
)}
|
)}
|
||||||
onClick={() => onClick?.(step)}
|
onClick={() => onClick?.(step)}
|
||||||
{...attributes({ disabled: !onClick })}
|
{...attributes({ disabled: !onClick })}
|
||||||
>
|
>
|
||||||
<div className="stepper-step-info">
|
<div>
|
||||||
<div
|
<span>{isDone ? <Check size={"1.25rem"} /> : step + 1}</span>
|
||||||
className={classnames(
|
|
||||||
["stepper-number", true],
|
|
||||||
["stepper-number-active", isActive],
|
|
||||||
["stepper-number-done", isDone]
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span className="stepper-numberValue">
|
|
||||||
{isDone ? <Check size={"1.25rem"} /> : step + 1}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!isLast && (
|
{!isLast && (
|
||||||
<div className="stepper-step-between">
|
<div>
|
||||||
<div
|
<hr />
|
||||||
className={classnames(
|
<span>{title}</span>
|
||||||
["stepper-separator", true],
|
|
||||||
["stepper-separator-done", isDone],
|
|
||||||
["stepper-separator-mounted", mounted.current]
|
|
||||||
)}
|
|
||||||
></div>
|
|
||||||
<span className={"stepper-text"}>{title}</span>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,17 +1,10 @@
|
||||||
import { Button } from "../Button/Button";
|
import { Button } from "../Button/Button";
|
||||||
import "./stepper.css";
|
import "./stepper.css";
|
||||||
import { CSSProperties, Dispatch, ReactNode } from "react";
|
import { Dispatch, ReactNode } from "react";
|
||||||
import { Spinner } from "../Spinner/Spinner";
|
import { Spinner } from "../Spinner/Spinner";
|
||||||
import { Step } from "./Step";
|
import { Step } from "./Step";
|
||||||
import { StepperAction, StepperState } from "./useStepperReducer";
|
import { StepperAction, StepperState } from "./useStepperReducer";
|
||||||
|
import { classnames } from "../utils/classnames";
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-background"?: string;
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-stepper-background": string;
|
|
||||||
"--codex-color-primary": string;
|
|
||||||
"--codex-border-color": string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +17,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The duration between steps
|
* The duration between steps
|
||||||
*/
|
*/
|
||||||
|
@ -69,7 +60,6 @@ export function Stepper({
|
||||||
titles,
|
titles,
|
||||||
children,
|
children,
|
||||||
state,
|
state,
|
||||||
style,
|
|
||||||
dispatch,
|
dispatch,
|
||||||
className = "",
|
className = "",
|
||||||
backLabel = "Back",
|
backLabel = "Back",
|
||||||
|
@ -95,8 +85,13 @@ export function Stepper({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"stepper " + className} style={style}>
|
<div
|
||||||
<div className="stepper-steps">
|
className={classnames(
|
||||||
|
["stepper " + className],
|
||||||
|
["stepper--progress", state.progress]
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<header>
|
||||||
{titles.map((title, index) => (
|
{titles.map((title, index) => (
|
||||||
<Step
|
<Step
|
||||||
title={title}
|
title={title}
|
||||||
|
@ -108,19 +103,13 @@ export function Stepper({
|
||||||
onClick={state.step > index ? () => onChangeStep(index) : undefined}
|
onClick={state.step > index ? () => onChangeStep(index) : undefined}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<div className="stepper-body">
|
<main>
|
||||||
{state.progress ? (
|
{state.progress ? <Spinner width={"3rem"} /> : <>{children}</>}
|
||||||
<div className="stepper-progress">
|
</main>
|
||||||
<Spinner width={"3rem"} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<>{children}</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="stepper-buttons">
|
<footer>
|
||||||
<Button
|
<Button
|
||||||
label={backLabel}
|
label={backLabel}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
@ -132,7 +121,7 @@ export function Stepper({
|
||||||
onClick={() => onChangeStep(state.step + 1)}
|
onClick={() => onChangeStep(state.step + 1)}
|
||||||
disabled={!state.isNextEnable}
|
disabled={!state.isNextEnable}
|
||||||
/>
|
/>
|
||||||
</div>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,120 +3,46 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: var(--codex-background);
|
background-color: var(--codex-background);
|
||||||
border-radius: var(--codex-border-radius);
|
border-radius: var(--codex-border-radius);
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-progress,
|
header {
|
||||||
.stepper-step-info,
|
display: flex;
|
||||||
.stepper-steps,
|
align-items: center;
|
||||||
.stepper-step {
|
gap: 0.5rem;
|
||||||
display: flex;
|
transition: opacity 0.35s;
|
||||||
align-items: center;
|
}
|
||||||
gap: 0.5rem;
|
|
||||||
transition: opacity 0.35s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-step:not([disabled]):not(.stepper-separator-active):hover {
|
main {
|
||||||
cursor: pointer;
|
margin: 1.5rem 0;
|
||||||
opacity: 0.8;
|
border: 1px dashed var(--codex-border-color);
|
||||||
}
|
border-radius: var(--codex-border-radius);
|
||||||
|
background-color: var(
|
||||||
|
--codex-stepper-background,
|
||||||
|
var(--codex-background-light)
|
||||||
|
);
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.stepper-number {
|
@media (min-width: 801px) {
|
||||||
width: 1.75rem;
|
& {
|
||||||
height: 1.75rem;
|
min-width: 500px;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
}
|
||||||
border-radius: 50%;
|
|
||||||
transition: background-color 0.35s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-number:not(.stepper-number-active):not(.stepper-number-done) {
|
&.stepper--progress {
|
||||||
background-color: var(
|
main {
|
||||||
--codex-stepper-background,
|
justify-content: center;
|
||||||
var(--codex-background-light)
|
flex: 1;
|
||||||
);
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.stepper-separator {
|
footer {
|
||||||
height: 1px;
|
display: flex;
|
||||||
flex: 1;
|
justify-content: space-between;
|
||||||
background-color: var(
|
}
|
||||||
--codex-stepper-background,
|
|
||||||
var(--codex-background-light)
|
|
||||||
);
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-number-done,
|
|
||||||
.stepper-number-active {
|
|
||||||
background-color: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-numberValue {
|
|
||||||
mix-blend-mode: difference;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-buttons {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-body {
|
|
||||||
margin: 1.5rem 0;
|
|
||||||
border: 1px dashed var(--codex-border-color);
|
|
||||||
border-radius: var(--codex-border-radius);
|
|
||||||
background-color: var(
|
|
||||||
--codex-stepper-background,
|
|
||||||
var(--codex-background-light)
|
|
||||||
);
|
|
||||||
min-height: 200px;
|
|
||||||
padding: 1.5rem;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-progress {
|
|
||||||
justify-content: center;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-numberValue {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-separator::before {
|
|
||||||
background-color: var(--codex-color-primary);
|
|
||||||
height: 1px;
|
|
||||||
content: " ";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
animation-duration: 1s;
|
|
||||||
animation-name: step-back;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
opacity: 0;
|
|
||||||
/* animation-direction: reverse; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-separator-done::before {
|
|
||||||
background-color: var(--codex-color-primary);
|
|
||||||
display: inline-block;
|
|
||||||
animation-duration: 1s;
|
|
||||||
animation-name: step;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-separator-mounted::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-success {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
place-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes step {
|
@keyframes step {
|
||||||
|
@ -138,40 +64,3 @@
|
||||||
width: 0%;
|
width: 0%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 801px) {
|
|
||||||
.stepper-container {
|
|
||||||
width: 700px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-step:not(:last-child) {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-step-between {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
place-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-text {
|
|
||||||
position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-body {
|
|
||||||
min-width: 500px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
|
||||||
.stepper-container {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepper-step:not(.stepper-step-active) .stepper-text,
|
|
||||||
.stepper-separator {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { ReactNode } from "react";
|
|
||||||
import "./cell.css";
|
|
||||||
|
|
||||||
export type CellProps = {
|
|
||||||
children: ReactNode | string;
|
|
||||||
} & React.DetailedHTMLProps<
|
|
||||||
React.TdHTMLAttributes<HTMLTableCellElement>,
|
|
||||||
HTMLTableCellElement
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const Cell = ({ children, className = "", ...rest }: CellProps) => (
|
|
||||||
<td className={"cell" + className} {...rest}>
|
|
||||||
{children}
|
|
||||||
</td>
|
|
||||||
);
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { Fragment, ReactElement } from "react";
|
|
||||||
import { Cell, CellProps } from "./Cell";
|
|
||||||
import "./row.css";
|
|
||||||
|
|
||||||
export type RowProps = {
|
|
||||||
cells: ReactElement<CellProps, typeof Cell>[];
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Row({ cells, className = "" }: RowProps) {
|
|
||||||
return (
|
|
||||||
<tr className={"row " + className}>
|
|
||||||
{cells.map((Cell, index) => (
|
|
||||||
<Fragment key={index}>{Cell}</Fragment>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
import "./table.css";
|
import "./table.css";
|
||||||
import { ArrowDownUp, Search } from "lucide-react";
|
import { ArrowDownUp, Search } from "lucide-react";
|
||||||
import { Row, RowProps } from "./Row";
|
import { Fragment, ReactElement, ReactNode, useEffect, useState } from "react";
|
||||||
import { Fragment, ReactElement, useEffect, useState } from "react";
|
|
||||||
import { classnames } from "../utils/classnames";
|
import { classnames } from "../utils/classnames";
|
||||||
|
import { attributes } from "../utils/attributes";
|
||||||
|
|
||||||
export type TabSortState = "asc" | "desc" | null;
|
export type TabSortState = "asc" | "desc" | null;
|
||||||
|
|
||||||
|
@ -61,10 +61,16 @@ export function Table({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`table-container ${className}`}>
|
<div
|
||||||
<table className={"table"}>
|
className={classnames(
|
||||||
<thead className="table-thead">
|
["table"],
|
||||||
<tr className="table-theadTr">
|
[className],
|
||||||
|
["table--empty", !!rows.length]
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
{headers.map((col, index) => {
|
{headers.map((col, index) => {
|
||||||
const [name, sort] = Array.isArray(col) ? col : [col];
|
const [name, sort] = Array.isArray(col) ? col : [col];
|
||||||
const state = index === sortSelected[0] ? sortSelected[1] : null;
|
const state = index === sortSelected[0] ? sortSelected[1] : null;
|
||||||
|
@ -72,9 +78,14 @@ export function Table({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
className={classnames(
|
{...attributes(
|
||||||
["table-theadTh"],
|
sort
|
||||||
["table-theadTh--clickable", !!sort]
|
? {
|
||||||
|
role: "button",
|
||||||
|
"aria-sort":
|
||||||
|
state === "asc" ? "ascending" : "descending",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
)}
|
)}
|
||||||
key={name}
|
key={name}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -82,14 +93,9 @@ export function Table({
|
||||||
sort?.(nxt);
|
sort?.(nxt);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="table-theadTh-content">
|
<div>
|
||||||
<span>{name}</span>
|
<span>{name}</span>
|
||||||
{sort && (
|
{sort && <ArrowDownUp size={"1rem"}></ArrowDownUp>}
|
||||||
<ArrowDownUp
|
|
||||||
className={"table-theadTh-icon--" + state}
|
|
||||||
size={"1rem"}
|
|
||||||
></ArrowDownUp>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
);
|
);
|
||||||
|
@ -104,11 +110,39 @@ export function Table({
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
{!rows.length && (
|
{!rows.length && (
|
||||||
<div className="table-placeholder">
|
<div>
|
||||||
<Search />
|
<Search />
|
||||||
<p className="table-placeholderText">No data.</p>
|
<p>No data.</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CellProps = {
|
||||||
|
children: ReactNode | string;
|
||||||
|
} & React.DetailedHTMLProps<
|
||||||
|
React.TdHTMLAttributes<HTMLTableCellElement>,
|
||||||
|
HTMLTableCellElement
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const Cell = ({ children, className = "", ...rest }: CellProps) => (
|
||||||
|
<td className={className} {...rest}>
|
||||||
|
{children}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
|
||||||
|
export type RowProps = {
|
||||||
|
cells: ReactElement<CellProps, typeof Cell>[];
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Row({ cells, className = "" }: RowProps) {
|
||||||
|
return (
|
||||||
|
<tr className={className}>
|
||||||
|
{cells.map((Cell, index) => (
|
||||||
|
<Fragment key={index}>{Cell}</Fragment>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
.cell {
|
|
||||||
text-align: left;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
.row {
|
|
||||||
border-bottom: 1px solid var(--codex-border-color);
|
|
||||||
transition: background-color 0.35s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row:hover {
|
|
||||||
background-color: var(--codex-background-light);
|
|
||||||
}
|
|
|
@ -1,70 +1,131 @@
|
||||||
.table {
|
.table {
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-placeholder {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-placeholderText {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-container {
|
|
||||||
border: 1px solid var(--codex-border-color);
|
|
||||||
background-color: var(--codex-background-secondary);
|
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
border-radius: var(--codex-border-radius);
|
border-radius: var(--codex-border-radius);
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.table-theadTr {
|
table {
|
||||||
border-bottom: 1px solid var(--codex-border-color);
|
border-spacing: 0 12px;
|
||||||
}
|
width: 100%;
|
||||||
|
|
||||||
.table-theadTh {
|
thead {
|
||||||
color: var(--codex-color-light);
|
tr {
|
||||||
font-weight: normal;
|
border-bottom: 1px solid var(--codex-border-color);
|
||||||
text-transform: uppercase;
|
border-radius: 8px;
|
||||||
font-size: 0.9rem;
|
|
||||||
text-align: left;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-theadTh--clickable {
|
th {
|
||||||
cursor: pointer;
|
color: var(--codex-color-light);
|
||||||
}
|
font-weight: normal;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
text-align: left;
|
||||||
|
height: 36px;
|
||||||
|
padding: 0 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #232323;
|
||||||
|
|
||||||
.table-theadTh-content {
|
&[role="button"] {
|
||||||
display: flex;
|
cursor: pointer;
|
||||||
align-items: center;
|
}
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-theadTh-content svg {
|
div {
|
||||||
position: relative;
|
display: flex;
|
||||||
top: -2px;
|
align-items: center;
|
||||||
cursor: pointer;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-theadTh-content svg path {
|
svg {
|
||||||
opacity: 0.5;
|
position: relative;
|
||||||
transition: opacity 0.35s;
|
top: -2px;
|
||||||
}
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.table-theadTh-icon--desc path:nth-child(1),
|
svg path {
|
||||||
.table-theadTh-icon--desc path:nth-child(2) {
|
opacity: 0.5;
|
||||||
opacity: 1;
|
transition: opacity 0.35s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-theadTh-icon--asc path:nth-child(3),
|
th[aria-sort="descending"] path:nth-child(1),
|
||||||
.table-theadTh-icon--asc path:nth-child(4) {
|
th[aria-sort="descending"] path:nth-child(2) {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
th[aria-sort="ascending"] path:nth-child(3),
|
||||||
|
th[aria-sort="ascending"] path:nth-child(4) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-top-left-radius: 8px;
|
||||||
|
border-bottom-left-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-top-right-radius: 8px;
|
||||||
|
border-bottom-right-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
tr {
|
||||||
|
border-bottom: 1px solid var(--codex-border-color);
|
||||||
|
transition: background-color 0.35s;
|
||||||
|
border-radius: 8px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--codex-background-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
text-align: left;
|
||||||
|
height: 64px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #232323;
|
||||||
|
padding: 0 16px;
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: -0.006em;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-top-left-radius: 8px;
|
||||||
|
border-bottom-left-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-top-right-radius: 8px;
|
||||||
|
border-bottom-right-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: " ";
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
display: inline-block;
|
||||||
|
background: #96969633;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -7px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 2rem;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ComponentType } from "react";
|
import { ComponentType } from "react";
|
||||||
import "./tabs.css";
|
import "./tabs.css";
|
||||||
import { classnames } from "../utils/classnames";
|
import { classnames } from "../utils/classnames";
|
||||||
|
import { attributes } from "../utils/attributes";
|
||||||
|
|
||||||
export type TabProps = {
|
export type TabProps = {
|
||||||
label: string;
|
label: string;
|
||||||
|
@ -26,11 +27,8 @@ export function Tabs({ tabs, onTabChange, tabIndex }: Props) {
|
||||||
{tabs.map((tab, index) => (
|
{tabs.map((tab, index) => (
|
||||||
<div
|
<div
|
||||||
key={tab.label}
|
key={tab.label}
|
||||||
className={classnames(
|
{...attributes({ "aria-selected": tabIndex === index })}
|
||||||
["tabs-tab"],
|
className={classnames([tab.className || ""])}
|
||||||
["tabs-tab--active", tabIndex === index],
|
|
||||||
[tab.className || ""]
|
|
||||||
)}
|
|
||||||
onClick={() => onTabChange(index)}
|
onClick={() => onTabChange(index)}
|
||||||
>
|
>
|
||||||
{tab.Icon && <tab.Icon />}
|
{tab.Icon && <tab.Icon />}
|
||||||
|
|
|
@ -3,50 +3,39 @@
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-tab {
|
&::after {
|
||||||
display: flex;
|
width: 100%;
|
||||||
align-items: center;
|
background-color: var(--codex-background-light);
|
||||||
gap: 0.25rem;
|
content: " ";
|
||||||
padding-bottom: 1rem;
|
position: absolute;
|
||||||
cursor: pointer;
|
height: 2px;
|
||||||
transition: 0.35s opacity;
|
top: 11px;
|
||||||
z-index: 1;
|
top: 31px;
|
||||||
position: relative;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.tabs::after {
|
div {
|
||||||
width: 100%;
|
display: flex;
|
||||||
background-color: var(--codex-background-light);
|
align-items: center;
|
||||||
content: " ";
|
gap: 0.25rem;
|
||||||
position: absolute;
|
padding-bottom: 1rem;
|
||||||
height: 2px;
|
cursor: pointer;
|
||||||
top: 11px;
|
transition: 0.35s opacity;
|
||||||
top: 31px;
|
z-index: 1;
|
||||||
}
|
position: relative;
|
||||||
|
|
||||||
.tabs-tab:not(.files-headerTab--active) {
|
&:hover {
|
||||||
opacity: 0.7;
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs-tab:hover {
|
&[aria-selected]:after {
|
||||||
opacity: 0.85;
|
width: 100%;
|
||||||
}
|
background-color: var(--codex-color-contrast);
|
||||||
|
content: " ";
|
||||||
.tabs-tab--active:after {
|
position: absolute;
|
||||||
width: 100%;
|
height: 2px;
|
||||||
background-color: var(--codex-color-contrast);
|
top: 11px;
|
||||||
content: " ";
|
top: 31px;
|
||||||
position: absolute;
|
}
|
||||||
height: 2px;
|
}
|
||||||
top: 11px;
|
|
||||||
top: 31px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-icon {
|
|
||||||
width: 1rem;
|
|
||||||
height: 1rem;
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
import { CSSProperties, useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { attributes } from "../utils/attributes";
|
import { attributes } from "../utils/attributes";
|
||||||
import "./toast.css";
|
import "./toast.css";
|
||||||
import { CircleCheck, CircleX, Info, X } from "lucide-react";
|
import { CircleCheck, CircleX, Info, X } from "lucide-react";
|
||||||
import { ButtonIcon } from "../ButtonIcon/ButtonIcon";
|
import { ButtonIcon } from "../ButtonIcon/ButtonIcon";
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-toast-background"?: string;
|
|
||||||
"--codex-toast-border-color"?: string;
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-toast-color"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
message: string;
|
message: string;
|
||||||
|
|
||||||
|
@ -30,22 +23,12 @@ type Props = {
|
||||||
|
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* codex-toast-background
|
|
||||||
* codex-toast-border-color
|
|
||||||
* codex-border-radius
|
|
||||||
* codex-toast-color
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
variant: "success" | "error" | "default";
|
variant: "success" | "error" | "default";
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Toast({
|
export function Toast({
|
||||||
message,
|
message,
|
||||||
time,
|
time,
|
||||||
style,
|
|
||||||
variant,
|
variant,
|
||||||
className = "",
|
className = "",
|
||||||
duration = 3000,
|
duration = 3000,
|
||||||
|
@ -84,12 +67,11 @@ export function Toast({
|
||||||
<div
|
<div
|
||||||
className={`toast ${className} toast--${variant}`}
|
className={`toast ${className} toast--${variant}`}
|
||||||
{...attributes({ "aria-hidden": time == 0 || msg === "" })}
|
{...attributes({ "aria-hidden": time == 0 || msg === "" })}
|
||||||
style={style}
|
|
||||||
>
|
>
|
||||||
<Icon size="1.25rem" className="toast-icon" />
|
<Icon size="1.25rem" />
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
<b className="toast-title">{variant} ! </b>
|
<b>{variant} ! </b>
|
||||||
<span>{msg}</span>
|
<span>{msg}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
@ -18,33 +18,33 @@
|
||||||
border: 1px solid rgb(var(--codex-toast-color));
|
border: 1px solid rgb(var(--codex-toast-color));
|
||||||
background: rgba(var(--codex-toast-color), 1);
|
background: rgba(var(--codex-toast-color), 1);
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
}
|
|
||||||
|
|
||||||
.toast-close {
|
&[aria-hidden] {
|
||||||
margin-left: 0.75rem;
|
transform: translateX(1000px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast[aria-hidden] {
|
&.toast--success {
|
||||||
transform: translateX(1000px);
|
--codex-toast-color: var(--codex-color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast-title {
|
&.toast--error {
|
||||||
text-transform: capitalize;
|
--codex-toast-color: var(--codex-color-error);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast-icon {
|
&.toast--default {
|
||||||
fill: rgba(var(--codex-toast-color), 0.2);
|
--codex-toast-color: var(--codex-color-grey);
|
||||||
stroke: white;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.toast--success {
|
.button {
|
||||||
--codex-toast-color: var(--codex-color-success);
|
margin-left: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--error {
|
b {
|
||||||
--codex-toast-color: var(--codex-color-error);
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--default {
|
svg {
|
||||||
--codex-toast-color: var(--codex-color-grey);
|
fill: rgba(var(--codex-toast-color), 0.2);
|
||||||
|
stroke: white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { FileStack, Upload as UploadIcon } from "lucide-react";
|
import { FileStack, Upload as UploadIcon } from "lucide-react";
|
||||||
import { ChangeEvent, CSSProperties, DragEventHandler, useRef } from "react";
|
import { ChangeEvent, DragEventHandler, useRef } from "react";
|
||||||
import { attributes } from "../utils/attributes.ts";
|
import { attributes } from "../utils/attributes.ts";
|
||||||
import "./upload.css";
|
import "./upload.css";
|
||||||
import { UploadFile } from "./UploadFile.tsx";
|
import { UploadFile } from "./UploadFile.tsx";
|
||||||
|
@ -7,17 +7,6 @@ import { useUploadStategy } from "./useUploadStrategy.ts";
|
||||||
import { classnames } from "../utils/classnames.ts";
|
import { classnames } from "../utils/classnames.ts";
|
||||||
import { ButtonIcon } from "../ButtonIcon/ButtonIcon.tsx";
|
import { ButtonIcon } from "../ButtonIcon/ButtonIcon.tsx";
|
||||||
import { CodexData } from "@codex-storage/sdk-js";
|
import { CodexData } from "@codex-storage/sdk-js";
|
||||||
import { SimpleText } from "../SimpleText/SimpleText.tsx";
|
|
||||||
|
|
||||||
interface CustomStyleCSS extends CSSProperties {
|
|
||||||
"--codex-border-color"?: string;
|
|
||||||
"--codex-border-radius"?: string;
|
|
||||||
"--codex-upload-background"?: string;
|
|
||||||
"--codex-color-primary"?: string;
|
|
||||||
"--codex-color"?: string;
|
|
||||||
"--codex-color-error"?: string;
|
|
||||||
"--codex-color-warning"?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/**
|
/**
|
||||||
|
@ -68,18 +57,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
// useWorker?: boolean;
|
// useWorker?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply custom css variables.
|
|
||||||
* --codex-border-color
|
|
||||||
* --codex-border-radius
|
|
||||||
* --codex-upload-background
|
|
||||||
* --codex-color-primary
|
|
||||||
* --codex-color
|
|
||||||
* --codex-color-error
|
|
||||||
* --codex-color-warning
|
|
||||||
*/
|
|
||||||
style?: CustomStyleCSS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Success message displayed when a file is updated.
|
* Success message displayed when a file is updated.
|
||||||
* Default: File uploaded successfully.
|
* Default: File uploaded successfully.
|
||||||
|
@ -151,17 +128,16 @@ export function Upload({
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
>
|
>
|
||||||
<ButtonIcon Icon={multiple ? FileStack : UploadIcon}></ButtonIcon>
|
<ButtonIcon Icon={multiple ? FileStack : UploadIcon}></ButtonIcon>
|
||||||
<div className="upload-text">
|
|
||||||
<div>
|
<p>
|
||||||
<b>
|
<b>
|
||||||
Drop your {multiple ? "file(s)" : "file"} here or{" "}
|
Drop your {multiple ? "file(s)" : "file"} here or{" "}
|
||||||
<span className="text--primary">browse</span>
|
<span>browse</span>
|
||||||
</b>
|
</b>
|
||||||
</div>
|
</p>
|
||||||
<SimpleText size="small" variant="light" center>
|
|
||||||
{multiple ? "Up to 10 files" : "Choose one single file"}
|
<small> {multiple ? "Up to 10 files" : "Choose one single file"}</small>
|
||||||
</SimpleText>
|
|
||||||
</div>
|
|
||||||
<input
|
<input
|
||||||
data-testid="upload"
|
data-testid="upload"
|
||||||
type="file"
|
type="file"
|
||||||
|
@ -171,7 +147,7 @@ export function Upload({
|
||||||
{...attributes({ multiple: multiple })}
|
{...attributes({ multiple: multiple })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{warning && <SimpleText variant="warning">{warning}</SimpleText>}
|
{warning && <span>{warning}</span>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{files.map(({ id, file }) => (
|
{files.map(({ id, file }) => (
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
.upload-file {
|
||||||
|
&[aria-invalid] {
|
||||||
|
--codex-upload-color: rgb(var(--codex-color-error));
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-done] {
|
||||||
|
--codex-upload-color: var(--codex-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
background-color: var(
|
||||||
|
--codex-upload-background,
|
||||||
|
var(--codex-background-secondary)
|
||||||
|
);
|
||||||
|
border-radius: var(--codex-border-radius);
|
||||||
|
border: 1px solid var(--codex-border-color);
|
||||||
|
padding: 1em 2rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
|
||||||
|
header {
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> div:first-child {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-radius: var(--codex-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
b {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--codex-upload-color);
|
||||||
|
|
||||||
|
span {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 150px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div:nth-child(2) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
color: var(--codex-upload-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 0.25 0;
|
||||||
|
|
||||||
|
progress {
|
||||||
|
flex-grow: 1;
|
||||||
|
background-color: var(
|
||||||
|
--codex-upload-background,
|
||||||
|
var(--codex-background-secondary)
|
||||||
|
);
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--codex-border-radius);
|
||||||
|
height: 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&[value]::-webkit-progress-bar {
|
||||||
|
background-color: var(--codex-background-light);
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[value]::-webkit-progress-value {
|
||||||
|
background: var(--codex-upload-color);
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[value]::-moz-progress-bar {
|
||||||
|
border-radius: 50px;
|
||||||
|
background: var(--codex-upload-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--codex-upload-color);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import { Spinner } from "../Spinner/Spinner";
|
||||||
import { CodexData } from "@codex-storage/sdk-js";
|
import { CodexData } from "@codex-storage/sdk-js";
|
||||||
import { WebFileIcon } from "../WebFileIcon/WebFileIcon";
|
import { WebFileIcon } from "../WebFileIcon/WebFileIcon";
|
||||||
import { ButtonIcon } from "../ButtonIcon/ButtonIcon";
|
import { ButtonIcon } from "../ButtonIcon/ButtonIcon";
|
||||||
import { SimpleText } from "../SimpleText/SimpleText";
|
import "./UploadFile.css";
|
||||||
|
|
||||||
type UploadFileProps = {
|
type UploadFileProps = {
|
||||||
file: File;
|
file: File;
|
||||||
|
@ -263,37 +263,32 @@ export function UploadFile({
|
||||||
const ActionIcon = () => <UploadActionIcon status={status} />;
|
const ActionIcon = () => <UploadActionIcon status={status} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
<div className={"uploadFile"}>
|
className="upload-file"
|
||||||
<div className="uploadFile-info">
|
{...attributes({
|
||||||
<div className="uploadFile-infoLeft">
|
"aria-invalid": status === "error",
|
||||||
|
"data-done": status === "done",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<header>
|
||||||
|
<div>
|
||||||
{preview ? (
|
{preview ? (
|
||||||
<img
|
<img src={preview} width="24" alt="Preview" />
|
||||||
src={preview}
|
|
||||||
width="24"
|
|
||||||
alt="Preview"
|
|
||||||
className="uploadFile-preview"
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<WebFileIcon type={file.type} />
|
<WebFileIcon type={file.type} />
|
||||||
)}
|
)}
|
||||||
<div className="uploadFile-infoText">
|
<p>
|
||||||
<b
|
<b>
|
||||||
className="uploadFile-name"
|
<span>{filename}</span>
|
||||||
{...attributes({
|
|
||||||
"aria-invalid": status === "error",
|
|
||||||
"data-done": status === "done",
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<span className="uploadFile-filename">{filename}</span>
|
|
||||||
{extension && <span>.{extension}</span>}
|
{extension && <span>.{extension}</span>}
|
||||||
</b>
|
</b>
|
||||||
<div>
|
<div>
|
||||||
<small>{PrettyBytes(file.size)}</small>
|
<small>{PrettyBytes(file.size)}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="uploadFile-infoRight">
|
<div>
|
||||||
<UploadStatusIcon status={status} />
|
<UploadStatusIcon status={status} />
|
||||||
|
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
|
@ -302,33 +297,27 @@ export function UploadFile({
|
||||||
Icon={ActionIcon}
|
Icon={ActionIcon}
|
||||||
></ButtonIcon>
|
></ButtonIcon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<div className="uploadFile-progress">
|
<main>
|
||||||
<progress
|
<progress
|
||||||
className="uploadFile-progressBar"
|
|
||||||
{...attributes({
|
{...attributes({
|
||||||
max: file ? progress.total.toString() : false,
|
max: file ? progress.total.toString() : false,
|
||||||
value: file ? progress.loaded.toString() : false,
|
value: file ? progress.loaded.toString() : false,
|
||||||
"aria-invalid": status === "error",
|
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
<span className="uploadFile-progressBarPercent">
|
<span>{percent.toFixed(2)} %</span>
|
||||||
{percent.toFixed(2)} %
|
</main>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="uploadFile-message">
|
<footer>
|
||||||
{cid ? (
|
{cid ? (
|
||||||
<div className="text--primary">{successMessage}</div>
|
<span>{successMessage}</span>
|
||||||
) : (
|
) : (
|
||||||
<SimpleText variant="error">
|
<span> {error ? error : <> </>}</span>
|
||||||
{error ? error : <> </>}
|
|
||||||
</SimpleText>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,172 +11,24 @@
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0.5rem 2rem;
|
padding: 0.5rem 2rem;
|
||||||
}
|
|
||||||
|
|
||||||
.upload-selected {
|
|
||||||
border-color: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile {
|
|
||||||
background-color: var(
|
|
||||||
--codex-upload-background,
|
|
||||||
var(--codex-background-secondary)
|
|
||||||
);
|
|
||||||
border-radius: var(--codex-border-radius);
|
|
||||||
border: 1px solid var(--codex-border-color);
|
|
||||||
padding: 1em 2rem;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-info {
|
|
||||||
flex-grow: 1;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-actions {
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-action-close {
|
|
||||||
color: var(--codex-color);
|
|
||||||
border: 1px solid var(--codex-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-action-confirm {
|
|
||||||
color: var(--codex-color-primary);
|
|
||||||
border: 1px solid var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar {
|
|
||||||
flex-grow: 1;
|
|
||||||
background-color: var(
|
|
||||||
--codex-upload-background,
|
|
||||||
var(--codex-background-secondary)
|
|
||||||
);
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
border: none;
|
|
||||||
border-radius: var(--codex-border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar {
|
|
||||||
height: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar[value]::-webkit-progress-bar {
|
|
||||||
background-color: var(--codex-background-light);
|
|
||||||
border-radius: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar[value]::-webkit-progress-value {
|
|
||||||
background: var(--codex-color-primary);
|
|
||||||
border-radius: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar[value]::-moz-progress-bar {
|
|
||||||
border-radius: 50px;
|
|
||||||
background: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar[aria-invalid]::-moz-progress-bar {
|
|
||||||
background: rgb(var(--codex-color-error));
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBar[aria-invalid]::-webkit-progress-value {
|
|
||||||
background: rgb(var(--codex-color-error));
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-filename {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 150px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBarPercent {
|
|
||||||
white-space: nowrap;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-message {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-progress-check {
|
|
||||||
color: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-progress-cancelled {
|
|
||||||
color: rgb(var(--codex-color-error));
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-preview {
|
|
||||||
border-radius: var(--codex-border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-infoLeft {
|
|
||||||
gap: 0.5rem;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progress {
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progress {
|
|
||||||
margin: 0.25 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-infoRight,
|
|
||||||
.uploadFile-progress,
|
|
||||||
.upload,
|
|
||||||
.uploadFile-info,
|
|
||||||
.uploadFile-infoLeft,
|
|
||||||
.uploadFile-name {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-name[aria-invalid] {
|
p {
|
||||||
color: rgb(var(--codex-color-error));
|
margin-bottom: 0;
|
||||||
}
|
margin-top: 12px;
|
||||||
|
line-height: 4px;
|
||||||
|
|
||||||
.uploadFile-name[data-done] {
|
span {
|
||||||
color: var(--codex-color-primary);
|
color: var(--codex-color-primary);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.uploadFile-infoText {
|
small {
|
||||||
flex-grow: 1;
|
color: var(--codex-input-label-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.uploadFile-infoRight {
|
input + span {
|
||||||
justify-content: space-around;
|
color: var(--codex-color-warning);
|
||||||
gap: 0.25rem;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-progressBarPercent,
|
|
||||||
.uploadFile-right {
|
|
||||||
width: 5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-cid {
|
|
||||||
transition: color 0.35s;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadFile-cid:hover {
|
|
||||||
color: var(--codex-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-warning {
|
|
||||||
border-color: rgb(var(--codex-color-warning));
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-text {
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ export { Button } from "./components/Button/Button";
|
||||||
export { ButtonIcon } from "./components/ButtonIcon/ButtonIcon";
|
export { ButtonIcon } from "./components/ButtonIcon/ButtonIcon";
|
||||||
export { Input } from "./components/Input/Input";
|
export { Input } from "./components/Input/Input";
|
||||||
export { InputGroup } from "./components/InputGroup/InputGroup";
|
export { InputGroup } from "./components/InputGroup/InputGroup";
|
||||||
export { SimpleText } from "./components/SimpleText/SimpleText";
|
|
||||||
export { Upload } from "./components/Upload/Upload";
|
export { Upload } from "./components/Upload/Upload";
|
||||||
export { Card } from "./components/Card/Card";
|
export { Card } from "./components/Card/Card";
|
||||||
export { Select } from "./components/Select/Select";
|
export { Select } from "./components/Select/Select";
|
||||||
|
@ -16,10 +15,7 @@ export { Spinner } from "./components/Spinner/Spinner";
|
||||||
export { WebFileIcon } from "./components/WebFileIcon/WebFileIcon";
|
export { WebFileIcon } from "./components/WebFileIcon/WebFileIcon";
|
||||||
export { Stepper } from "./components/Stepper/Stepper";
|
export { Stepper } from "./components/Stepper/Stepper";
|
||||||
export { Backdrop } from "./components/Backdrop/Backdrop";
|
export { Backdrop } from "./components/Backdrop/Backdrop";
|
||||||
export { Cell, type CellProps } from "./components/Table/Cell";
|
export * from "./components/Table/Table";
|
||||||
export { Table, type TabSortState } from "./components/Table/Table";
|
|
||||||
export { Row, type RowProps } from "./components/Table/Row";
|
|
||||||
export { NetworkIndicator } from "./components/NetworkIndicator/NetworkIndicator";
|
|
||||||
export { Tooltip } from "./components/Tooltip/Tooltip";
|
export { Tooltip } from "./components/Tooltip/Tooltip";
|
||||||
export { Collapse } from "./components/Collapse/Collapse";
|
export { Collapse } from "./components/Collapse/Collapse";
|
||||||
export { Placeholder } from "./components/Placeholder/Placeholder";
|
export { Placeholder } from "./components/Placeholder/Placeholder";
|
||||||
|
|
|
@ -65,7 +65,12 @@ const ActionTemplate = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: "6rem" }}>
|
<div style={{ padding: "6rem" }}>
|
||||||
<button onClick={onOpen}>Make Modal</button>
|
<button onClick={onOpen}>Make Modal</button>
|
||||||
<Modal onClose={onClose} open={open} onAction={onAction}>
|
<Modal
|
||||||
|
onClose={onClose}
|
||||||
|
open={open}
|
||||||
|
onAction={onAction}
|
||||||
|
displayActionButton={true}
|
||||||
|
>
|
||||||
<p>Hello world</p>
|
<p>Hello world</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
import type { Meta, StoryObj } from "@storybook/react";
|
|
||||||
import { NetworkIndicator } from "../src/components/NetworkIndicator/NetworkIndicator";
|
|
||||||
|
|
||||||
const meta = {
|
|
||||||
title: "Components/NetworkIndicator",
|
|
||||||
component: NetworkIndicator,
|
|
||||||
parameters: {
|
|
||||||
layout: "centered",
|
|
||||||
},
|
|
||||||
tags: ["autodocs"],
|
|
||||||
argTypes: {},
|
|
||||||
} satisfies Meta<typeof NetworkIndicator>;
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
type Story = StoryObj<typeof meta>;
|
|
||||||
|
|
||||||
export const Online: Story = {
|
|
||||||
args: {
|
|
||||||
online: true,
|
|
||||||
text: "Online",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Offline: Story = {
|
|
||||||
args: {
|
|
||||||
online: false,
|
|
||||||
text: "Offline",
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -20,14 +20,17 @@ export const Default: Story = {
|
||||||
{
|
{
|
||||||
title: "Space allocated",
|
title: "Space allocated",
|
||||||
size: 10000000,
|
size: 10000000,
|
||||||
|
color: "red"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "New space allocation",
|
title: "New space allocation",
|
||||||
size: 10000000 * 0.2,
|
size: 10000000 * 0.2,
|
||||||
|
color: "yellow"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Remaining space",
|
title: "Remaining space",
|
||||||
size: 10000000 * 0.2,
|
size: 10000000 * 0.2,
|
||||||
|
color: "green"
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import type { Meta, StoryObj } from "@storybook/react";
|
import type { Meta, StoryObj } from "@storybook/react";
|
||||||
import { Table } from "../src/components/Table/Table";
|
import { Table, Row } from "../src/components/Table/Table";
|
||||||
import "./Table.stories.css";
|
import "./Table.stories.css";
|
||||||
import { Row } from "../src/components/Table/Row";
|
|
||||||
import { Cell } from "../src";
|
import { Cell } from "../src";
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
|
|
Loading…
Reference in New Issue