app: shell + scificn-ui frontend (SCI-FI theme, brightened --text-muted)

scificn-ui v0.1.0 integrated copy-paste per its docs: Button/Panel/Badge/Card/Alert
in components/ui/, cn() helper in lib/utils.ts, theme tokens in app/globals.css.
Deliberate deviation from upstream: --text-muted #4A4A40 -> #6B6B5C (+12pt lightness)
for readability on the near-black background (default SCI-FI theme only). Landing page
proves the integration; no game UI yet.
This commit is contained in:
2026-09-28 15:56:24 +00:00
parent f6d2876a44
commit e688e9a0f0
10 changed files with 955 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const alertVariants = cva(
[
'relative w-full',
'border border-solid border-l-[3px]',
'p-4',
'font-mono',
'rounded-none',
],
{
variants: {
variant: {
STATUS: [
'border-[var(--border)]',
'border-l-[var(--color-green)]',
'bg-[var(--surface)]',
],
WARNING: [
'border-[var(--border)]',
'border-l-[var(--color-amber)]',
'bg-[var(--surface)]',
],
CRITICAL: [
'border-[var(--border)]',
'border-l-[var(--color-red)]',
'bg-[var(--surface)]',
],
INFO: [
'border-[var(--border)]',
'border-l-[var(--color-blue)]',
'bg-[var(--surface)]',
],
},
},
defaultVariants: { variant: 'STATUS' },
}
)
const prefixMap = {
STATUS: { symbol: '◈', color: 'var(--color-green)', glow: 'var(--text-glow-green)' },
WARNING: { symbol: '⚠', color: 'var(--color-amber)', glow: 'var(--text-glow-amber)' },
CRITICAL: { symbol: '✕', color: 'var(--color-red)', glow: 'var(--text-glow-red)' },
INFO: { symbol: 'ℹ', color: 'var(--color-blue)', glow: 'var(--text-glow-blue)' },
}
export interface AlertProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof alertVariants> {}
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
({ className, variant = 'STATUS', children, ...props }, ref) => {
const v = variant ?? 'STATUS'
const prefix = prefixMap[v]
return (
<div ref={ref} className={cn(alertVariants({ variant }), className)} role="alert" {...props}>
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'flex-start' }}>
<span
style={{
color: prefix.color,
textShadow: prefix.glow,
fontSize: '0.85rem',
lineHeight: 1.5,
flexShrink: 0,
}}
>
{prefix.symbol}
</span>
<div style={{ flex: 1 }}>{children}</div>
</div>
</div>
)
}
)
Alert.displayName = 'Alert'
/* ── AlertTitle ── */
const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
({ className, style, ...props }, ref) => (
<h5
ref={ref}
className={cn(className)}
style={{
fontSize: '0.75rem',
fontWeight: 600,
color: 'var(--text-secondary)',
letterSpacing: '0.08em',
textTransform: 'uppercase',
marginBottom: '0.25rem',
...style,
}}
{...props}
/>
)
)
AlertTitle.displayName = 'AlertTitle'
/* ── AlertDescription ── */
const AlertDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
({ className, style, ...props }, ref) => (
<p
ref={ref}
className={cn(className)}
style={{
fontSize: '0.8rem',
color: 'var(--text-muted)',
lineHeight: 1.6,
...style,
}}
{...props}
/>
)
)
AlertDescription.displayName = 'AlertDescription'
export { Alert, AlertTitle, AlertDescription, alertVariants }