@indinno/digicode-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/bin/digicode.mjs +136 -0
- package/package.json +31 -0
- package/registry/components/accordion.tsx +41 -0
- package/registry/components/alert.tsx +21 -0
- package/registry/components/avatar.tsx +18 -0
- package/registry/components/badge.tsx +9 -0
- package/registry/components/breadcrumb.tsx +22 -0
- package/registry/components/button.tsx +38 -0
- package/registry/components/card.tsx +10 -0
- package/registry/components/checkbox.tsx +15 -0
- package/registry/components/dialog.tsx +46 -0
- package/registry/components/drawer.tsx +42 -0
- package/registry/components/dropdown-menu.tsx +38 -0
- package/registry/components/empty-state.tsx +20 -0
- package/registry/components/input.tsx +28 -0
- package/registry/components/pagination.tsx +21 -0
- package/registry/components/progress.tsx +17 -0
- package/registry/components/radio-group.tsx +40 -0
- package/registry/components/select.tsx +33 -0
- package/registry/components/separator.tsx +10 -0
- package/registry/components/skeleton.tsx +6 -0
- package/registry/components/spinner.tsx +11 -0
- package/registry/components/stat-card.tsx +21 -0
- package/registry/components/switch.tsx +15 -0
- package/registry/components/table.tsx +11 -0
- package/registry/components/tabs.tsx +52 -0
- package/registry/components/textarea.tsx +22 -0
- package/registry/components/tooltip.tsx +16 -0
- package/registry/lib/cn.ts +3 -0
- package/registry/registry.json +32 -0
- package/registry/styles/digicode.css +253 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export interface EmptyStateProps {
|
|
4
|
+
icon?: ReactNode;
|
|
5
|
+
title: ReactNode;
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
actions?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function EmptyState({ icon, title, description, actions, className }: EmptyStateProps) {
|
|
12
|
+
return (
|
|
13
|
+
<div className={className ? `digicode-empty ${className}` : "digicode-empty"}>
|
|
14
|
+
{icon && <div className="digicode-empty__icon">{icon}</div>}
|
|
15
|
+
<h3 className="digicode-empty__title">{title}</h3>
|
|
16
|
+
{description && <p className="digicode-empty__description">{description}</p>}
|
|
17
|
+
{actions && <div className="digicode-empty__actions">{actions}</div>}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { forwardRef, type InputHTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
5
|
+
label?: string;
|
|
6
|
+
hint?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
prefix?: ReactNode;
|
|
9
|
+
suffix?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|
13
|
+
{ className, id, label, hint, error, prefix, suffix, ...props },
|
|
14
|
+
ref
|
|
15
|
+
) {
|
|
16
|
+
const inputId = id || props.name;
|
|
17
|
+
return (
|
|
18
|
+
<label className="digicode-field" htmlFor={inputId}>
|
|
19
|
+
{label && <span className="digicode-field__label">{label}</span>}
|
|
20
|
+
<span className={cn("digicode-input-wrap", error && "digicode-input-wrap--error")}>
|
|
21
|
+
{prefix && <span className="digicode-input__affix">{prefix}</span>}
|
|
22
|
+
<input ref={ref} id={inputId} className={cn("digicode-input", className)} aria-invalid={!!error || undefined} {...props} />
|
|
23
|
+
{suffix && <span className="digicode-input__affix">{suffix}</span>}
|
|
24
|
+
</span>
|
|
25
|
+
{error ? <span className="digicode-field__error">{error}</span> : hint && <span className="digicode-field__hint">{hint}</span>}
|
|
26
|
+
</label>
|
|
27
|
+
);
|
|
28
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export interface PaginationProps {
|
|
4
|
+
page: number;
|
|
5
|
+
totalPages: number;
|
|
6
|
+
onPageChange?: (page: number) => void;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Pagination({ page, totalPages, onPageChange, className }: PaginationProps) {
|
|
11
|
+
const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
12
|
+
return (
|
|
13
|
+
<nav aria-label="Pagination" className={className ? `digicode-pagination ${className}` : "digicode-pagination"}>
|
|
14
|
+
<button type="button" className="digicode-pagination__item" disabled={page <= 1} onClick={() => onPageChange?.(page - 1)} aria-label="Previous page">‹</button>
|
|
15
|
+
{pages.map((value) => (
|
|
16
|
+
<button key={value} type="button" className="digicode-pagination__item" data-active={page === value} aria-current={page === value ? "page" : undefined} onClick={() => onPageChange?.(value)}>{value}</button>
|
|
17
|
+
))}
|
|
18
|
+
<button type="button" className="digicode-pagination__item" disabled={page >= totalPages} onClick={() => onPageChange?.(page + 1)} aria-label="Next page">›</button>
|
|
19
|
+
</nav>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface ProgressProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
value: number;
|
|
6
|
+
max?: number;
|
|
7
|
+
label?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Progress({ className, value, max = 100, label = "Progress", ...props }: ProgressProps) {
|
|
11
|
+
const percent = Math.max(0, Math.min(100, (value / max) * 100));
|
|
12
|
+
return (
|
|
13
|
+
<div className={cn("digicode-progress", className)} role="progressbar" aria-label={label} aria-valuenow={value} aria-valuemin={0} aria-valuemax={max} {...props}>
|
|
14
|
+
<div className="digicode-progress__bar" style={{ width: `${percent}%` }} />
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { InputHTMLAttributes } from "react";
|
|
4
|
+
|
|
5
|
+
export interface RadioOption {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RadioGroupProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "value" | "onChange"> {
|
|
12
|
+
name: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
defaultValue?: string;
|
|
15
|
+
options: RadioOption[];
|
|
16
|
+
onValueChange?: (value: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function RadioGroup({ name, value, defaultValue, options, onValueChange, ...props }: RadioGroupProps) {
|
|
20
|
+
return (
|
|
21
|
+
<div className="digicode-radio-group" role="radiogroup">
|
|
22
|
+
{options.map((option) => (
|
|
23
|
+
<label className="digicode-checkline" key={option.value}>
|
|
24
|
+
<input
|
|
25
|
+
type="radio"
|
|
26
|
+
className="digicode-radio"
|
|
27
|
+
name={name}
|
|
28
|
+
value={option.value}
|
|
29
|
+
checked={value !== undefined ? value === option.value : undefined}
|
|
30
|
+
defaultChecked={value === undefined ? defaultValue === option.value : undefined}
|
|
31
|
+
disabled={option.disabled}
|
|
32
|
+
onChange={() => onValueChange?.(option.value)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
<span>{option.label}</span>
|
|
36
|
+
</label>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { forwardRef, type SelectHTMLAttributes } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface SelectOption {
|
|
5
|
+
label: string;
|
|
6
|
+
value: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
|
|
11
|
+
label?: string;
|
|
12
|
+
hint?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
options?: SelectOption[];
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(
|
|
19
|
+
{ className, id, label, hint, error, options = [], placeholder, children, ...props },
|
|
20
|
+
ref
|
|
21
|
+
) {
|
|
22
|
+
const selectId = id || props.name;
|
|
23
|
+
return (
|
|
24
|
+
<label className="digicode-field" htmlFor={selectId}>
|
|
25
|
+
{label && <span className="digicode-field__label">{label}</span>}
|
|
26
|
+
<select ref={ref} id={selectId} className={cn("digicode-select", className)} aria-invalid={!!error || undefined} {...props}>
|
|
27
|
+
{placeholder && <option value="">{placeholder}</option>}
|
|
28
|
+
{children || options.map((option) => <option key={option.value} value={option.value} disabled={option.disabled}>{option.label}</option>)}
|
|
29
|
+
</select>
|
|
30
|
+
{error ? <span className="digicode-field__error">{error}</span> : hint && <span className="digicode-field__hint">{hint}</span>}
|
|
31
|
+
</label>
|
|
32
|
+
);
|
|
33
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface SeparatorProps extends HTMLAttributes<HTMLHRElement> {
|
|
5
|
+
orientation?: "horizontal" | "vertical";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function Separator({ className, orientation = "horizontal", ...props }: SeparatorProps) {
|
|
9
|
+
return <hr role="separator" aria-orientation={orientation} className={cn("digicode-separator", `digicode-separator--${orientation}`, className)} {...props} />;
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
|
+
size?: "sm" | "md" | "lg";
|
|
6
|
+
label?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Spinner({ className, size = "md", label = "Loading", ...props }: SpinnerProps) {
|
|
10
|
+
return <span role="status" aria-label={label} className={cn("digicode-spinner", size !== "md" && `digicode-spinner--${size}`, className)} {...props} />;
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface StatCardProps {
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
value: ReactNode;
|
|
7
|
+
icon?: ReactNode;
|
|
8
|
+
delta?: ReactNode;
|
|
9
|
+
trend?: "up" | "down" | "neutral";
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function StatCard({ label, value, icon, delta, trend = "neutral", className }: StatCardProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div className={cn("digicode-stat", className)}>
|
|
16
|
+
<div className="digicode-stat__top"><span className="digicode-stat__label">{label}</span>{icon && <span className="digicode-stat__icon">{icon}</span>}</div>
|
|
17
|
+
<div className="digicode-stat__value">{value}</div>
|
|
18
|
+
{delta && <div className={cn("digicode-stat__delta", trend !== "neutral" && `digicode-stat__delta--${trend}`)}>{delta}</div>}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { forwardRef, type InputHTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
5
|
+
label?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch({ className, label, ...props }, ref) {
|
|
9
|
+
return (
|
|
10
|
+
<label className="digicode-switch-wrap">
|
|
11
|
+
<input ref={ref} type="checkbox" role="switch" className={cn("digicode-switch", className)} {...props} />
|
|
12
|
+
{label && <span>{label}</span>}
|
|
13
|
+
</label>
|
|
14
|
+
);
|
|
15
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export function Table({ className, ...props }: ComponentPropsWithoutRef<"table">) {
|
|
5
|
+
return <div className="digicode-table-wrap"><table className={cn("digicode-table", className)} {...props} /></div>;
|
|
6
|
+
}
|
|
7
|
+
export function TableHeader(props: ComponentPropsWithoutRef<"thead">) { return <thead {...props} />; }
|
|
8
|
+
export function TableBody(props: ComponentPropsWithoutRef<"tbody">) { return <tbody {...props} />; }
|
|
9
|
+
export function TableRow(props: ComponentPropsWithoutRef<"tr">) { return <tr {...props} />; }
|
|
10
|
+
export function TableHead(props: ComponentPropsWithoutRef<"th">) { return <th {...props} />; }
|
|
11
|
+
export function TableCell(props: ComponentPropsWithoutRef<"td">) { return <td {...props} />; }
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo, useState, type ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
export interface TabItem {
|
|
6
|
+
value: string;
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
content: ReactNode;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface TabsProps {
|
|
13
|
+
items: TabItem[];
|
|
14
|
+
defaultValue?: string;
|
|
15
|
+
value?: string;
|
|
16
|
+
onValueChange?: (value: string) => void;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function Tabs({ items, defaultValue, value, onValueChange, className }: TabsProps) {
|
|
21
|
+
const first = useMemo(() => items.find((item) => !item.disabled)?.value ?? "", [items]);
|
|
22
|
+
const [internal, setInternal] = useState(defaultValue ?? first);
|
|
23
|
+
const active = value ?? internal;
|
|
24
|
+
const current = items.find((item) => item.value === active) ?? items[0];
|
|
25
|
+
|
|
26
|
+
function select(next: string) {
|
|
27
|
+
if (value === undefined) setInternal(next);
|
|
28
|
+
onValueChange?.(next);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className={className ? `digicode-tabs ${className}` : "digicode-tabs"}>
|
|
33
|
+
<div className="digicode-tabs__list" role="tablist">
|
|
34
|
+
{items.map((item) => (
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
role="tab"
|
|
38
|
+
key={item.value}
|
|
39
|
+
disabled={item.disabled}
|
|
40
|
+
aria-selected={active === item.value}
|
|
41
|
+
data-active={active === item.value}
|
|
42
|
+
className="digicode-tabs__trigger"
|
|
43
|
+
onClick={() => select(item.value)}
|
|
44
|
+
>
|
|
45
|
+
{item.label}
|
|
46
|
+
</button>
|
|
47
|
+
))}
|
|
48
|
+
</div>
|
|
49
|
+
<div className="digicode-tabs__panel" role="tabpanel">{current?.content}</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { forwardRef, type TextareaHTMLAttributes } from "react";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
|
|
4
|
+
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
5
|
+
label?: string;
|
|
6
|
+
hint?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(
|
|
11
|
+
{ className, id, label, hint, error, ...props },
|
|
12
|
+
ref
|
|
13
|
+
) {
|
|
14
|
+
const textareaId = id || props.name;
|
|
15
|
+
return (
|
|
16
|
+
<label className="digicode-field" htmlFor={textareaId}>
|
|
17
|
+
{label && <span className="digicode-field__label">{label}</span>}
|
|
18
|
+
<textarea ref={ref} id={textareaId} className={cn("digicode-textarea", className)} aria-invalid={!!error || undefined} {...props} />
|
|
19
|
+
{error ? <span className="digicode-field__error">{error}</span> : hint && <span className="digicode-field__hint">{hint}</span>}
|
|
20
|
+
</label>
|
|
21
|
+
);
|
|
22
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export interface TooltipProps {
|
|
4
|
+
content: ReactNode;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Tooltip({ content, children, className }: TooltipProps) {
|
|
10
|
+
return (
|
|
11
|
+
<span className={className ? `digicode-tooltip ${className}` : "digicode-tooltip"}>
|
|
12
|
+
{children}
|
|
13
|
+
<span role="tooltip" className="digicode-tooltip__content">{content}</span>
|
|
14
|
+
</span>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "DigiCode",
|
|
3
|
+
"style": "digicode",
|
|
4
|
+
"components": [
|
|
5
|
+
"accordion",
|
|
6
|
+
"alert",
|
|
7
|
+
"avatar",
|
|
8
|
+
"badge",
|
|
9
|
+
"breadcrumb",
|
|
10
|
+
"button",
|
|
11
|
+
"card",
|
|
12
|
+
"checkbox",
|
|
13
|
+
"dialog",
|
|
14
|
+
"drawer",
|
|
15
|
+
"dropdown-menu",
|
|
16
|
+
"empty-state",
|
|
17
|
+
"input",
|
|
18
|
+
"pagination",
|
|
19
|
+
"progress",
|
|
20
|
+
"radio-group",
|
|
21
|
+
"select",
|
|
22
|
+
"separator",
|
|
23
|
+
"skeleton",
|
|
24
|
+
"spinner",
|
|
25
|
+
"stat-card",
|
|
26
|
+
"switch",
|
|
27
|
+
"table",
|
|
28
|
+
"tabs",
|
|
29
|
+
"textarea",
|
|
30
|
+
"tooltip"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--digicode-ink: #1c2f41;
|
|
3
|
+
--digicode-heading: #12212e;
|
|
4
|
+
--digicode-muted: #60707e;
|
|
5
|
+
--digicode-primary: #2474ad;
|
|
6
|
+
--digicode-primary-hover: #1f6699;
|
|
7
|
+
--digicode-primary-soft: #eef6fb;
|
|
8
|
+
--digicode-surface: #ffffff;
|
|
9
|
+
--digicode-surface-2: #f4f7f9;
|
|
10
|
+
--digicode-line: #e4eaee;
|
|
11
|
+
--digicode-line-strong: #ced9e0;
|
|
12
|
+
--digicode-success: #21986c;
|
|
13
|
+
--digicode-warning: #c98217;
|
|
14
|
+
--digicode-danger: #c34a4a;
|
|
15
|
+
--digicode-info: #2474ad;
|
|
16
|
+
--digicode-ring: rgba(36, 116, 173, 0.2);
|
|
17
|
+
--digicode-radius-sm: 8px;
|
|
18
|
+
--digicode-radius: 12px;
|
|
19
|
+
--digicode-radius-lg: 18px;
|
|
20
|
+
--digicode-shadow-sm: 0 1px 2px rgba(18, 33, 46, 0.07);
|
|
21
|
+
--digicode-shadow: 0 8px 24px rgba(18, 33, 46, 0.08);
|
|
22
|
+
--digicode-shadow-lg: 0 20px 60px rgba(18, 33, 46, 0.16);
|
|
23
|
+
--digicode-ease: cubic-bezier(0.19, 1, 0.22, 1);
|
|
24
|
+
--digicode-font: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[data-digicode-theme="dark"] {
|
|
28
|
+
--digicode-ink: #e6eef4;
|
|
29
|
+
--digicode-heading: #f8fbfd;
|
|
30
|
+
--digicode-muted: #9babb8;
|
|
31
|
+
--digicode-primary: #5da4d1;
|
|
32
|
+
--digicode-primary-hover: #77b4da;
|
|
33
|
+
--digicode-primary-soft: #173247;
|
|
34
|
+
--digicode-surface: #0f1922;
|
|
35
|
+
--digicode-surface-2: #15232e;
|
|
36
|
+
--digicode-line: #253845;
|
|
37
|
+
--digicode-line-strong: #36505f;
|
|
38
|
+
--digicode-ring: rgba(93, 164, 209, 0.25);
|
|
39
|
+
--digicode-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
40
|
+
--digicode-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
|
|
41
|
+
--digicode-shadow-lg: 0 24px 70px rgba(0, 0, 0, 0.38);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.digicode-button,
|
|
45
|
+
.digicode-input,
|
|
46
|
+
.digicode-textarea,
|
|
47
|
+
.digicode-select,
|
|
48
|
+
.digicode-checkbox,
|
|
49
|
+
.digicode-radio,
|
|
50
|
+
.digicode-switch,
|
|
51
|
+
.digicode-badge,
|
|
52
|
+
.digicode-card,
|
|
53
|
+
.digicode-alert,
|
|
54
|
+
.digicode-avatar,
|
|
55
|
+
.digicode-tabs,
|
|
56
|
+
.digicode-accordion,
|
|
57
|
+
.digicode-dialog,
|
|
58
|
+
.digicode-drawer,
|
|
59
|
+
.digicode-dropdown,
|
|
60
|
+
.digicode-tooltip,
|
|
61
|
+
.digicode-breadcrumb,
|
|
62
|
+
.digicode-pagination,
|
|
63
|
+
.digicode-table,
|
|
64
|
+
.digicode-empty,
|
|
65
|
+
.digicode-stat {
|
|
66
|
+
font-family: var(--digicode-font);
|
|
67
|
+
box-sizing: border-box;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.digicode-button {
|
|
71
|
+
appearance: none;
|
|
72
|
+
border: 1px solid transparent;
|
|
73
|
+
border-radius: var(--digicode-radius);
|
|
74
|
+
min-height: 42px;
|
|
75
|
+
padding: 9px 18px;
|
|
76
|
+
display: inline-flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
gap: 9px;
|
|
80
|
+
font: 600 14px/1.2 var(--digicode-font);
|
|
81
|
+
white-space: nowrap;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
transition: transform .18s var(--digicode-ease), background .18s, border-color .18s, box-shadow .18s, color .18s;
|
|
84
|
+
}
|
|
85
|
+
.digicode-button:hover { transform: translateY(-1px); }
|
|
86
|
+
.digicode-button:active { transform: translateY(0); }
|
|
87
|
+
.digicode-button:focus-visible,
|
|
88
|
+
.digicode-input:focus-visible,
|
|
89
|
+
.digicode-textarea:focus-visible,
|
|
90
|
+
.digicode-select:focus-visible,
|
|
91
|
+
.digicode-checkbox:focus-visible,
|
|
92
|
+
.digicode-radio:focus-visible,
|
|
93
|
+
.digicode-switch:focus-visible,
|
|
94
|
+
.digicode-pagination__item:focus-visible {
|
|
95
|
+
outline: 3px solid var(--digicode-ring);
|
|
96
|
+
outline-offset: 2px;
|
|
97
|
+
}
|
|
98
|
+
.digicode-button:disabled { opacity: .55; cursor: not-allowed; transform: none; }
|
|
99
|
+
.digicode-button--primary { background: var(--digicode-ink); color: #fff; box-shadow: var(--digicode-shadow-sm); }
|
|
100
|
+
.digicode-button--primary:hover { background: #284458; box-shadow: 0 7px 18px rgba(28,47,65,.16); }
|
|
101
|
+
[data-digicode-theme="dark"] .digicode-button--primary { background: #e6eef4; color: #12212e; }
|
|
102
|
+
[data-digicode-theme="dark"] .digicode-button--primary:hover { background: #fff; }
|
|
103
|
+
.digicode-button--secondary { background: var(--digicode-primary); color: #fff; }
|
|
104
|
+
.digicode-button--secondary:hover { background: var(--digicode-primary-hover); }
|
|
105
|
+
.digicode-button--outline { background: var(--digicode-surface); color: var(--digicode-ink); border-color: var(--digicode-line-strong); }
|
|
106
|
+
.digicode-button--outline:hover { border-color: var(--digicode-primary); color: var(--digicode-primary); }
|
|
107
|
+
.digicode-button--ghost { background: transparent; color: var(--digicode-ink); }
|
|
108
|
+
.digicode-button--ghost:hover { background: var(--digicode-surface-2); }
|
|
109
|
+
.digicode-button--destructive { background: var(--digicode-danger); color: #fff; }
|
|
110
|
+
.digicode-button--link { padding-inline: 0; min-height: auto; background: transparent; color: var(--digicode-primary); border-radius: 0; }
|
|
111
|
+
.digicode-button--sm { min-height: 34px; padding: 7px 12px; font-size: 12px; border-radius: 9px; }
|
|
112
|
+
.digicode-button--lg { min-height: 50px; padding: 12px 22px; font-size: 15px; }
|
|
113
|
+
.digicode-button--icon { width: 42px; padding: 0; }
|
|
114
|
+
.digicode-button__spinner { width: 16px; height: 16px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: digicode-spin .7s linear infinite; }
|
|
115
|
+
@keyframes digicode-spin { to { transform: rotate(360deg); } }
|
|
116
|
+
|
|
117
|
+
.digicode-field { display: grid; gap: 7px; font-family: var(--digicode-font); }
|
|
118
|
+
.digicode-field__label { color: var(--digicode-heading); font-size: 13px; font-weight: 650; }
|
|
119
|
+
.digicode-field__hint { color: var(--digicode-muted); font-size: 12px; line-height: 1.45; }
|
|
120
|
+
.digicode-field__error { color: var(--digicode-danger); font-size: 12px; line-height: 1.45; }
|
|
121
|
+
.digicode-input-wrap { display: flex; align-items: center; gap: 8px; min-height: 44px; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); background: var(--digicode-surface); color: var(--digicode-ink); padding-inline: 12px; transition: border-color .18s, box-shadow .18s, background .18s; }
|
|
122
|
+
.digicode-input-wrap:focus-within { border-color: var(--digicode-primary); box-shadow: 0 0 0 3px var(--digicode-ring); }
|
|
123
|
+
.digicode-input-wrap--error { border-color: var(--digicode-danger); }
|
|
124
|
+
.digicode-input { width: 100%; min-width: 0; border: 0; outline: 0; color: inherit; background: transparent; padding: 10px 0; font: 400 14px/1.4 var(--digicode-font); }
|
|
125
|
+
.digicode-input::placeholder, .digicode-textarea::placeholder { color: #93a0aa; }
|
|
126
|
+
.digicode-input__affix { display: inline-flex; align-items: center; color: var(--digicode-muted); font-size: 13px; }
|
|
127
|
+
.digicode-textarea { width: 100%; min-height: 112px; resize: vertical; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); background: var(--digicode-surface); color: var(--digicode-ink); padding: 11px 12px; font: 400 14px/1.55 var(--digicode-font); transition: border-color .18s, box-shadow .18s; }
|
|
128
|
+
.digicode-textarea:focus { outline: 0; border-color: var(--digicode-primary); box-shadow: 0 0 0 3px var(--digicode-ring); }
|
|
129
|
+
.digicode-select { width: 100%; min-height: 44px; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); background: var(--digicode-surface); color: var(--digicode-ink); padding: 0 36px 0 12px; font: 500 14px var(--digicode-font); }
|
|
130
|
+
|
|
131
|
+
.digicode-checkline { display: inline-flex; align-items: flex-start; gap: 10px; color: var(--digicode-ink); font: 500 14px/1.45 var(--digicode-font); cursor: pointer; }
|
|
132
|
+
.digicode-checkbox, .digicode-radio { width: 18px; height: 18px; flex: 0 0 18px; margin: 1px 0 0; accent-color: var(--digicode-primary); cursor: pointer; }
|
|
133
|
+
.digicode-radio-group { display: grid; gap: 10px; }
|
|
134
|
+
.digicode-switch-wrap { display: inline-flex; align-items: center; gap: 10px; color: var(--digicode-ink); font: 500 14px var(--digicode-font); cursor: pointer; }
|
|
135
|
+
.digicode-switch { position: relative; width: 42px; height: 24px; flex: 0 0 auto; appearance: none; border: 1px solid var(--digicode-line-strong); border-radius: 999px; background: #cfd8de; cursor: pointer; transition: background .2s, border-color .2s; }
|
|
136
|
+
.digicode-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,.18); transition: transform .2s var(--digicode-ease); }
|
|
137
|
+
.digicode-switch:checked { background: var(--digicode-primary); border-color: var(--digicode-primary); }
|
|
138
|
+
.digicode-switch:checked::after { transform: translateX(18px); }
|
|
139
|
+
|
|
140
|
+
.digicode-badge { display: inline-flex; align-items: center; gap: 6px; width: fit-content; min-height: 24px; padding: 3px 9px; border-radius: 999px; background: var(--digicode-surface-2); color: var(--digicode-ink); border: 1px solid var(--digicode-line); font: 650 11px/1 var(--digicode-font); }
|
|
141
|
+
.digicode-badge--primary { color: var(--digicode-primary); background: var(--digicode-primary-soft); border-color: transparent; }
|
|
142
|
+
.digicode-badge--success { color: var(--digicode-success); background: rgba(33,152,108,.1); border-color: transparent; }
|
|
143
|
+
.digicode-badge--warning { color: var(--digicode-warning); background: rgba(201,130,23,.11); border-color: transparent; }
|
|
144
|
+
.digicode-badge--danger { color: var(--digicode-danger); background: rgba(195,74,74,.1); border-color: transparent; }
|
|
145
|
+
|
|
146
|
+
.digicode-card { border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius-lg); background: var(--digicode-surface); color: var(--digicode-ink); box-shadow: var(--digicode-shadow-sm); overflow: hidden; }
|
|
147
|
+
.digicode-card--elevated { box-shadow: var(--digicode-shadow); }
|
|
148
|
+
.digicode-card__header, .digicode-card__content, .digicode-card__footer { padding: 20px; }
|
|
149
|
+
.digicode-card__header { display: grid; gap: 6px; }
|
|
150
|
+
.digicode-card__content { padding-top: 0; }
|
|
151
|
+
.digicode-card__footer { border-top: 1px solid var(--digicode-line); display: flex; align-items: center; gap: 10px; }
|
|
152
|
+
.digicode-card__title { margin: 0; color: var(--digicode-heading); font: 650 17px/1.35 var(--digicode-font); }
|
|
153
|
+
.digicode-card__description { margin: 0; color: var(--digicode-muted); font: 400 13px/1.55 var(--digicode-font); }
|
|
154
|
+
|
|
155
|
+
.digicode-alert { display: flex; gap: 12px; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); padding: 14px 15px; background: var(--digicode-surface); color: var(--digicode-ink); }
|
|
156
|
+
.digicode-alert--info { border-color: rgba(36,116,173,.25); background: rgba(36,116,173,.06); }
|
|
157
|
+
.digicode-alert--success { border-color: rgba(33,152,108,.25); background: rgba(33,152,108,.06); }
|
|
158
|
+
.digicode-alert--warning { border-color: rgba(201,130,23,.25); background: rgba(201,130,23,.06); }
|
|
159
|
+
.digicode-alert--danger { border-color: rgba(195,74,74,.25); background: rgba(195,74,74,.06); }
|
|
160
|
+
.digicode-alert__icon { margin-top: 2px; flex: 0 0 auto; }
|
|
161
|
+
.digicode-alert__title { margin: 0 0 3px; font: 650 13px/1.4 var(--digicode-font); }
|
|
162
|
+
.digicode-alert__description { margin: 0; color: var(--digicode-muted); font: 400 13px/1.5 var(--digicode-font); }
|
|
163
|
+
|
|
164
|
+
.digicode-avatar { display: inline-flex; align-items: center; justify-content: center; overflow: hidden; border-radius: 50%; background: var(--digicode-primary-soft); color: var(--digicode-primary); font: 700 13px var(--digicode-font); flex: 0 0 auto; }
|
|
165
|
+
.digicode-avatar img { width: 100%; height: 100%; object-fit: cover; }
|
|
166
|
+
.digicode-avatar--sm { width: 30px; height: 30px; }
|
|
167
|
+
.digicode-avatar--md { width: 40px; height: 40px; }
|
|
168
|
+
.digicode-avatar--lg { width: 52px; height: 52px; font-size: 16px; }
|
|
169
|
+
|
|
170
|
+
.digicode-spinner { display: inline-block; width: 24px; height: 24px; border: 3px solid var(--digicode-line); border-top-color: var(--digicode-primary); border-radius: 50%; animation: digicode-spin .75s linear infinite; }
|
|
171
|
+
.digicode-spinner--sm { width: 16px; height: 16px; border-width: 2px; }
|
|
172
|
+
.digicode-spinner--lg { width: 34px; height: 34px; border-width: 4px; }
|
|
173
|
+
.digicode-skeleton { display: block; border-radius: var(--digicode-radius-sm); background: linear-gradient(90deg, var(--digicode-surface-2) 25%, var(--digicode-line) 37%, var(--digicode-surface-2) 63%); background-size: 400% 100%; animation: digicode-shimmer 1.35s ease infinite; }
|
|
174
|
+
@keyframes digicode-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
|
|
175
|
+
.digicode-progress { width: 100%; height: 8px; overflow: hidden; border-radius: 999px; background: var(--digicode-surface-2); }
|
|
176
|
+
.digicode-progress__bar { height: 100%; border-radius: inherit; background: var(--digicode-primary); transition: width .3s var(--digicode-ease); }
|
|
177
|
+
.digicode-separator { border: 0; margin: 0; background: var(--digicode-line); }
|
|
178
|
+
.digicode-separator--horizontal { width: 100%; height: 1px; }
|
|
179
|
+
.digicode-separator--vertical { width: 1px; height: 100%; min-height: 18px; }
|
|
180
|
+
|
|
181
|
+
.digicode-tabs__list { display: inline-flex; align-items: center; gap: 3px; padding: 4px; background: var(--digicode-surface-2); border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); }
|
|
182
|
+
.digicode-tabs__trigger { appearance: none; border: 0; border-radius: 9px; background: transparent; color: var(--digicode-muted); padding: 8px 13px; font: 600 13px var(--digicode-font); cursor: pointer; }
|
|
183
|
+
.digicode-tabs__trigger[data-active="true"] { color: var(--digicode-heading); background: var(--digicode-surface); box-shadow: var(--digicode-shadow-sm); }
|
|
184
|
+
.digicode-tabs__panel { padding-top: 16px; color: var(--digicode-ink); }
|
|
185
|
+
|
|
186
|
+
.digicode-accordion { border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); background: var(--digicode-surface); overflow: hidden; }
|
|
187
|
+
.digicode-accordion__item + .digicode-accordion__item { border-top: 1px solid var(--digicode-line); }
|
|
188
|
+
.digicode-accordion__trigger { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 15px 16px; border: 0; background: transparent; color: var(--digicode-heading); text-align: left; font: 650 14px var(--digicode-font); cursor: pointer; }
|
|
189
|
+
.digicode-accordion__chevron { transition: transform .2s; }
|
|
190
|
+
.digicode-accordion__trigger[aria-expanded="true"] .digicode-accordion__chevron { transform: rotate(180deg); }
|
|
191
|
+
.digicode-accordion__content { padding: 0 16px 16px; color: var(--digicode-muted); font: 400 13px/1.6 var(--digicode-font); }
|
|
192
|
+
|
|
193
|
+
.digicode-dialog-native { width: min(520px, calc(100vw - 32px)); max-width: none; border: 1px solid var(--digicode-line); border-radius: 20px; padding: 0; background: var(--digicode-surface); color: var(--digicode-ink); box-shadow: var(--digicode-shadow-lg); }
|
|
194
|
+
.digicode-dialog-native::backdrop { background: rgba(10, 22, 31, .56); backdrop-filter: blur(3px); }
|
|
195
|
+
.digicode-dialog__header, .digicode-dialog__body, .digicode-dialog__footer { padding: 20px; }
|
|
196
|
+
.digicode-dialog__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; border-bottom: 1px solid var(--digicode-line); }
|
|
197
|
+
.digicode-dialog__title { margin: 0; color: var(--digicode-heading); font: 650 18px/1.4 var(--digicode-font); }
|
|
198
|
+
.digicode-dialog__description { margin: 5px 0 0; color: var(--digicode-muted); font: 400 13px/1.55 var(--digicode-font); }
|
|
199
|
+
.digicode-dialog__close { appearance: none; border: 0; border-radius: 8px; width: 32px; height: 32px; background: var(--digicode-surface-2); color: var(--digicode-muted); cursor: pointer; }
|
|
200
|
+
.digicode-dialog__footer { border-top: 1px solid var(--digicode-line); display: flex; justify-content: flex-end; gap: 9px; }
|
|
201
|
+
|
|
202
|
+
.digicode-drawer-native { margin: 0 0 0 auto; width: min(430px, 92vw); height: 100dvh; max-height: none; border: 0; border-left: 1px solid var(--digicode-line); border-radius: 20px 0 0 20px; padding: 0; background: var(--digicode-surface); color: var(--digicode-ink); box-shadow: var(--digicode-shadow-lg); }
|
|
203
|
+
.digicode-drawer-native::backdrop { background: rgba(10,22,31,.48); }
|
|
204
|
+
.digicode-drawer__header, .digicode-drawer__body, .digicode-drawer__footer { padding: 20px; }
|
|
205
|
+
.digicode-drawer__header { border-bottom: 1px solid var(--digicode-line); display: flex; justify-content: space-between; gap: 16px; }
|
|
206
|
+
.digicode-drawer__body { min-height: calc(100dvh - 150px); }
|
|
207
|
+
.digicode-drawer__footer { border-top: 1px solid var(--digicode-line); }
|
|
208
|
+
|
|
209
|
+
.digicode-dropdown { position: relative; display: inline-block; }
|
|
210
|
+
.digicode-dropdown > summary { list-style: none; }
|
|
211
|
+
.digicode-dropdown > summary::-webkit-details-marker { display: none; }
|
|
212
|
+
.digicode-dropdown__menu { position: absolute; z-index: 40; top: calc(100% + 7px); right: 0; width: 200px; padding: 6px; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); background: var(--digicode-surface); box-shadow: var(--digicode-shadow); }
|
|
213
|
+
.digicode-dropdown__item { width: 100%; display: flex; align-items: center; gap: 9px; border: 0; border-radius: 8px; padding: 9px 10px; background: transparent; color: var(--digicode-ink); text-align: left; font: 500 13px var(--digicode-font); cursor: pointer; }
|
|
214
|
+
.digicode-dropdown__item:hover { background: var(--digicode-surface-2); }
|
|
215
|
+
.digicode-dropdown__item--danger { color: var(--digicode-danger); }
|
|
216
|
+
.digicode-dropdown__separator { height: 1px; margin: 5px 2px; background: var(--digicode-line); }
|
|
217
|
+
.digicode-dropdown__label { padding: 6px 10px; color: var(--digicode-muted); font: 650 11px var(--digicode-font); text-transform: uppercase; letter-spacing: .04em; }
|
|
218
|
+
|
|
219
|
+
.digicode-tooltip { position: relative; display: inline-flex; }
|
|
220
|
+
.digicode-tooltip__content { pointer-events: none; position: absolute; z-index: 60; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%) translateY(3px); opacity: 0; min-width: max-content; max-width: 240px; padding: 6px 8px; border-radius: 7px; background: var(--digicode-heading); color: #fff; font: 500 11px/1.35 var(--digicode-font); transition: opacity .15s, transform .15s; }
|
|
221
|
+
.digicode-tooltip:hover .digicode-tooltip__content, .digicode-tooltip:focus-within .digicode-tooltip__content { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
222
|
+
|
|
223
|
+
.digicode-breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; color: var(--digicode-muted); font: 500 12px var(--digicode-font); }
|
|
224
|
+
.digicode-breadcrumb a { color: inherit; text-decoration: none; }
|
|
225
|
+
.digicode-breadcrumb a:hover { color: var(--digicode-primary); }
|
|
226
|
+
.digicode-breadcrumb__current { color: var(--digicode-heading); }
|
|
227
|
+
.digicode-breadcrumb__sep { color: #a0aab1; }
|
|
228
|
+
|
|
229
|
+
.digicode-pagination { display: flex; align-items: center; gap: 5px; }
|
|
230
|
+
.digicode-pagination__item { min-width: 36px; height: 36px; border: 1px solid var(--digicode-line); border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; background: var(--digicode-surface); color: var(--digicode-ink); font: 600 12px var(--digicode-font); cursor: pointer; }
|
|
231
|
+
.digicode-pagination__item:hover { border-color: var(--digicode-primary); color: var(--digicode-primary); }
|
|
232
|
+
.digicode-pagination__item[data-active="true"] { background: var(--digicode-ink); color: #fff; border-color: var(--digicode-ink); }
|
|
233
|
+
|
|
234
|
+
.digicode-table-wrap { overflow-x: auto; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius); background: var(--digicode-surface); }
|
|
235
|
+
.digicode-table { width: 100%; border-collapse: collapse; color: var(--digicode-ink); font: 400 13px/1.5 var(--digicode-font); }
|
|
236
|
+
.digicode-table th { padding: 11px 14px; background: var(--digicode-surface-2); color: var(--digicode-muted); text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .035em; }
|
|
237
|
+
.digicode-table td { padding: 13px 14px; border-top: 1px solid var(--digicode-line); }
|
|
238
|
+
.digicode-table tbody tr:hover { background: color-mix(in srgb, var(--digicode-surface-2) 60%, transparent); }
|
|
239
|
+
|
|
240
|
+
.digicode-empty { display: grid; place-items: center; text-align: center; gap: 8px; padding: 34px 24px; border: 1px dashed var(--digicode-line-strong); border-radius: var(--digicode-radius-lg); background: var(--digicode-surface); }
|
|
241
|
+
.digicode-empty__icon { width: 44px; height: 44px; display: grid; place-items: center; border-radius: 13px; background: var(--digicode-primary-soft); color: var(--digicode-primary); }
|
|
242
|
+
.digicode-empty__title { margin: 4px 0 0; color: var(--digicode-heading); font: 650 15px var(--digicode-font); }
|
|
243
|
+
.digicode-empty__description { margin: 0; max-width: 420px; color: var(--digicode-muted); font: 400 13px/1.55 var(--digicode-font); }
|
|
244
|
+
.digicode-empty__actions { margin-top: 6px; display: flex; gap: 8px; }
|
|
245
|
+
|
|
246
|
+
.digicode-stat { display: grid; gap: 9px; padding: 18px; border: 1px solid var(--digicode-line); border-radius: var(--digicode-radius-lg); background: var(--digicode-surface); box-shadow: var(--digicode-shadow-sm); }
|
|
247
|
+
.digicode-stat__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
248
|
+
.digicode-stat__label { color: var(--digicode-muted); font: 600 12px var(--digicode-font); }
|
|
249
|
+
.digicode-stat__icon { color: var(--digicode-primary); }
|
|
250
|
+
.digicode-stat__value { color: var(--digicode-heading); font: 700 28px/1 var(--digicode-font); letter-spacing: -.025em; }
|
|
251
|
+
.digicode-stat__delta { color: var(--digicode-muted); font: 500 11px var(--digicode-font); }
|
|
252
|
+
.digicode-stat__delta--up { color: var(--digicode-success); }
|
|
253
|
+
.digicode-stat__delta--down { color: var(--digicode-danger); }
|