Revert "feat: migrate frontend to Astro SSG with design system"
This reverts commit 8ad888da28.
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
variant?: "default" | "secondary" | "success" | "warning" | "destructive" | "outline";
|
||||
size?: "sm" | "default";
|
||||
dot?: boolean;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = "default",
|
||||
size = "default",
|
||||
dot = false,
|
||||
class: className = "",
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<span class:list={[`badge badge--${variant} badge--${size}`, className]}>
|
||||
{dot && <span class="badge__dot" aria-hidden="true" />}
|
||||
<slot />
|
||||
</span>
|
||||
|
||||
<style is:global>
|
||||
.badge {
|
||||
--fs-xs: 0.75rem;
|
||||
--fs-xxs: 0.625rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid transparent;
|
||||
font-weight: var(--fw-medium, 500);
|
||||
transition:
|
||||
background-color var(--duration-fast, 150ms) var(--ease-out, ease-out),
|
||||
color var(--duration-fast, 150ms) var(--ease-out, ease-out);
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.badge--default {
|
||||
padding-inline: 0.625rem;
|
||||
padding-block: 0.125rem;
|
||||
font-size: var(--fs-xs);
|
||||
background-color: oklch(var(--primary));
|
||||
color: oklch(var(--primary-foreground));
|
||||
}
|
||||
|
||||
.badge--secondary {
|
||||
padding-inline: 0.625rem;
|
||||
padding-block: 0.125rem;
|
||||
font-size: var(--fs-xs);
|
||||
background-color: oklch(var(--muted));
|
||||
color: oklch(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.badge--success {
|
||||
padding-inline: 0.625rem;
|
||||
padding-block: 0.125rem;
|
||||
font-size: var(--fs-xs);
|
||||
background-color: oklch(var(--success) / 0.15);
|
||||
color: oklch(var(--success));
|
||||
}
|
||||
|
||||
.badge--warning {
|
||||
padding-inline: 0.625rem;
|
||||
padding-block: 0.125rem;
|
||||
font-size: var(--fs-xs);
|
||||
background-color: oklch(var(--warning) / 0.15);
|
||||
color: oklch(var(--warning));
|
||||
}
|
||||
|
||||
.badge--destructive {
|
||||
padding-inline: 0.625rem;
|
||||
padding-block: 0.125rem;
|
||||
font-size: var(--fs-xs);
|
||||
background-color: oklch(var(--destructive) / 0.15);
|
||||
color: oklch(var(--destructive));
|
||||
}
|
||||
|
||||
.badge--outline {
|
||||
padding-inline: 0.625rem;
|
||||
padding-block: 0.125rem;
|
||||
font-size: var(--fs-xs);
|
||||
border-color: oklch(var(--border));
|
||||
background-color: transparent;
|
||||
color: oklch(var(--foreground));
|
||||
}
|
||||
|
||||
/* ── Size sm ───────────────────────────────────── */
|
||||
|
||||
.badge--sm {
|
||||
padding-inline: 0.375rem;
|
||||
padding-block: 0.0625rem;
|
||||
font-size: var(--fs-xxs);
|
||||
}
|
||||
|
||||
/* ── Dot indicator ─────────────────────────────── */
|
||||
|
||||
.badge__dot {
|
||||
display: inline-block;
|
||||
width: 0.375rem;
|
||||
height: 0.375rem;
|
||||
border-radius: 50%;
|
||||
background-color: currentColor;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
variant?: "primary" | "secondary" | "destructive" | "outline" | "ghost";
|
||||
size?: "sm" | "default" | "lg" | "icon";
|
||||
disabled?: boolean;
|
||||
href?: string;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = "primary",
|
||||
size = "default",
|
||||
disabled = false,
|
||||
href,
|
||||
class: className = "",
|
||||
} = Astro.props;
|
||||
|
||||
const Tag = href ? "a" : "button";
|
||||
|
||||
const attrs: Record<string, string | number | boolean> = {
|
||||
class: `btn btn--${variant} btn--${size} ${className}`,
|
||||
};
|
||||
if (Tag === "button") {
|
||||
attrs.disabled = disabled;
|
||||
} else if (disabled) {
|
||||
attrs["aria-disabled"] = true;
|
||||
attrs.role = "link";
|
||||
}
|
||||
---
|
||||
|
||||
<Tag {...attrs}>
|
||||
<slot />
|
||||
</Tag>
|
||||
|
||||
<style is:global>
|
||||
.btn {
|
||||
--rd-md: calc(var(--radius, 1rem) - 2px);
|
||||
--fs-sm: 0.875rem;
|
||||
--fw-medium: 500;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
white-space: nowrap;
|
||||
border-radius: var(--rd-md);
|
||||
font-size: var(--fs-sm);
|
||||
font-weight: var(--fw-medium);
|
||||
line-height: 1.25rem;
|
||||
transition:
|
||||
background-color var(--duration-fast, 150ms) var(--ease-out, ease-out),
|
||||
color var(--duration-fast, 150ms) var(--ease-out, ease-out),
|
||||
border-color var(--duration-fast, 150ms) var(--ease-out, ease-out),
|
||||
box-shadow var(--duration-fast, 150ms) var(--ease-out, ease-out),
|
||||
transform var(--duration-fast, 150ms) var(--ease-out, ease-out);
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.btn:focus-visible {
|
||||
outline: 2px solid oklch(var(--ring));
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
.btn:disabled,
|
||||
.btn[aria-disabled="true"] {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* ── Variants ──────────────────────────────────────────── */
|
||||
|
||||
.btn--primary {
|
||||
background-color: oklch(var(--primary));
|
||||
color: oklch(var(--primary-foreground));
|
||||
box-shadow: 0 1px 2px oklch(0 0 0 / 0.05);
|
||||
}
|
||||
.btn--primary:hover {
|
||||
background-color: oklch(var(--primary) / 0.9);
|
||||
}
|
||||
|
||||
.btn--secondary {
|
||||
background-color: oklch(var(--secondary));
|
||||
color: oklch(var(--secondary-foreground));
|
||||
}
|
||||
.btn--secondary:hover {
|
||||
background-color: oklch(var(--secondary) / 0.8);
|
||||
}
|
||||
|
||||
.btn--destructive {
|
||||
background-color: oklch(var(--destructive));
|
||||
color: oklch(var(--destructive-foreground));
|
||||
box-shadow: 0 1px 2px oklch(0 0 0 / 0.05);
|
||||
}
|
||||
.btn--destructive:hover {
|
||||
background-color: oklch(var(--destructive) / 0.9);
|
||||
}
|
||||
|
||||
.btn--outline {
|
||||
border-color: oklch(var(--border));
|
||||
background-color: oklch(var(--background));
|
||||
color: oklch(var(--foreground));
|
||||
}
|
||||
.btn--outline:hover {
|
||||
background-color: oklch(var(--accent));
|
||||
color: oklch(var(--accent-foreground));
|
||||
}
|
||||
|
||||
.btn--ghost {
|
||||
background-color: transparent;
|
||||
color: oklch(var(--foreground));
|
||||
}
|
||||
.btn--ghost:hover {
|
||||
background-color: oklch(var(--accent));
|
||||
color: oklch(var(--accent-foreground));
|
||||
}
|
||||
|
||||
/* ── Sizes ─────────────────────────────────────────────── */
|
||||
|
||||
.btn--sm {
|
||||
height: 2.25rem;
|
||||
padding-inline: 0.75rem;
|
||||
}
|
||||
|
||||
.btn--default {
|
||||
height: 2.5rem;
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
|
||||
.btn--lg {
|
||||
height: 2.75rem;
|
||||
padding-inline: 2rem;
|
||||
}
|
||||
|
||||
.btn--icon {
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,101 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
variant?: "default" | "elevated" | "glass" | "interactive";
|
||||
padding?: "none" | "sm" | "md" | "lg";
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = "default",
|
||||
padding = "md",
|
||||
class: className = "",
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<div class:list={[`card card--${variant} card--pad-${padding}`, className]}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style is:global>
|
||||
.card {
|
||||
--rd-lg: var(--radius, 1rem);
|
||||
border-radius: var(--rd-lg);
|
||||
transition:
|
||||
background-color var(--duration-normal, 300ms) var(--ease-out, ease-out),
|
||||
color var(--duration-normal, 300ms) var(--ease-out, ease-out),
|
||||
border-color var(--duration-normal, 300ms) var(--ease-out, ease-out),
|
||||
box-shadow var(--duration-normal, 300ms) var(--ease-out, ease-out),
|
||||
transform var(--duration-normal, 300ms) var(--ease-out, ease-out);
|
||||
}
|
||||
|
||||
/* ── Padding variants ──────────────────────────── */
|
||||
|
||||
.card--pad-none {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.card--pad-sm {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.card--pad-md {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.card--pad-lg {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
/* ── Variant: default ──────────────────────────── */
|
||||
|
||||
.card--default {
|
||||
background-color: oklch(var(--card));
|
||||
color: oklch(var(--card-foreground));
|
||||
border: 1px solid oklch(var(--border));
|
||||
box-shadow: 0 1px 2px oklch(0 0 0 / 0.05);
|
||||
}
|
||||
|
||||
/* ── Variant: elevated ─────────────────────────── */
|
||||
|
||||
.card--elevated {
|
||||
background-color: oklch(var(--card));
|
||||
color: oklch(var(--card-foreground));
|
||||
border: 1px solid oklch(var(--border));
|
||||
box-shadow:
|
||||
0 4px 6px -1px oklch(0 0 0 / 0.1),
|
||||
0 2px 4px -2px oklch(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
/* ── Variant: glass ────────────────────────────── */
|
||||
|
||||
.card--glass {
|
||||
background-color: oklch(var(--glass-bg));
|
||||
border: 1px solid oklch(var(--glass-border));
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
box-shadow: 0 4px 24px oklch(var(--glass-shadow));
|
||||
}
|
||||
|
||||
/* ── Variant: interactive ──────────────────────── */
|
||||
|
||||
.card--interactive {
|
||||
background-color: oklch(var(--card));
|
||||
color: oklch(var(--card-foreground));
|
||||
border: 1px solid oklch(var(--border));
|
||||
box-shadow: 0 1px 2px oklch(0 0 0 / 0.05);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card--interactive:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow:
|
||||
0 10px 15px -3px oklch(0 0 0 / 0.1),
|
||||
0 4px 6px -4px oklch(0 0 0 / 0.1);
|
||||
border-color: oklch(var(--primary) / 0.3);
|
||||
}
|
||||
|
||||
.card--interactive:focus-visible {
|
||||
outline: 2px solid oklch(var(--ring));
|
||||
outline-offset: 2px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
severity: "safe" | "low" | "medium" | "high" | "critical";
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { severity, class: className = "" } = Astro.props;
|
||||
|
||||
const ICONS: Record<string, string> = {
|
||||
safe: "✔",
|
||||
low: "↗",
|
||||
medium: "⚠",
|
||||
high: "⚡",
|
||||
critical: "✖",
|
||||
};
|
||||
|
||||
const icon = ICONS[severity] ?? "";
|
||||
---
|
||||
|
||||
<span
|
||||
class:list={[`severity-badge severity-badge--${severity}`, className]}
|
||||
data-severity={severity}
|
||||
role="status"
|
||||
>
|
||||
<span class="severity-badge__icon" aria-hidden="true" set:html={icon} />
|
||||
<span class="severity-badge__label"><slot /></span>
|
||||
</span>
|
||||
|
||||
<style is:global>
|
||||
.severity-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
padding-inline: 0.5rem;
|
||||
padding-block: 0.2rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
border: 1px solid transparent;
|
||||
line-height: 1;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.severity-badge__icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.severity-badge__label {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
/* ── Severity: safe → success ──────────────────── */
|
||||
|
||||
.severity-badge--safe {
|
||||
background-color: oklch(var(--success) / 0.15);
|
||||
color: oklch(var(--success));
|
||||
border-color: oklch(var(--success) / 0.25);
|
||||
}
|
||||
|
||||
/* ── Severity: low → info ──────────────────────── */
|
||||
|
||||
.severity-badge--low {
|
||||
background-color: oklch(var(--info) / 0.15);
|
||||
color: oklch(var(--info));
|
||||
border-color: oklch(var(--info) / 0.25);
|
||||
}
|
||||
|
||||
/* ── Severity: medium → warning ────────────────── */
|
||||
|
||||
.severity-badge--medium {
|
||||
background-color: oklch(var(--warning) / 0.15);
|
||||
color: oklch(var(--warning));
|
||||
border-color: oklch(var(--warning) / 0.25);
|
||||
}
|
||||
|
||||
/* ── Severity: high → destructive ──────────────── */
|
||||
|
||||
.severity-badge--high {
|
||||
background-color: oklch(var(--destructive) / 0.12);
|
||||
color: oklch(var(--destructive));
|
||||
border-color: oklch(var(--destructive) / 0.2);
|
||||
}
|
||||
|
||||
/* ── Severity: critical ────────────────────────── */
|
||||
|
||||
.severity-badge--critical {
|
||||
background-color: oklch(var(--destructive) / 0.25);
|
||||
color: oklch(var(--destructive));
|
||||
border-color: oklch(var(--destructive) / 0.4);
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
variant?: "text" | "card" | "circle" | "rect";
|
||||
width?: string;
|
||||
height?: string;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = "text",
|
||||
width,
|
||||
height,
|
||||
class: className = "",
|
||||
} = Astro.props;
|
||||
|
||||
const style: Record<string, string> = {};
|
||||
if (width) style.width = width;
|
||||
if (height) style.height = height;
|
||||
---
|
||||
|
||||
<div
|
||||
aria-hidden="true"
|
||||
role="presentation"
|
||||
class:list={[`skeleton skeleton--${variant}`, className]}
|
||||
style={Object.keys(style).length > 0 ? style : undefined}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style is:global>
|
||||
.skeleton {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
oklch(var(--muted)) 25%,
|
||||
oklch(var(--muted-foreground) / 0.15) 50%,
|
||||
oklch(var(--muted)) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s ease-in-out infinite;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/* ── Variant: text (default) ───────────────────── */
|
||||
|
||||
.skeleton--text {
|
||||
width: 100%;
|
||||
height: 1rem;
|
||||
border-radius: calc(var(--radius, 1rem) - 4px);
|
||||
}
|
||||
|
||||
/* ── Variant: card ─────────────────────────────── */
|
||||
|
||||
.skeleton--card {
|
||||
width: 100%;
|
||||
height: 8rem;
|
||||
border-radius: var(--radius, 1rem);
|
||||
}
|
||||
|
||||
/* ── Variant: circle ───────────────────────────── */
|
||||
|
||||
.skeleton--circle {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* ── Variant: rect ─────────────────────────────── */
|
||||
|
||||
.skeleton--rect {
|
||||
width: 100%;
|
||||
height: 3rem;
|
||||
border-radius: calc(var(--radius, 1rem) - 2px);
|
||||
}
|
||||
</style>
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
size?: "sm" | "default" | "lg";
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { size = "default", class: className = "" } = Astro.props;
|
||||
---
|
||||
|
||||
<span
|
||||
aria-label="Loading"
|
||||
role="status"
|
||||
class:list={[`spinner spinner--${size}`, className]}
|
||||
>
|
||||
<span class="spinner__ring" aria-hidden="true" />
|
||||
</span>
|
||||
|
||||
<style is:global>
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.spinner__ring {
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
border-style: solid;
|
||||
border-color: oklch(var(--muted));
|
||||
border-top-color: oklch(var(--primary));
|
||||
animation: spin 0.6s linear infinite;
|
||||
}
|
||||
|
||||
/* ── Sizes ─────────────────────────────────────── */
|
||||
|
||||
.spinner--sm .spinner__ring {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.spinner--default .spinner__ring {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border-width: 2.5px;
|
||||
}
|
||||
|
||||
.spinner--lg .spinner__ring {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border-width: 3px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user