Remove glows, refine feature legend, forms, and showcase pages
- Delete glows.css and GlowsPage (unused) - Enhance DTFeatureLegend and feature-legend.css with improved layout - Update DTRadioGroup styling - Refine bevels.css, forms-dt.css - Update AnimationsPage, CardsAdvancedPage, FormsPage, HomePage - Add type:module to web package.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { DTCard, DTStaggerContainer } from '@dangerousthings/react';
|
||||
import { Section, Row, CodeLabel } from '../components/Section';
|
||||
|
||||
@@ -25,6 +25,69 @@ function AnimBox({ className, label }: { className: string; label: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
const VARIANTS = ['normal', 'emphasis', 'warning', 'success', 'other'] as const;
|
||||
|
||||
function ProgressBarDemo() {
|
||||
const [progress, setProgress] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
const [running, setRunning] = useState(false);
|
||||
|
||||
const animate = () => {
|
||||
// Reset then animate up
|
||||
setProgress([0, 0, 0, 0, 0]);
|
||||
setRunning(true);
|
||||
let tick = 0;
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
intervalRef.current = setInterval(() => {
|
||||
tick++;
|
||||
setProgress(prev =>
|
||||
prev.map((_, i) => Math.min(100, Math.round(tick * (1.5 + i * 0.4))))
|
||||
);
|
||||
if (tick > 80) {
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
setRunning(false);
|
||||
}
|
||||
}, 40);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Auto-run on mount
|
||||
const t = setTimeout(animate, 500);
|
||||
return () => {
|
||||
clearTimeout(t);
|
||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', marginBottom: 16 }}>
|
||||
{VARIANTS.map((v, i) => (
|
||||
<DTCard
|
||||
key={v}
|
||||
variant={v}
|
||||
title={`${v.toUpperCase()} ${progress[i]}%`}
|
||||
progress={progress[i]}
|
||||
style={{ width: 160, transition: 'all 0.1s ease-out' }}
|
||||
>
|
||||
<div className="card-body" style={{ fontSize: '0.75rem', minHeight: 60, display: 'flex', alignItems: 'center' }}>
|
||||
Progress fills the left edge from bottom to top
|
||||
</div>
|
||||
</DTCard>
|
||||
))}
|
||||
</div>
|
||||
<button
|
||||
className="btn-secondary"
|
||||
onClick={animate}
|
||||
disabled={running}
|
||||
type="button"
|
||||
>
|
||||
{running ? 'ANIMATING...' : 'REPLAY PROGRESS'}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function AnimationsPage() {
|
||||
const [entranceKey, setEntranceKey] = useState(0);
|
||||
const [staggerKey, setStaggerKey] = useState(0);
|
||||
@@ -126,6 +189,11 @@ export function AnimationsPage() {
|
||||
<CodeLabel text=".dt-transition-accordion | .dt-transition-chevron | .dt-transition-progress" />
|
||||
</Section>
|
||||
|
||||
<Section title="Card Progress Bar" description="Cards have a vertical progress bar on the left edge. Animate it by transitioning --dt-card-progress from 0 to 100.">
|
||||
<ProgressBarDemo />
|
||||
<CodeLabel text="<DTCard progress={value} /> — CSS ::after gradient driven by --dt-card-progress" />
|
||||
</Section>
|
||||
|
||||
<Section title="Scrollbar Styling" description="Thin neon scrollbar scoped under [data-brand='dt'].">
|
||||
<div
|
||||
className="dt-scrollbar"
|
||||
|
||||
@@ -33,30 +33,31 @@ const modes: DTVariant[] = ['normal', 'emphasis', 'warning', 'success', 'other']
|
||||
const ico = (C: any) => createElement(C, { style: { fontSize: '2rem' } });
|
||||
|
||||
// Full chip feature legend (9 features — from storefront UseCaseLegend)
|
||||
// detail text simulates what the storefront shows for an NExT implant
|
||||
const chipFeatures: DTFeatureItem[] = [
|
||||
{ key: 'smartphone', name: 'Smartphone', icon: ico(MdOutlinePhonelinkRing), state: 'supported' },
|
||||
{ key: 'access_control', name: 'Access Control', icon: ico(MdOutlineVpnKey), state: 'supported' },
|
||||
{ key: 'digital_security', name: 'Digital Security', icon: ico(FaUserShield), state: 'supported' },
|
||||
{ key: 'cryptography', name: 'Cryptography', icon: ico(LuBinary), state: 'unsupported' },
|
||||
{ key: 'data_sharing', name: 'Data Sharing', icon: ico(MdOutlineMobileScreenShare), state: 'supported' },
|
||||
{ key: 'payment', name: 'Payment', icon: ico(MdOutlineCreditCard), state: 'disabled' },
|
||||
{ key: 'magic', name: 'UID Magic', icon: ico(MdOutlineCopyAll), state: 'supported' },
|
||||
{ key: 'illumination', name: 'Illumination', icon: ico(MdOutlineLightbulb), state: 'unsupported' },
|
||||
{ key: 'temperature', name: 'Temperature', icon: ico(MdOutlineThermostat), state: 'unsupported' },
|
||||
{ key: 'smartphone', name: 'Smartphone', icon: ico(MdOutlinePhonelinkRing), state: 'supported', detail: 'Full NFC smartphone support' },
|
||||
{ key: 'access_control', name: 'Access Control', icon: ico(MdOutlineVpnKey), state: 'supported', detail: 'DESFire, MIFARE Classic, iCLASS' },
|
||||
{ key: 'digital_security', name: 'Digital Security', icon: ico(FaUserShield), state: 'supported', detail: 'FIDO2 / WebAuthn' },
|
||||
{ key: 'cryptography', name: 'Cryptography', icon: ico(LuBinary), state: 'unsupported', detail: 'Not Supported' },
|
||||
{ key: 'data_sharing', name: 'Data Sharing', icon: ico(MdOutlineMobileScreenShare), state: 'supported', detail: 'NDEF records, vCard, URL' },
|
||||
{ key: 'payment', name: 'Payment', icon: ico(MdOutlineCreditCard), state: 'disabled', detail: 'Apex required' },
|
||||
{ key: 'magic', name: 'Magic', icon: ico(MdOutlineCopyAll), state: 'supported', detail: 'Gen2 Magic UID' },
|
||||
{ key: 'Illumination', name: 'Illumination', icon: ico(MdOutlineLightbulb), state: 'unsupported', detail: 'None' },
|
||||
{ key: 'temperature', name: 'Sensors', icon: ico(MdOutlineThermostat), state: 'unsupported', detail: 'None' },
|
||||
];
|
||||
|
||||
// Full biomagnet feature legend (4 features — from storefront MagnetUseCaseLegend)
|
||||
const magnetFeatures: DTFeatureItem[] = [
|
||||
{ key: 'sensing', name: 'Sensing', icon: ico(MdOutlineSensors), state: 'supported' },
|
||||
{ key: 'lifting', name: 'Lifting', icon: ico(MdOutlineFitbit), state: 'supported' },
|
||||
{ key: 'haptics', name: 'Haptics', icon: ico(MdOutlineVibration), state: 'supported' },
|
||||
{ key: 'polarity', name: 'Polarity Detection', icon: ico(MdOutlineExplore), state: 'unsupported' },
|
||||
{ key: 'sensing', name: 'Sensing', icon: ico(MdOutlineSensors), state: 'supported', detail: 'Electromagnetic field detection' },
|
||||
{ key: 'lifting', name: 'Lifting', icon: ico(MdOutlineFitbit), state: 'supported', detail: '2.1 kg lifting force' },
|
||||
{ key: 'haptics', name: 'Haptics', icon: ico(MdOutlineVibration), state: 'supported', detail: 'Tactile vibration feedback' },
|
||||
{ key: 'polarity', name: 'Polarity Detection', icon: ico(MdOutlineExplore), state: 'unsupported', detail: 'Not Supported' },
|
||||
];
|
||||
|
||||
// Full aesthetic feature legend (2 features — from storefront AestheticUseCaseLegend)
|
||||
const aestheticFeatures: DTFeatureItem[] = [
|
||||
{ key: 'illumination', name: 'Illumination', icon: ico(MdLightbulbOutline), state: 'supported' },
|
||||
{ key: 'prominence', name: 'Prominence', icon: ico(MdOutlineVisibility), state: 'supported' },
|
||||
{ key: 'illumination', name: 'Illumination', icon: ico(MdLightbulbOutline), state: 'supported', detail: 'LED: Red, Green, Blue, White' },
|
||||
{ key: 'prominence', name: 'Prominence', icon: ico(MdOutlineVisibility), state: 'supported', detail: 'High visibility under skin' },
|
||||
];
|
||||
|
||||
export function CardsAdvancedPage() {
|
||||
@@ -108,30 +109,36 @@ export function CardsAdvancedPage() {
|
||||
<CodeLabel text=".dt-badge-parent > .dt-card-badge — badge positioned on card image container" />
|
||||
</Section>
|
||||
|
||||
<Section title="Buttons" description="Beveled buttons with active/selected states, mode colors, and level indentation.">
|
||||
<Section title="Buttons" description="Beveled buttons with active/selected states and mode colors. Nested levels use inline paddingLeft.">
|
||||
<div style={{ maxWidth: 300 }}>
|
||||
{['All Products', 'NFC Implants', 'RFID Tags', 'Accessories', 'Lab Products'].map((item, i) => (
|
||||
{[
|
||||
{ name: 'All Products', cls: ' active', pad: 0 },
|
||||
{ name: 'NFC Implants', cls: '', pad: 0 },
|
||||
{ name: 'RFID Tags', cls: '', pad: 32 },
|
||||
{ name: 'Accessories', cls: '', pad: 32 },
|
||||
{ name: 'Lab Products', cls: ' mode-warning', pad: 0 },
|
||||
].map(item => (
|
||||
<button
|
||||
key={item}
|
||||
className={`dt-menu-item${i === 0 ? ' active' : ''}${i === 4 ? ' mode-warning' : ''}`}
|
||||
style={i > 1 && i < 4 ? { '--dt-menu-level': '1' } as CSSProperties : undefined}
|
||||
key={item.name}
|
||||
className={`dt-menu-item${item.cls}`}
|
||||
style={item.pad ? { paddingLeft: item.pad } : undefined}
|
||||
type="button"
|
||||
>
|
||||
{item}
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<CodeLabel text=".dt-menu-item | .dt-menu-item.active | --dt-menu-level: 1" />
|
||||
<CodeLabel text=".dt-menu-item | .active | paddingLeft for nesting" />
|
||||
</Section>
|
||||
|
||||
<Section title="Feature Legends" description="Product feature grids from the storefront. Icons indicate feature capabilities; color indicates state.">
|
||||
<DTFeatureLegend features={chipFeatures} title="NFC CHIP FEATURES" variant="normal" columns={5} />
|
||||
<Section title="Feature Legends" description="Interactive product feature grids from the storefront. Hover icons for details. Toggle labels with the ? button.">
|
||||
<DTFeatureLegend features={chipFeatures} title="NExT Features" variant="normal" columns={5} />
|
||||
<div style={{ height: 'var(--space-6)' }} />
|
||||
<DTFeatureLegend features={magnetFeatures} title="BIOMAGNET FEATURES" variant="emphasis" columns={4} />
|
||||
<DTFeatureLegend features={magnetFeatures} title="Titan Features" variant="emphasis" columns={4} />
|
||||
<div style={{ height: 'var(--space-6)' }} />
|
||||
<DTFeatureLegend features={aestheticFeatures} title="AESTHETIC FEATURES" variant="other" columns={2} />
|
||||
<DTFeatureLegend features={aestheticFeatures} title="xLED Features" variant="other" columns={2} />
|
||||
<div style={{ height: 'var(--space-4)' }} />
|
||||
<CodeLabel text="<DTFeatureLegend features={chipFeatures} title='NFC CHIP FEATURES' variant='normal' />" />
|
||||
<CodeLabel text="<DTFeatureLegend features={chipFeatures} title='NExT Features' variant='normal' />" />
|
||||
<CodeLabel text="<DTFeatureLegend features={magnetFeatures} variant='emphasis' columns={4} />" />
|
||||
<CodeLabel text="<DTFeatureLegend features={aestheticFeatures} variant='other' columns={2} />" />
|
||||
<div style={{ marginTop: 'var(--space-3)', display: 'flex', gap: 'var(--space-4)', fontSize: '0.75rem' }}>
|
||||
|
||||
@@ -102,20 +102,26 @@ export function FormsPage() {
|
||||
<CodeLabel text=".dt-filter-header | .dt-filter-header.active" />
|
||||
</Section>
|
||||
|
||||
<Section title="Buttons" description="Beveled buttons with active state, mode colors, and level indentation.">
|
||||
<Section title="Buttons" description="Beveled buttons with active state and mode colors. Nested levels use inline paddingLeft.">
|
||||
<div style={{ maxWidth: 300 }}>
|
||||
{['All Products', 'NFC Implants', 'RFID Tags', 'Accessories', 'Lab Products'].map((name, i) => (
|
||||
{[
|
||||
{ name: 'All Products', cls: ' active', pad: 0 },
|
||||
{ name: 'NFC Implants', cls: '', pad: 0 },
|
||||
{ name: 'RFID Tags', cls: '', pad: 32 },
|
||||
{ name: 'Accessories', cls: '', pad: 32 },
|
||||
{ name: 'Lab Products', cls: ' mode-warning', pad: 0 },
|
||||
].map(item => (
|
||||
<button
|
||||
key={name}
|
||||
className={`dt-menu-item${i === 0 ? ' active' : ''}${i === 4 ? ' mode-warning' : ''}`}
|
||||
style={(i === 2 || i === 3) ? { '--dt-menu-level': '1' } as React.CSSProperties : undefined}
|
||||
key={item.name}
|
||||
className={`dt-menu-item${item.cls}`}
|
||||
style={item.pad ? { paddingLeft: item.pad } : undefined}
|
||||
type="button"
|
||||
>
|
||||
{name}
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<CodeLabel text=".dt-menu-item | .active | --dt-menu-level: 1" />
|
||||
<CodeLabel text=".dt-menu-item | .active | paddingLeft for nesting" />
|
||||
</Section>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
import { DTCard } from '@dangerousthings/react';
|
||||
import { Section, Row, CodeLabel } from '../components/Section';
|
||||
|
||||
export function GlowsPage() {
|
||||
return (
|
||||
<>
|
||||
<h1 className="page-title">Glows</h1>
|
||||
<p className="page-subtitle">Neon drop-shadow and text-shadow effects. Active on the DT brand.</p>
|
||||
|
||||
<Section title="Button Glows" description="filter: drop-shadow() follows clip-path shape. Hover for enhanced glow.">
|
||||
<Row>
|
||||
<button className="btn-primary" type="button">PRIMARY GLOW</button>
|
||||
<button className="btn-danger" type="button">DANGER GLOW</button>
|
||||
</Row>
|
||||
<CodeLabel text={'.btn-primary / .btn-danger — automatic on [data-brand="dt"]'} />
|
||||
<br />
|
||||
<Row>
|
||||
<button className="btn-secondary" type="button">SECONDARY (HOVER)</button>
|
||||
</Row>
|
||||
<CodeLabel text=".btn-secondary — glow on hover" />
|
||||
</Section>
|
||||
|
||||
<Section title="Link Glow" description="text-shadow on hover. Respects --dt-glow-color when set by a parent mode.">
|
||||
<Row>
|
||||
<a href="#" style={{ color: 'var(--color-primary)', fontWeight: 600, fontSize: '1.125rem' }}>
|
||||
Hover this link for text glow
|
||||
</a>
|
||||
</Row>
|
||||
<CodeLabel text="a:hover — uses var(--dt-glow-color, var(--color-primary))" />
|
||||
</Section>
|
||||
|
||||
<Section title="Mode-Aware Link Glow" description="Links inside mode containers glow with that mode's color.">
|
||||
<Row>
|
||||
{(['normal', 'emphasis', 'warning', 'success', 'other'] as const).map(mode => (
|
||||
<div key={mode} className={`mode-${mode}`} style={{ padding: 'var(--space-3)' }}>
|
||||
<a href="#" style={{ fontWeight: 600, fontSize: '1rem' }}>{mode.toUpperCase()}</a>
|
||||
</div>
|
||||
))}
|
||||
</Row>
|
||||
<CodeLabel text=".mode-emphasis a:hover — glows yellow via --dt-glow-color" />
|
||||
</Section>
|
||||
|
||||
<Section title="Terminal Inset Glow" description="Inset + outer box-shadow. No clip-path so box-shadow works directly.">
|
||||
<div className="terminal dt-accent-top">
|
||||
<code>{'$ dt-web-theme --install\n> Installing design tokens...\n> Applying cyberpunk aesthetic...\n> Done. Welcome to the future.'}</code>
|
||||
</div>
|
||||
<CodeLabel text={'.terminal — automatic on [data-brand="dt"]'} />
|
||||
</Section>
|
||||
|
||||
<Section title="Card Hover Glow" description="filter: drop-shadow() respects the beveled clip-path.">
|
||||
<DTCard title="HOVER ME" style={{ cursor: 'pointer' }}>
|
||||
<div className="card-body">Cards get a drop-shadow glow on hover.</div>
|
||||
</DTCard>
|
||||
<CodeLabel text={'.card:hover — automatic on [data-brand="dt"]'} />
|
||||
</Section>
|
||||
|
||||
<Section title="Input Focus Glow" description="box-shadow: 0 4px 0 1px — bright bar beneath the input.">
|
||||
<input
|
||||
type="text"
|
||||
className="input"
|
||||
placeholder="Click to focus — see the glow bar"
|
||||
style={{ maxWidth: 400 }}
|
||||
/>
|
||||
<CodeLabel text={'.input:focus — automatic on [data-brand="dt"]'} />
|
||||
</Section>
|
||||
|
||||
<Section title="Glow Utilities" description="Generic utility classes for applying glow effects to any element.">
|
||||
<Row>
|
||||
<div className="dt-glow" style={{ background: 'var(--color-primary)', padding: 'var(--space-4) var(--space-6)', display: 'inline-block', fontWeight: 700, color: 'var(--color-bg)' }}>.dt-glow</div>
|
||||
<div className="dt-glow-strong" style={{ background: 'var(--color-primary)', padding: 'var(--space-4) var(--space-6)', display: 'inline-block', fontWeight: 700, color: 'var(--color-bg)' }}>.dt-glow-strong</div>
|
||||
</Row>
|
||||
<CodeLabel text=".dt-glow | .dt-glow-strong" />
|
||||
<Row>
|
||||
<div className="dt-glow-inset" style={{ padding: 'var(--space-4) var(--space-6)', display: 'inline-block', fontWeight: 700, border: '1px solid var(--color-border)' }}>.dt-glow-inset</div>
|
||||
<div className="dt-text-glow" style={{ fontSize: '1.25rem', fontWeight: 700, color: 'var(--color-primary)', display: 'inline-block' }}>.dt-text-glow</div>
|
||||
</Row>
|
||||
<CodeLabel text=".dt-glow-inset | .dt-text-glow" />
|
||||
</Section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import { Section, CodeLabel } from '../components/Section';
|
||||
|
||||
const categories: { hash: string; title: string; desc: string; mode: DTVariant; count: number }[] = [
|
||||
{ hash: 'bevels', title: 'Bevels', desc: 'Angular clip-path patterns — cards, buttons, badges, media frames, modals, drawers', mode: 'normal', count: 8 },
|
||||
{ hash: 'glows', title: 'Glows', desc: 'Neon drop-shadow and text-shadow effects for the DT brand', mode: 'emphasis', count: 6 },
|
||||
{ hash: 'forms', title: 'Forms', desc: 'Text inputs, checkboxes, switches, radios, progress bars, accordions, steppers', mode: 'success', count: 7 },
|
||||
{ hash: 'animations', title: 'Animations', desc: 'Entrance animations, stagger containers, transition utilities, scrollbar styling', mode: 'other', count: 5 },
|
||||
{ hash: 'cards-advanced', title: 'Advanced Cards', desc: 'Card color modes, progress bars, badge overlays, interactive bevel buttons, feature legend', mode: 'warning', count: 6 },
|
||||
|
||||
Reference in New Issue
Block a user