diff --git a/package-lock.json b/package-lock.json index e55a564..682f2d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@codex-storage/marketplace-ui-components", - "version": "0.0.27", + "version": "0.0.28", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@codex-storage/marketplace-ui-components", - "version": "0.0.27", + "version": "0.0.28", "license": "MIT", "dependencies": { "lucide-react": "^0.453.0" @@ -41,6 +41,7 @@ }, "peerDependencies": { "@codex-storage/sdk-js": ">=0.0.12", + "postcss-nesting": "^13.0.1", "react": "^18.3.1", "react-dom": "^18.3.1" } @@ -628,6 +629,50 @@ "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": { "version": "0.23.1", "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==", "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": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -5558,7 +5615,6 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -5824,8 +5880,7 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -5939,7 +5994,6 @@ "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5964,6 +6018,46 @@ "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": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6673,7 +6767,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7134,8 +7227,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", diff --git a/package.json b/package.json index 43dfcdb..5c8b122 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "git", "url": "https://github.com/codex-storage/codex-marketplace-ui-components" }, - "version": "0.0.27", + "version": "0.0.28", "type": "module", "scripts": { "prepack": "npm run build", @@ -37,7 +37,8 @@ "peerDependencies": { "@codex-storage/sdk-js": ">=0.0.12", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "postcss-nesting": "^13.0.1" }, "devDependencies": { "@chromatic-com/storybook": "^2.0.2", diff --git a/src/components/Alert/Alert.tsx b/src/components/Alert/Alert.tsx index 1a1c17c..caebbf8 100644 --- a/src/components/Alert/Alert.tsx +++ b/src/components/Alert/Alert.tsx @@ -1,12 +1,5 @@ import "./alert.css"; -import { CSSProperties, ReactNode } from "react"; - -interface CustomStyleCSS extends CSSProperties { - "--codex-border-radius"?: string; - "--codex-color-primary"?: string; - "--codex-color-warning"?: string; - "--codex-font-family"?: string; -} +import { ReactNode } from "react"; type Props = { variant: "success" | "warning" | "toast"; @@ -20,21 +13,11 @@ type Props = { */ className?: string; - /** - * Apply custom css variables. - * --codex-border-radius - * --codex-color-primary: string; - * --codex-color-warning - * --codex-font-family - */ - style?: CustomStyleCSS; - Icon?: ReactNode; }; export function Alert({ variant, - style, title, Icon, children, @@ -42,20 +25,16 @@ export function Alert({ ...rest }: Props) { return ( -
+
{Icon && ( - - {Icon} + + {Icon} )} -
- {title} -
{children}
+
+ {title} +
{children}
); diff --git a/src/components/Alert/alert.css b/src/components/Alert/alert.css index eba4d9e..cec483e 100644 --- a/src/components/Alert/alert.css +++ b/src/components/Alert/alert.css @@ -9,34 +9,34 @@ word-break: break-word; display: flex; gap: 1rem; -} -.alert-icon { - display: flex; - width: 1rem; - color: rgb(var(--codex-alert-color)); -} + b { + text-transform: capitalize; + margin-bottom: 0.25rem; + display: inline-block; + } -.alert-circleIcon { - background: rgba(var(--codex-alert-color), 0.2); - border-radius: 75px; - height: 1.75rem; - min-width: 1.75rem; - display: flex; - justify-content: center; - align-items: center; -} + span { + background: rgba(var(--codex-alert-color), 0.2); + border-radius: 75px; + height: 1.75rem; + min-width: 1.75rem; + display: flex; + justify-content: center; + align-items: center; -.alert-title { - text-transform: capitalize; - margin-bottom: 0.25rem; - display: inline-block; -} + span { + display: flex; + width: 1rem; + color: rgb(var(--codex-alert-color)); + } + } -.alert--success { - --codex-alert-color: var(--codex-color-success); -} + &.alert--success { + --codex-alert-color: var(--codex-color-success); + } -.alert--warning { - --codex-alert-color: var(--codex-color-warning); + &.alert--warning { + --codex-alert-color: var(--codex-color-warning); + } } diff --git a/src/components/Backdrop/backdrop.css b/src/components/Backdrop/backdrop.css index 3c73896..ce1a4d7 100644 --- a/src/components/Backdrop/backdrop.css +++ b/src/components/Backdrop/backdrop.css @@ -10,11 +10,11 @@ backdrop-filter: blur(2px); display: block; z-index: -1; -} -.backdrop[aria-expanded] { - z-index: 10; - opacity: 1; + &[aria-expanded] { + z-index: 10; + opacity: 1; + } } .document-noOverflow { diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 0cae94d..d0abf96 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -1,20 +1,7 @@ -import { ComponentType, CSSProperties } from "react"; +import { ComponentType } from "react"; import "./button.css"; 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 = { /** * Button style variant. Default is primary. @@ -50,21 +37,6 @@ type Props = { * Apply custom classname. */ 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({ @@ -75,7 +47,6 @@ export function Button({ onMouseLeave, fetching = false, disabled = false, - style, variant = "primary", onClick, }: Props) { @@ -84,7 +55,6 @@ export function Button({ onClick={onClick} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} - style={style} className={`button ${className} button--${variant}`} {...attributes({ disabled: disabled || fetching, @@ -93,11 +63,11 @@ export function Button({ })} > {Icon && ( -
+
)} - {label} + {label} ); } diff --git a/src/components/Button/button.css b/src/components/Button/button.css index 986d9bc..44c42cd 100644 --- a/src/components/Button/button.css +++ b/src/components/Button/button.css @@ -14,84 +14,84 @@ font-family: var(--codex-font-family); border: 1px solid transparent; place-content: center; -} - -.button--primary { - background-color: var(--codex-color-primary); - color: var(--codex-color-on-primary); -} - -.button:disabled { - cursor: not-allowed; -} - -.button--primary:disabled { - background-color: var(--codex-color-disabled); -} - -.button--outline:disabled { - color: var(--codex-color-disabled); -} - -.button-label { - display: flex; - align-items: center; - gap: 0.75rem; -} - -.button--outline { - color: var(--codex-color-outline, var(--codex-color-contrast)); - border-color: var(--codex-border-color); - border-width: 1px; - border-style: solid; - background-color: transparent; -} - -.button[aria-busy] { - cursor: wait; -} - -.button-icon { - width: 16px; - height: 16px; - display: flex; - place-items: center; -} - -.button[aria-busy]::after { - content: " "; - display: block; - background-image: var( - --codex-button-loader, - url('data:image/svg+xml,') - ); - position: absolute; - background-color: var( - --codex-button-background-busy, - var(--codex-background-backdrop) - ); - - /** - * Set full size and add border. - */ - width: calc(100% + 2px); - height: calc(100% + 2px); - - background-repeat: no-repeat; - background-position: center; - background-size: 28px; - left: -1px; - right: 0; - border-radius: var(--codex-border-radius); -} - -.button--primary:not(:disabled):hover { - cursor: pointer; - box-shadow: 0 0 0 3px - var(--codex-button-color-box-shadow, var(--codex-color-primary-variant)); -} - -.button--outline:not(:disabled):hover { - cursor: pointer; - box-shadow: 0 0 0 2px var(--codex-border-color); + + &[aria-busy] { + cursor: wait; + } + + &[aria-busy]::after { + content: " "; + display: block; + background-image: var( + --codex-button-loader, + url('data:image/svg+xml,') + ); + position: absolute; + background-color: var( + --codex-button-background-busy, + var(--codex-background-backdrop) + ); + + /** + * Set full size and add border. + */ + width: calc(100% + 2px); + height: calc(100% + 2px); + + background-repeat: no-repeat; + background-position: center; + background-size: 28px; + left: -1px; + right: 0; + border-radius: var(--codex-border-radius); + } + + &.button--primary:not(:disabled):hover { + cursor: pointer; + box-shadow: 0 0 0 3px + var(--codex-button-color-box-shadow, var(--codex-color-primary-variant)); + } + + &.button--outline:not(:disabled):hover { + cursor: pointer; + box-shadow: 0 0 0 2px var(--codex-border-color); + } + + &.button--primary { + background-color: var(--codex-color-primary); + color: var(--codex-color-on-primary); + } + + &:disabled { + cursor: not-allowed; + } + + &.button--primary:disabled { + background-color: var(--codex-color-disabled); + } + + &.button--outline:disabled { + color: var(--codex-color-disabled); + } + + &.button--outline { + color: var(--codex-color-outline, var(--codex-color-contrast)); + border-color: var(--codex-border-color); + border-width: 1px; + border-style: solid; + background-color: transparent; + } + + span { + display: flex; + align-items: center; + gap: 0.75rem; + } + + div { + width: 16px; + height: 16px; + display: flex; + place-items: center; + } } diff --git a/src/components/ButtonIcon/ButtonIcon.tsx b/src/components/ButtonIcon/ButtonIcon.tsx index 04a866c..0a8b08f 100644 --- a/src/components/ButtonIcon/ButtonIcon.tsx +++ b/src/components/ButtonIcon/ButtonIcon.tsx @@ -1,18 +1,7 @@ -import { - AnimationEventHandler, - ComponentType, - CSSProperties, - useState, -} from "react"; +import { AnimationEventHandler, ComponentType, useState } from "react"; import "./buttonIcon.css"; import { attributes } from "../utils/attributes"; -interface CustomStyleCSS extends CSSProperties { - "--codex-button-icon-background"?: string; - "--codex-border-color"?: string; - "--codex-color-disabled"?: string; -} - type Props = { Icon: ComponentType<{ className?: string; @@ -29,14 +18,6 @@ type Props = { disabled?: boolean; - /** - * Apply custom css variables. - * --codex-button-icon-background - * --codex-border-color - * --codex-color-disabled - */ - style?: CustomStyleCSS; - /** * Apply custom classname. */ @@ -51,7 +32,6 @@ type Props = { export function ButtonIcon({ Icon, onClick, - style, onMouseEnter, onMouseLeave, className = "", @@ -74,7 +54,6 @@ export function ButtonIcon({ onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={onInternalClick} - style={style} {...attributes({ disabled: disabled, "aria-disabled": disabled })} > diff --git a/src/components/ButtonIcon/buttonIcon.css b/src/components/ButtonIcon/buttonIcon.css index 52580be..88ec7b0 100644 --- a/src/components/ButtonIcon/buttonIcon.css +++ b/src/components/ButtonIcon/buttonIcon.css @@ -10,41 +10,52 @@ cursor: pointer; transition: box-shadow 0.35s; border: none; -} -.buttonIcon--big { - width: 4rem; - height: 4rem; -} + &.buttonIcon--big { + width: 4rem; + height: 4rem; + } -.buttonIcon--small { - width: 2rem; - height: 2rem; -} + &.buttonIcon--small { + width: 2rem; + height: 2rem; + } -.buttonIcon svg { - mix-blend-mode: difference; -} + &:not(:disabled):hover { + cursor: pointer; + box-shadow: 0 0 0 2px var(--codex-border-color); + } -.buttonIcon:not(:disabled):hover { - cursor: pointer; - box-shadow: 0 0 0 2px var(--codex-border-color); -} + &:disabled { + color: var(--codex-color-disabled); + cursor: not-allowed; + } -.buttonIcon:disabled { - color: var(--codex-color-disabled); - cursor: not-allowed; -} + &.buttonIcon--buzz { + -webkit-animation-name: buzz; + 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 { - -webkit-animation-name: buzz; - 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--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; + } + + svg { + mix-blend-mode: difference; + } } @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 { 0% { -webkit-transform: translateY(0) scale(1); diff --git a/src/components/Card/Card.tsx b/src/components/Card/Card.tsx index 613b7cf..0d5cb6f 100644 --- a/src/components/Card/Card.tsx +++ b/src/components/Card/Card.tsx @@ -1,33 +1,19 @@ -import { CSSProperties, ReactNode } from "react"; +import { ReactNode } from "react"; import "./card.css"; -interface CustomStyleCSS extends CSSProperties { - "--codex-border-radius"?: string; - "--codex-border-color"?: string; - "--codex-font-family"?: string; -} - type Props = { children: ReactNode; className?: 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 ( -
-
{title}
-
{children}
+
+
{title}
+
{children}
); } diff --git a/src/components/Card/card.css b/src/components/Card/card.css index 52485f3..a1f3302 100644 --- a/src/components/Card/card.css +++ b/src/components/Card/card.css @@ -3,15 +3,15 @@ border: 1px solid var(--codex-border-color); font-family: var(--codex-font-family); background-color: var(--codex-background-secondary); -} -.card-header { - border-bottom: 1px solid var(--codex-border-color); - padding: 1rem 1.5rem; - font-size: 1.15rem; - font-weight: bold; -} + header { + border-bottom: 1px solid var(--codex-border-color); + padding: 1rem 1.5rem; + font-size: 1.15rem; + font-weight: bold; + } -.card-body { - padding: 1.5rem; + div { + padding: 1.5rem; + } } diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index f367c4f..fcd3a50 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -8,15 +8,9 @@ import { import "./dropdown.css"; import { attributes } from "../utils/attributes"; import { Backdrop } from "../Backdrop/Backdrop"; -import { Input, InputCustomStyleCSS } from "../Input/Input"; +import { Input } from "../Input/Input"; 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 = { /** * Dropdown option icon displayed on the left @@ -70,14 +64,6 @@ type Props = { onMouseLeave?: () => void; - /** - * Apply custom css variables. - * --codex-dropdown-panel-background - * --codex-dropdown-border - * --codex-dropdown-option-background-hover - */ - style?: CustomStyleCSS; - label: string; id: string; @@ -85,7 +71,6 @@ type Props = { export function Dropdown({ placeholder, - style, options, label, id, @@ -134,12 +119,10 @@ export function Dropdown({ const attr = attributes({ "aria-expanded": focused }); return ( - <> - +
+ -
+
-
+
    {filtered.length ? ( filtered.map((o) => ( -
    onSelect(o)} - key={o.title} - > +
  • onSelect(o)} key={o.title}> {o.Icon && } -
    - {o.title} - {o.subtitle && ( - {o.subtitle} - )} -
    -
  • + {o.title} + {o.subtitle && {o.subtitle}} + )) ) : ( -

    No results found

    +

    No results found

    )} -
+
- +
); } diff --git a/src/components/Dropdown/dropdown.css b/src/components/Dropdown/dropdown.css index fe200d8..87db971 100644 --- a/src/components/Dropdown/dropdown.css +++ b/src/components/Dropdown/dropdown.css @@ -1,85 +1,83 @@ .dropdown { - position: relative; -} + label { + margin-bottom: 0.5rem; + font-weight: 500; + display: block; + color: var(--codex-color); + } -.dropdown-panel { - position: absolute; - 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; -} + > div { + position: relative; + } -.dropdown-label { - margin-bottom: 0.5rem; - font-weight: 500; - display: block; - color: var(--codex-color); -} + ul { + position: absolute; + 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-panel[aria-expanded] { - transform: translateY(0.5rem); - opacity: 1; - z-index: 10; -} + &[aria-expanded] { + transform: translateY(0rem); + opacity: 1; + z-index: 10; + } -.dropdown-input { - 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; -} + li { + padding: 0.5rem; + border-radius: var(--codex-border-radius); + transition: background-color 0.35s; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.75rem; -.dropdown-input:focus { - z-index: 11; -} + &:hover { + background-color: var( + --codex-dropdown-option-background-hover, + var(--codex-background-light) + ); + } -.dropdown-option { - padding: 0.5rem; - border-radius: var(--codex-border-radius); - transition: background-color 0.35s; - cursor: pointer; - display: flex; - align-items: center; - gap: 0.75rem; -} + span { + display: block; + word-break: break-all; + } -.dropdown-option:hover { - background-color: var( - --codex-dropdown-option-background-hover, - var(--codex-background-light) - ); -} + span + span { + mix-blend-mode: difference; + font-size: 0.75rem; + } + } + } -.dropdown-noResults { - padding: 0.75rem 0.25rem; -} + .input { + 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 { - display: block; -} + &:focus { + z-index: 11; + } + } -.dropdown-subtitle { - mix-blend-mode: difference; - font-size: 0.75rem; -} - -.dropdown-title, -.dropdown-subtitle { - word-break: break-all; + p { + padding: 0.75rem 0.25rem; + } } diff --git a/src/components/Failure/Failure.tsx b/src/components/Failure/Failure.tsx index ed0b9df..43f6a20 100644 --- a/src/components/Failure/Failure.tsx +++ b/src/components/Failure/Failure.tsx @@ -1,12 +1,5 @@ import "./failure.css"; 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 = { /** @@ -29,14 +22,6 @@ type Props = { * The button label */ button?: string; - - /** - * Apply custom css variables. - * --codex-code-font-size - * --codex-text-contrast - * --codex-font-family - */ - style?: CustomStyleCSS; }; export function Failure({ @@ -48,9 +33,9 @@ export function Failure({ }: Props) { return (
-

{code}

-

{title}

-
{message}
+

{code}

+

{title}

+
{message}
{onClick &&
); diff --git a/src/components/Failure/failure.css b/src/components/Failure/failure.css index 121a9cc..b53fb62 100644 --- a/src/components/Failure/failure.css +++ b/src/components/Failure/failure.css @@ -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 { display: flex; align-items: center; justify-content: center; flex-direction: column; flex: 1; -} -.failure-title { - font-size: 1.875rem; - line-height: 2.25rem; - font-weight: 600; - margin: 0.75rem 0; - color: var(--codex-text-contrast); -} + h1 { + 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-message { - margin-bottom: 0.75rem; - mix-blend-mode: difference; + h2 { + font-size: 1.875rem; + 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; + } } diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 3b70769..902b6f3 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -1,7 +1,6 @@ import { ChangeEvent, ComponentType, - CSSProperties, forwardRef, InputHTMLAttributes, useState, @@ -9,16 +8,6 @@ import { import { attributes } from "../utils/attributes"; import { classnames } from "../utils/classnames"; 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 = { id: string; @@ -80,54 +69,39 @@ export const Input = forwardRef( }; return ( - <> - {label && ( - +
+ {label && } -
+
{Icon && ( -
+
)}
- {helper && ( -
- - {helper} - -
- )} - + {helper && {helper}} +
); } ); diff --git a/src/components/Input/input.css b/src/components/Input/input.css index 24db102..a5854f5 100644 --- a/src/components/Input/input.css +++ b/src/components/Input/input.css @@ -1,105 +1,71 @@ .input { - background-color: var(--codex-input-background); - color: white; - border-radius: var(--codex-border-radius); - border: 1px solid var(--codex-input-border-color); - padding: 16px; - outline: none; - display: inline-block; - box-sizing: border-box; - font-weight: 500; - font-size: 20px; - height: 64px; -} - -.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 { + background-color: var(--codex-input-background); + color: white; + border-radius: var(--codex-border-radius); + border: 1px solid var(--codex-input-border-color); + padding: 16px; + outline: none; + display: inline-block; + box-sizing: border-box; + font-weight: 500; + font-size: 20px; + height: 64px; + position: relative; } -} */ + + &.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); + } +} diff --git a/src/components/InputGroup/InputGroup.tsx b/src/components/InputGroup/InputGroup.tsx index 33bf3ae..1a69670 100644 --- a/src/components/InputGroup/InputGroup.tsx +++ b/src/components/InputGroup/InputGroup.tsx @@ -1,13 +1,8 @@ -import { ChangeEvent, CSSProperties, LegacyRef, ReactNode } from "react"; +import { ChangeEvent, LegacyRef, ReactNode } from "react"; import "./inputGroup.css"; import { Input } from "../Input/Input"; import { Select } from "../Select/Select"; -export interface CustomStyleCSS extends CSSProperties { - "--codex-border-radius"?: string; - "--codex-border-color"?: string; -} - type Props = { label: string; @@ -63,13 +58,6 @@ type Props = { step?: string; - /** - * Apply custom css variables. - * --codex-border-radius - * --codex-border-color - */ - style?: CustomStyleCSS; - name?: string; /** @@ -91,7 +79,6 @@ export function InputGroup({ name, helper, type = "text", - style, group, className = "", inputClassName = "", @@ -111,17 +98,17 @@ export function InputGroup({ extra, }: Props) { return ( -
-
-
-
+
+
+
+
-
- - {helper && {helper}} - +

+ {helper && {helper}} {extra} -

+

); diff --git a/src/components/InputGroup/inputGroup.css b/src/components/InputGroup/inputGroup.css index b62d169..804fa78 100644 --- a/src/components/InputGroup/inputGroup.css +++ b/src/components/InputGroup/inputGroup.css @@ -1,45 +1,48 @@ -.inputGroup-element { - display: flex; - align-items: flex-end; -} +.input-group { + > div { + flex-grow: 1; -.inputGroup-container { - flex-grow: 1; -} + > div { + display: flex; + align-items: flex-end; -.inputGroup-helper { - height: 15px; - display: inline-block; -} + > div:first-child { + flex: 1; -input.inputGroup-input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - border-right: none; -} + input { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: none; + } -select.inputGroup-select { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - min-width: 110px; -} + select { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + min-width: 110px; + } + } -.inputGroup-unit { - display: flex; - align-items: center; - border: 1px solid var(--codex-border-color); - border-top-right-radius: var(--codex-border-radius); - border-bottom-right-radius: var(--codex-border-radius); - background-color: var(--codex-border-color); - padding: calc(0.5rem + 0.5px); -} + > div:nth-child(2) { + display: flex; + align-items: center; + border: 1px solid var(--codex-border-color); + border-top-right-radius: var(--codex-border-radius); + border-bottom-right-radius: var(--codex-border-radius); + background-color: var(--codex-border-color); + padding: calc(0.5rem + 0.5px); + } + } + } -.inputGroup-inputContainer { - flex: 1; -} + p { + display: flex; + justify-content: space-between; + align-items: center; + max-width: 0; -.inputGroup-helpers { - display: flex; - justify-content: space-between; - align-items: center; + small { + height: 15px; + display: inline-block; + } + } } diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index 3d3a61b..3c93922 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -53,6 +53,8 @@ type Props = { disableActionButton?: boolean; children: ReactNode; + + className?: string; }; export function Modal({ @@ -60,6 +62,7 @@ export function Modal({ onClose, disableActionButton, disableCloseButton, + className = "", displayCloseButton = true, displayActionButton = false, labelActionButton = "Action", @@ -79,24 +82,21 @@ export function Modal({ }; return ( - <> +
-
-
{open && children}
+ +
{open && children}
-
+
{displayCloseButton && (
-
- + + +
); } diff --git a/src/components/Modal/modal.css b/src/components/Modal/modal.css index 76c5fc7..3105790 100644 --- a/src/components/Modal/modal.css +++ b/src/components/Modal/modal.css @@ -1,64 +1,55 @@ .modal { - transition: - transform 0.25s, - opacity 0.25s; - max-width: 800px; - overflow-y: auto; - overflow-x: hidden; - opacity: 0; - z-index: -1; - max-height: 100%; - left: 50%; - top: 50%; - transform: translateX(-50%); - position: fixed; - display: flex; - flex-direction: column; - background-color: var(--codex-background); - padding: 1.5rem; - border-radius: var(--codex-border-radius); -} - -.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 { + dialog { + transition: + transform 0.25s, + opacity 0.25s; + max-width: 800px; + overflow-y: auto; + overflow-x: hidden; + opacity: 0; + z-index: -1; + max-height: 100%; + left: 50%; + top: 50%; + transform: translateX(-50%); + position: fixed; + display: flex; + flex-direction: column; + background-color: var(--codex-background); + padding: 1.5rem; + border-radius: var(--codex-border-radius); + border: none; 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; } } diff --git a/src/components/NetworkIndicator/NetworkIndicator.tsx b/src/components/NetworkIndicator/NetworkIndicator.tsx deleted file mode 100644 index bb16589..0000000 --- a/src/components/NetworkIndicator/NetworkIndicator.tsx +++ /dev/null @@ -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 ( -
-
- {text} -
- ); -} diff --git a/src/components/NetworkIndicator/networkIndicator.css b/src/components/NetworkIndicator/networkIndicator.css deleted file mode 100644 index 46fc428..0000000 --- a/src/components/NetworkIndicator/networkIndicator.css +++ /dev/null @@ -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; - } -} diff --git a/src/components/Placeholder/Placeholder.tsx b/src/components/Placeholder/Placeholder.tsx index b4b2cd6..db89cd7 100644 --- a/src/components/Placeholder/Placeholder.tsx +++ b/src/components/Placeholder/Placeholder.tsx @@ -1,7 +1,6 @@ import { ReactNode } from "react"; import { Button } from "../Button/Button"; import "./placeholder.css"; -import { SimpleText } from "../SimpleText/SimpleText"; type Props = { title: string; @@ -35,14 +34,10 @@ export function Placeholder({ }: Props) { return (
-
{Icon}
- {title} +
{Icon}
+ {title} - {subtitle && ( -
- {subtitle} -
- )} + {subtitle &&

subtitle

}
{message}
diff --git a/src/components/Placeholder/placeholder.css b/src/components/Placeholder/placeholder.css index 3554d9c..f7af078 100644 --- a/src/components/Placeholder/placeholder.css +++ b/src/components/Placeholder/placeholder.css @@ -1,24 +1,25 @@ .placeholder { text-align: center; margin: auto; -} -.placeholder-icon { - display: block; - margin: auto auto 0.75rem; -} + > div:first-child { + display: block; + margin: auto auto 0.75rem; + } -.placeholder-title { - margin-bottom: 0.25rem; - display: inline-block; -} + b { + margin-bottom: 0.25rem; + display: inline-block; + } -.placeholder-subtitle { - margin-bottom: 0.25rem; - max-width: 600px; - margin: auto; -} + p { + margin-bottom: 0.25rem; + max-width: 600px; + margin: auto; + color: var(--codex-input-label-color); + } -.placeholder-button { - margin: 0.75rem auto 0; + .button { + margin: 0.75rem auto 0; + } } diff --git a/src/components/Select/Select.tsx b/src/components/Select/Select.tsx index 653e31a..d84c641 100644 --- a/src/components/Select/Select.tsx +++ b/src/components/Select/Select.tsx @@ -1,14 +1,6 @@ -import { ChangeEvent, CSSProperties } from "react"; +import { ChangeEvent } from "react"; 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 = { label: string; @@ -33,11 +25,6 @@ type Props = { onMouseLeave?: () => void; - /** - * Apply custom css variables. - */ - style?: CustomStyleCSS; - defaultValue?: string; value: string; @@ -54,36 +41,29 @@ export function Select({ onFocus, onMouseEnter, onMouseLeave, - style, className = "", defaultValue, value, }: Props) { return ( - <> - -
- -
- +
+ + +
); } diff --git a/src/components/Select/select.css b/src/components/Select/select.css index bcd8918..6be3916 100644 --- a/src/components/Select/select.css +++ b/src/components/Select/select.css @@ -1,44 +1,46 @@ .select { - appearance: none; - -moz-appearance: none; - -webkit-appearance: none; - background-color: var( - --codex-select-background, - var(--codex-background-secondary) - ); - outline: 2px solid transparent; - outline-offset: 2px; - color: var(--codex-color); - border-radius: var(--codex-border-radius); - padding: 0.75rem 1rem; - padding-inline-end: 2.25rem; - transition: box-shadow 0.35s; - border: var(--codex-select-border, 1px solid var(--codex-border-color)); - background-image: var( - --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-size: 1.25em 1.25em; - box-sizing: border-box; -} + select { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + background-color: var( + --codex-select-background, + var(--codex-background-secondary) + ); + outline: 2px solid transparent; + outline-offset: 2px; + color: var(--codex-color); + border-radius: var(--codex-border-radius); + padding: 0.75rem 1rem; + padding-inline-end: 2.25rem; + transition: box-shadow 0.35s; + border: var(--codex-select-border, 1px solid var(--codex-border-color)); + background-image: var( + --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-size: 1.25em 1.25em; + box-sizing: border-box; -.select:hover, -.select:focus-visible, -.select:active { - box-shadow: 0 0 0 1px var(--codex-border-color); -} + @media (min-width: 801px) { + & { + min-width: 20rem; + } + } -.select-label { - margin-bottom: 0.5rem; - font-weight: 500; - display: block; - color: var(--codex-color); -} + &:hover, + &:focus-visible, + &:active { + box-shadow: 0 0 0 1px var(--codex-border-color); + } + } -@media (min-width: 801px) { - .select { - min-width: 20rem; + label { + margin-bottom: 0.5rem; + font-weight: 500; + display: block; + color: var(--codex-color); } } diff --git a/src/components/Sheets/Sheets.tsx b/src/components/Sheets/Sheets.tsx index dfcf741..cd0a962 100644 --- a/src/components/Sheets/Sheets.tsx +++ b/src/components/Sheets/Sheets.tsx @@ -16,17 +16,10 @@ export function Sheets({ open, onClose, children }: Props) { const attr = attributes({ "aria-expanded": open }); return ( -
- +
+ -
- {children} -
+
); } diff --git a/src/components/Sheets/sheets.css b/src/components/Sheets/sheets.css index 789cd9f..8bc1ca9 100644 --- a/src/components/Sheets/sheets.css +++ b/src/components/Sheets/sheets.css @@ -1,57 +1,53 @@ .sheets { - position: fixed; - transition: transform 0.25s; - background-color: var(--codex-background-secondary); - z-index: 2; - justify-content: space-between; -} - -.sheets-container { overflow: hidden; width: 100%; height: 100%; left: 0; top: 0; z-index: -1; -} -.sheets-container--open { - 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--open { + z-index: 2; } - .sheets[aria-expanded] { - transform: translatex(0); - z-index: 10; - } -} - -@media (max-width: 999px) { - .sheets { - width: 100%; - height: auto; - bottom: 0; - top: auto; - transform: translatey(1300px); - left: 0; - padding-bottom: 1.5rem; - } - - .sheets[aria-expanded] { - transform: translatey(0); - z-index: 10; + aside { + position: fixed; + transition: transform 0.25s; + background-color: var(--codex-background-secondary); + z-index: 2; + justify-content: space-between; + + @media (min-width: 1000px) { + & { + width: 300px; + height: 100%; + bottom: 0; + top: 0; + transform: translatex(1300px); + right: 0; + } + + &[aria-expanded] { + transform: translatex(0); + 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; + } + } } } diff --git a/src/components/SimpleText/SimpleText.tsx b/src/components/SimpleText/SimpleText.tsx deleted file mode 100644 index 8d83d58..0000000 --- a/src/components/SimpleText/SimpleText.tsx +++ /dev/null @@ -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 ( - - {children} - - ); - } - - return ( - - {children} - - ); -} diff --git a/src/components/SimpleText/simpleText.css b/src/components/SimpleText/simpleText.css deleted file mode 100644 index 1ff4587..0000000 --- a/src/components/SimpleText/simpleText.css +++ /dev/null @@ -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; -} diff --git a/src/components/SpaceAllocation/SpaceAllocation.tsx b/src/components/SpaceAllocation/SpaceAllocation.tsx index 3471538..edcdf20 100644 --- a/src/components/SpaceAllocation/SpaceAllocation.tsx +++ b/src/components/SpaceAllocation/SpaceAllocation.tsx @@ -1,4 +1,3 @@ -import { SimpleText } from "../SimpleText/SimpleText"; import { PrettyBytes } from "../utils/bytes"; import "./spaceAllocation.css"; @@ -25,36 +24,31 @@ export function SpaceAllocation({ data }: Props) { const total = data.reduce((acc, val) => acc + val.size, 0); return ( - <> -
+
+
{data.map((d) => ( ))} -
+ -
+
    {data.map((d) => ( -
    -
    -
    - {d.title} - - {PrettyBytes(d.size)} - -
    -
    +
  • + +

    + {d.title} + {PrettyBytes(d.size)} +

    +
  • ))} -
- + +
); } diff --git a/src/components/SpaceAllocation/spaceAllocation.css b/src/components/SpaceAllocation/spaceAllocation.css index 06a1098..886efbf 100644 --- a/src/components/SpaceAllocation/spaceAllocation.css +++ b/src/components/SpaceAllocation/spaceAllocation.css @@ -1,48 +1,46 @@ -.nodeSpaceAllocation-bar { - height: 10px; - display: flex; - gap: 0.75rem; - margin-bottom: 0.5rem; -} +.space-allocation { + header { + height: 10px; + display: flex; + gap: 0.75rem; + margin-bottom: 0.5rem; -.nodeSpaceAllocation-barQuota { - width: 10%; -} + span { + display: inline-block; + height: 100%; + border-radius: var(--codex-border-radius); + } + } -.nodeSpaceAllocation-barItem { - display: inline-block; - height: 100%; - border-radius: var(--codex-border-radius); -} + ul { + display: flex; + gap: 0.75rem; + flex-wrap: wrap; + padding-left: 0; -.nodeSpaceAllocation-barQuota-used { - border-top-left-radius: var(--codex-border-radius); - border-bottom-left-radius: var(--codex-border-radius); - border-radius: var(--codex-border-radius); -} + li { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; -.nodeSpaceAllocation-legend { - display: flex; - gap: 0.75rem; - flex-wrap: wrap; -} + > span { + width: 1rem; + height: 1rem; + border-radius: var(--codex-border-radius); + } -.nodeSpaceAllocation-legendItem { - width: 1rem; - height: 1rem; - border-radius: var(--codex-border-radius); -} + p { + display: flex; + flex-direction: column; + line-height: 1rem; + margin: 0; + font-size: 12px; -.nodeSpaceAllocation-legendRow { - display: flex; - 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; + small { + color: var(--codex-input-label-color); + } + } + } + } } diff --git a/src/components/Stepper/Step.css b/src/components/Stepper/Step.css new file mode 100644 index 0000000..8b2f116 --- /dev/null +++ b/src/components/Stepper/Step.css @@ -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; + } + } + } +} diff --git a/src/components/Stepper/Step.tsx b/src/components/Stepper/Step.tsx index 6346778..2a557e9 100644 --- a/src/components/Stepper/Step.tsx +++ b/src/components/Stepper/Step.tsx @@ -2,6 +2,7 @@ import { Check } from "lucide-react"; import { useEffect, useRef } from "react"; import { attributes } from "../utils/attributes"; import { classnames } from "../utils/classnames"; +import "./Step.css"; type StepProps = { /** @@ -52,36 +53,22 @@ export function Step({ return (
onClick?.(step)} {...attributes({ disabled: !onClick })} > -
-
- - {isDone ? : step + 1} - -
+
+ {isDone ? : step + 1}
{!isLast && ( -
-
- {title} +
+
+ {title}
)}
diff --git a/src/components/Stepper/Stepper.tsx b/src/components/Stepper/Stepper.tsx index fa67313..cbbf783 100644 --- a/src/components/Stepper/Stepper.tsx +++ b/src/components/Stepper/Stepper.tsx @@ -1,17 +1,10 @@ import { Button } from "../Button/Button"; import "./stepper.css"; -import { CSSProperties, Dispatch, ReactNode } from "react"; +import { Dispatch, ReactNode } from "react"; import { Spinner } from "../Spinner/Spinner"; import { Step } from "./Step"; import { StepperAction, StepperState } from "./useStepperReducer"; - -interface CustomStyleCSS extends CSSProperties { - "--codex-background"?: string; - "--codex-border-radius"?: string; - "--codex-stepper-background": string; - "--codex-color-primary": string; - "--codex-border-color": string; -} +import { classnames } from "../utils/classnames"; type Props = { /** @@ -24,8 +17,6 @@ type Props = { */ children: ReactNode; - style?: CustomStyleCSS; - /** * The duration between steps */ @@ -69,7 +60,6 @@ export function Stepper({ titles, children, state, - style, dispatch, className = "", backLabel = "Back", @@ -95,8 +85,13 @@ export function Stepper({ }; return ( -
-
+
+
{titles.map((title, index) => ( index ? () => onChangeStep(index) : undefined} /> ))} -
+ -
- {state.progress ? ( -
- -
- ) : ( - <>{children} - )} -
+
+ {state.progress ? : <>{children}} +
-
+
+
); } diff --git a/src/components/Stepper/stepper.css b/src/components/Stepper/stepper.css index 33fbdbb..ba6e342 100644 --- a/src/components/Stepper/stepper.css +++ b/src/components/Stepper/stepper.css @@ -3,120 +3,46 @@ flex-direction: column; background-color: var(--codex-background); border-radius: var(--codex-border-radius); -} -.stepper-progress, -.stepper-step-info, -.stepper-steps, -.stepper-step { - display: flex; - align-items: center; - gap: 0.5rem; - transition: opacity 0.35s; -} + header { + display: flex; + align-items: center; + gap: 0.5rem; + transition: opacity 0.35s; + } -.stepper-step:not([disabled]):not(.stepper-separator-active):hover { - cursor: pointer; - opacity: 0.8; -} + main { + 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-number { - width: 1.75rem; - height: 1.75rem; - display: flex; - align-items: center; - justify-content: center; - border-radius: 50%; - transition: background-color 0.35s; -} + @media (min-width: 801px) { + & { + min-width: 500px; + } + } + } -.stepper-number:not(.stepper-number-active):not(.stepper-number-done) { - background-color: var( - --codex-stepper-background, - var(--codex-background-light) - ); -} + &.stepper--progress { + main { + justify-content: center; + flex: 1; + align-items: center; + } + } -.stepper-separator { - height: 1px; - flex: 1; - 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; + footer { + display: flex; + justify-content: space-between; + } } @keyframes step { @@ -138,40 +64,3 @@ 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; - } -} diff --git a/src/components/Table/Cell.tsx b/src/components/Table/Cell.tsx deleted file mode 100644 index 834889f..0000000 --- a/src/components/Table/Cell.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ReactNode } from "react"; -import "./cell.css"; - -export type CellProps = { - children: ReactNode | string; -} & React.DetailedHTMLProps< - React.TdHTMLAttributes, - HTMLTableCellElement ->; - -export const Cell = ({ children, className = "", ...rest }: CellProps) => ( - - {children} - -); diff --git a/src/components/Table/Row.tsx b/src/components/Table/Row.tsx deleted file mode 100644 index a42da0b..0000000 --- a/src/components/Table/Row.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Fragment, ReactElement } from "react"; -import { Cell, CellProps } from "./Cell"; -import "./row.css"; - -export type RowProps = { - cells: ReactElement[]; - className?: string; -}; - -export function Row({ cells, className = "" }: RowProps) { - return ( - - {cells.map((Cell, index) => ( - {Cell} - ))} - - ); -} diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index e6525d4..218fb7c 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -1,8 +1,8 @@ import "./table.css"; import { ArrowDownUp, Search } from "lucide-react"; -import { Row, RowProps } from "./Row"; -import { Fragment, ReactElement, useEffect, useState } from "react"; +import { Fragment, ReactElement, ReactNode, useEffect, useState } from "react"; import { classnames } from "../utils/classnames"; +import { attributes } from "../utils/attributes"; export type TabSortState = "asc" | "desc" | null; @@ -61,10 +61,16 @@ export function Table({ }; return ( -
- - - +
+
+ + {headers.map((col, index) => { const [name, sort] = Array.isArray(col) ? col : [col]; const state = index === sortSelected[0] ? sortSelected[1] : null; @@ -72,9 +78,14 @@ export function Table({ return ( ); @@ -104,11 +110,39 @@ export function Table({
{ @@ -82,14 +93,9 @@ export function Table({ sort?.(nxt); }} > -
+
{name} - {sort && ( - - )} + {sort && }
{!rows.length && ( -
+
-

No data.

+

No data.

)}
); } + +export type CellProps = { + children: ReactNode | string; +} & React.DetailedHTMLProps< + React.TdHTMLAttributes, + HTMLTableCellElement +>; + +export const Cell = ({ children, className = "", ...rest }: CellProps) => ( + + {children} + +); + +export type RowProps = { + cells: ReactElement[]; + className?: string; +}; + +export function Row({ cells, className = "" }: RowProps) { + return ( + + {cells.map((Cell, index) => ( + {Cell} + ))} + + ); +} diff --git a/src/components/Table/cell.css b/src/components/Table/cell.css deleted file mode 100644 index 7ce41de..0000000 --- a/src/components/Table/cell.css +++ /dev/null @@ -1,4 +0,0 @@ -.cell { - text-align: left; - padding: 1rem; -} diff --git a/src/components/Table/row.css b/src/components/Table/row.css deleted file mode 100644 index 842284e..0000000 --- a/src/components/Table/row.css +++ /dev/null @@ -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); -} diff --git a/src/components/Table/table.css b/src/components/Table/table.css index e1e383c..3948b9c 100644 --- a/src/components/Table/table.css +++ b/src/components/Table/table.css @@ -1,70 +1,131 @@ .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; border-radius: var(--codex-border-radius); overflow-x: auto; overflow-y: hidden; -} -.table-theadTr { - border-bottom: 1px solid var(--codex-border-color); -} + table { + border-spacing: 0 12px; + width: 100%; -.table-theadTh { - color: var(--codex-color-light); - font-weight: normal; - text-transform: uppercase; - font-size: 0.9rem; - text-align: left; - padding: 1rem; -} + thead { + tr { + border-bottom: 1px solid var(--codex-border-color); + border-radius: 8px; -.table-theadTh--clickable { - cursor: pointer; -} + th { + 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 { - display: flex; - align-items: center; - gap: 0.5rem; -} + &[role="button"] { + cursor: pointer; + } -.table-theadTh-content svg { - position: relative; - top: -2px; - cursor: pointer; -} + div { + display: flex; + align-items: center; + gap: 0.5rem; + } -.table-theadTh-content svg path { - opacity: 0.5; - transition: opacity 0.35s; -} + svg { + position: relative; + top: -2px; + cursor: pointer; + } -.table-theadTh-icon--desc path:nth-child(1), -.table-theadTh-icon--desc path:nth-child(2) { - opacity: 1; -} + svg path { + opacity: 0.5; + transition: opacity 0.35s; + } -.table-theadTh-icon--asc path:nth-child(3), -.table-theadTh-icon--asc path:nth-child(4) { - opacity: 1; + th[aria-sort="descending"] path:nth-child(1), + th[aria-sort="descending"] path:nth-child(2) { + 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; + } + } } diff --git a/src/components/Tabs/Tabs.tsx b/src/components/Tabs/Tabs.tsx index 596e657..2ace8e4 100644 --- a/src/components/Tabs/Tabs.tsx +++ b/src/components/Tabs/Tabs.tsx @@ -1,6 +1,7 @@ import { ComponentType } from "react"; import "./tabs.css"; import { classnames } from "../utils/classnames"; +import { attributes } from "../utils/attributes"; export type TabProps = { label: string; @@ -26,11 +27,8 @@ export function Tabs({ tabs, onTabChange, tabIndex }: Props) { {tabs.map((tab, index) => (
onTabChange(index)} > {tab.Icon && } diff --git a/src/components/Tabs/tabs.css b/src/components/Tabs/tabs.css index ce24e1c..4d61ce3 100644 --- a/src/components/Tabs/tabs.css +++ b/src/components/Tabs/tabs.css @@ -3,50 +3,39 @@ margin-top: 1rem; gap: 1rem; position: relative; -} -.tabs-tab { - display: flex; - align-items: center; - gap: 0.25rem; - padding-bottom: 1rem; - cursor: pointer; - transition: 0.35s opacity; - z-index: 1; - position: relative; -} + &::after { + width: 100%; + background-color: var(--codex-background-light); + content: " "; + position: absolute; + height: 2px; + top: 11px; + top: 31px; + } -.tabs::after { - width: 100%; - background-color: var(--codex-background-light); - content: " "; - position: absolute; - height: 2px; - top: 11px; - top: 31px; -} + div { + display: flex; + align-items: center; + gap: 0.25rem; + padding-bottom: 1rem; + cursor: pointer; + transition: 0.35s opacity; + z-index: 1; + position: relative; -.tabs-tab:not(.files-headerTab--active) { - opacity: 0.7; -} + &:hover { + opacity: 0.85; + } -.tabs-tab:hover { - opacity: 0.85; -} - -.tabs-tab--active:after { - width: 100%; - background-color: var(--codex-color-contrast); - content: " "; - position: absolute; - height: 2px; - top: 11px; - top: 31px; -} - -.tabs-icon { - width: 1rem; - height: 1rem; - display: flex; - place-items: center; + &[aria-selected]:after { + width: 100%; + background-color: var(--codex-color-contrast); + content: " "; + position: absolute; + height: 2px; + top: 11px; + top: 31px; + } + } } diff --git a/src/components/Toast/Toast.tsx b/src/components/Toast/Toast.tsx index 32699fd..4bffa5a 100644 --- a/src/components/Toast/Toast.tsx +++ b/src/components/Toast/Toast.tsx @@ -1,16 +1,9 @@ -import { CSSProperties, useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { attributes } from "../utils/attributes"; import "./toast.css"; import { CircleCheck, CircleX, Info, X } from "lucide-react"; 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 = { message: string; @@ -30,22 +23,12 @@ type Props = { 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"; }; export function Toast({ message, time, - style, variant, className = "", duration = 3000, @@ -84,12 +67,11 @@ export function Toast({
- + - {variant} ! + {variant} ! {msg} diff --git a/src/components/Toast/toast.css b/src/components/Toast/toast.css index 1d8ae09..e53391b 100644 --- a/src/components/Toast/toast.css +++ b/src/components/Toast/toast.css @@ -18,33 +18,33 @@ border: 1px solid rgb(var(--codex-toast-color)); background: rgba(var(--codex-toast-color), 1); z-index: 20; -} -.toast-close { - margin-left: 0.75rem; -} + &[aria-hidden] { + transform: translateX(1000px); + } -.toast[aria-hidden] { - transform: translateX(1000px); -} + &.toast--success { + --codex-toast-color: var(--codex-color-success); + } -.toast-title { - text-transform: capitalize; -} + &.toast--error { + --codex-toast-color: var(--codex-color-error); + } -.toast-icon { - fill: rgba(var(--codex-toast-color), 0.2); - stroke: white; -} + &.toast--default { + --codex-toast-color: var(--codex-color-grey); + } -.toast--success { - --codex-toast-color: var(--codex-color-success); -} + .button { + margin-left: 0.75rem; + } -.toast--error { - --codex-toast-color: var(--codex-color-error); -} + b { + text-transform: capitalize; + } -.toast--default { - --codex-toast-color: var(--codex-color-grey); + svg { + fill: rgba(var(--codex-toast-color), 0.2); + stroke: white; + } } diff --git a/src/components/Upload/Upload.tsx b/src/components/Upload/Upload.tsx index d9fa618..86e479a 100644 --- a/src/components/Upload/Upload.tsx +++ b/src/components/Upload/Upload.tsx @@ -1,5 +1,5 @@ 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 "./upload.css"; import { UploadFile } from "./UploadFile.tsx"; @@ -7,17 +7,6 @@ import { useUploadStategy } from "./useUploadStrategy.ts"; import { classnames } from "../utils/classnames.ts"; import { ButtonIcon } from "../ButtonIcon/ButtonIcon.tsx"; 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 = { /** @@ -68,18 +57,6 @@ type Props = { */ // 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. * Default: File uploaded successfully. @@ -151,17 +128,16 @@ export function Upload({ onMouseLeave={onMouseLeave} > -
-
- - Drop your {multiple ? "file(s)" : "file"} here or{" "} - browse - -
- - {multiple ? "Up to 10 files" : "Choose one single file"} - -
+ +

+ + Drop your {multiple ? "file(s)" : "file"} here or{" "} + browse + +

+ + {multiple ? "Up to 10 files" : "Choose one single file"} + - {warning && {warning}} + {warning && {warning}}
{files.map(({ id, file }) => ( diff --git a/src/components/Upload/UploadFile.css b/src/components/Upload/UploadFile.css new file mode 100644 index 0000000..06899ba --- /dev/null +++ b/src/components/Upload/UploadFile.css @@ -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); + } +} diff --git a/src/components/Upload/UploadFile.tsx b/src/components/Upload/UploadFile.tsx index 7228b56..acb59bf 100644 --- a/src/components/Upload/UploadFile.tsx +++ b/src/components/Upload/UploadFile.tsx @@ -7,7 +7,7 @@ import { Spinner } from "../Spinner/Spinner"; import { CodexData } from "@codex-storage/sdk-js"; import { WebFileIcon } from "../WebFileIcon/WebFileIcon"; import { ButtonIcon } from "../ButtonIcon/ButtonIcon"; -import { SimpleText } from "../SimpleText/SimpleText"; +import "./UploadFile.css"; type UploadFileProps = { file: File; @@ -263,37 +263,32 @@ export function UploadFile({ const ActionIcon = () => ; return ( - <> -
-
-
+
+
+
+
{preview ? ( - Preview + Preview ) : ( )} -
- - {filename} +

+ + {filename} {extension && .{extension}}

{PrettyBytes(file.size)}
-
+

-
+
-
+
-
+
- - {percent.toFixed(2)} % - -
+ {percent.toFixed(2)} % + -
+
{cid ? ( -
{successMessage}
+ {successMessage} ) : ( - - {error ? error : <> } - + {error ? error : <> } )} -
+
- +
); } diff --git a/src/components/Upload/upload.css b/src/components/Upload/upload.css index c0bcf26..502a5f7 100644 --- a/src/components/Upload/upload.css +++ b/src/components/Upload/upload.css @@ -11,172 +11,24 @@ gap: 0.5rem; cursor: pointer; 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; align-items: center; -} -.uploadFile-name[aria-invalid] { - color: rgb(var(--codex-color-error)); -} + p { + margin-bottom: 0; + margin-top: 12px; + line-height: 4px; -.uploadFile-name[data-done] { - color: var(--codex-color-primary); -} + span { + color: var(--codex-color-primary); + } + } -.uploadFile-infoText { - flex-grow: 1; -} + small { + color: var(--codex-input-label-color); + } -.uploadFile-infoRight { - justify-content: space-around; - 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; + input + span { + color: var(--codex-color-warning); + } } diff --git a/src/index.ts b/src/index.ts index b518432..3b01541 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,6 @@ export { Button } from "./components/Button/Button"; export { ButtonIcon } from "./components/ButtonIcon/ButtonIcon"; export { Input } from "./components/Input/Input"; export { InputGroup } from "./components/InputGroup/InputGroup"; -export { SimpleText } from "./components/SimpleText/SimpleText"; export { Upload } from "./components/Upload/Upload"; export { Card } from "./components/Card/Card"; export { Select } from "./components/Select/Select"; @@ -16,10 +15,7 @@ export { Spinner } from "./components/Spinner/Spinner"; export { WebFileIcon } from "./components/WebFileIcon/WebFileIcon"; export { Stepper } from "./components/Stepper/Stepper"; export { Backdrop } from "./components/Backdrop/Backdrop"; -export { Cell, type CellProps } from "./components/Table/Cell"; -export { Table, type TabSortState } from "./components/Table/Table"; -export { Row, type RowProps } from "./components/Table/Row"; -export { NetworkIndicator } from "./components/NetworkIndicator/NetworkIndicator"; +export * from "./components/Table/Table"; export { Tooltip } from "./components/Tooltip/Tooltip"; export { Collapse } from "./components/Collapse/Collapse"; export { Placeholder } from "./components/Placeholder/Placeholder"; diff --git a/stories/Modal.stories.tsx b/stories/Modal.stories.tsx index e79760d..ab03f93 100644 --- a/stories/Modal.stories.tsx +++ b/stories/Modal.stories.tsx @@ -65,7 +65,12 @@ const ActionTemplate = (props: Props) => { return (
- +

Hello world

diff --git a/stories/NetworkIndicator.stories.ts b/stories/NetworkIndicator.stories.ts deleted file mode 100644 index 4fd41ad..0000000 --- a/stories/NetworkIndicator.stories.ts +++ /dev/null @@ -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; - -export default meta; -type Story = StoryObj; - -export const Online: Story = { - args: { - online: true, - text: "Online", - }, -}; - -export const Offline: Story = { - args: { - online: false, - text: "Offline", - }, -}; diff --git a/stories/SpaceAllocation.stories.ts b/stories/SpaceAllocation.stories.ts index 8926980..56c0f4e 100644 --- a/stories/SpaceAllocation.stories.ts +++ b/stories/SpaceAllocation.stories.ts @@ -20,14 +20,17 @@ export const Default: Story = { { title: "Space allocated", size: 10000000, + color: "red" }, { title: "New space allocation", size: 10000000 * 0.2, + color: "yellow" }, { title: "Remaining space", size: 10000000 * 0.2, + color: "green" }, ], }, diff --git a/stories/Table.stories.tsx b/stories/Table.stories.tsx index c51ed69..e81883d 100644 --- a/stories/Table.stories.tsx +++ b/stories/Table.stories.tsx @@ -1,7 +1,6 @@ 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 { Row } from "../src/components/Table/Row"; import { Cell } from "../src"; const meta = {