Skip to content

Commit 7debf21

Browse files
UltraDAGcomClaude Opus 4.6 (1M context)
andcommitted
Enforce strict 2-color theme across entire dashboard
Color enforcement: - Primary accent #00E0C4 (cyan) for ALL primary buttons, active states, success indicators, positive values, and links - #EF4444 (red) ONLY for errors and destructive actions (Unstake, Reject) - Removed #0066FF (blue), #A855F7 (purple), #FFB800 (yellow) from ALL buttons — these only remain as badge/status indicator colors Button standardization (from theme.ts): - primaryButtonStyle: solid cyan, dark text — Create, Submit, Pay, Send, Stake, Unlock, Continue, Save - secondaryButtonStyle: subtle bg + border — Cancel, Back, View on GitHub - dangerButtonStyle: red tinted — Remove, Unstake, Reject - buttonStyle(): ghost/outline — Refresh, Select, Edit, small actions Converted 4 Tailwind-only components to inline CSS variables: - CreateKeystoreModal, VertexCard, RoundTable, MempoolTable (text-slate-*, bg-slate-*, border-slate-* → var(--dag-*)) Removed ALL gradient buttons (linear-gradient → solid #00E0C4): - App.tsx unlock screen, PasskeyOnboarding (4 buttons), BountyPage, BountyDetail, PayBountyModal, EditProfileModal, StreamsPage, WalletPage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 88bee99 commit 7debf21

26 files changed

Lines changed: 2881 additions & 2830 deletions

dashboard/src/App.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { getNodeUrl, getNetwork, switchNetwork, type NetworkType } from './lib/a
3232
import { ToastProvider } from './hooks/useToast';
3333
import { NameCacheProvider } from './contexts/NameCacheContext';
3434
import { AppStatusProvider } from './contexts/AppStatusContext';
35+
import { primaryButtonStyle, secondaryButtonStyle } from './lib/theme';
3536

3637
function App() {
3738
const pk = usePasskeyWallet();
@@ -137,19 +138,17 @@ function App() {
137138
</p>
138139

139140
<button onClick={async () => { await pk.unlock(); }} style={{
140-
width: '100%', padding: '14px 0', borderRadius: 12,
141-
background: 'linear-gradient(135deg, #00E0C4, #0066FF)',
142-
color: '#fff', fontSize: 14, fontWeight: 700, cursor: 'pointer', border: 'none',
143-
boxShadow: '0 4px 20px rgba(0,224,196,0.2)',
144-
transition: 'opacity 0.2s',
141+
...primaryButtonStyle, width: '100%', padding: '14px 0', borderRadius: 12,
142+
fontSize: 14,
145143
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
146144
}}>
147145
◎ Unlock with Biometrics
148146
</button>
149147

150148
<button onClick={() => pk.destroy()} style={{
151-
background: 'none', border: 'none', color: 'var(--dag-text-faint)',
152-
fontSize: 11, cursor: 'pointer', marginTop: 20, transition: 'color 0.2s',
149+
...secondaryButtonStyle, background: 'none', border: 'none',
150+
color: 'var(--dag-text-faint)', fontSize: 11, marginTop: 20,
151+
padding: 0,
153152
}}>
154153
Start Fresh
155154
</button>

dashboard/src/components/bounty/BountyDetail.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { severityInfo, statusColor, bountyDescription, timeAgo, type ParsedBounty } from '../../lib/github';
22
import { DisplayIdentity } from '../shared/DisplayIdentity';
3+
import { primaryButtonStyle, secondaryButtonStyle } from '../../lib/theme';
34

45
interface BountyDetailProps {
56
bounty: ParsedBounty | null;
@@ -96,20 +97,15 @@ export function BountyDetail({ bounty, unlocked, onPayClick }: BountyDetailProps
9697
target="_blank"
9798
rel="noopener noreferrer"
9899
style={{
99-
flex: 1, padding: '10px 0', borderRadius: 8, textAlign: 'center',
100-
background: 'var(--dag-input-bg)', border: '1px solid var(--dag-border)',
101-
color: 'var(--dag-text)', fontSize: 12, fontWeight: 600, textDecoration: 'none',
102-
cursor: 'pointer', transition: 'border-color 0.15s',
100+
...secondaryButtonStyle, flex: 1, padding: '10px 0', textAlign: 'center' as const,
101+
textDecoration: 'none',
103102
}}
104103
>
105104
View on GitHub →
106105
</a>
107106
{canPay && (
108107
<button onClick={onPayClick} style={{
109-
flex: 1, padding: '10px 0', borderRadius: 8, border: 'none',
110-
background: 'linear-gradient(135deg, #00E0C4, #0066FF)',
111-
color: '#fff', fontSize: 12, fontWeight: 700, cursor: 'pointer',
112-
boxShadow: '0 2px 12px rgba(0,224,196,0.2)',
108+
...primaryButtonStyle, flex: 1, padding: '10px 0',
113109
}}>
114110
Pay Bounty
115111
</button>

dashboard/src/components/bounty/PayBountyModal.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useState } from 'react';
22
import { postTx, isValidAddress, normalizeAddress, getNodeUrl } from '../../lib/api';
33
import { getPasskeyInfo, signAndSubmitWithPasskey } from '../../lib/webauthn-sign';
44
import { useToast } from '../../hooks/useToast';
5+
import { primaryButtonStyle } from '../../lib/theme';
56
import type { ParsedBounty } from '../../lib/github';
67
import type { Wallet } from '../../lib/keystore';
78

@@ -134,12 +135,9 @@ export function PayBountyModal({ bounty, wallets, onClose, onSuccess }: PayBount
134135
)}
135136

136137
<button onClick={handlePay} disabled={loading} style={{
137-
width: '100%', padding: '12px 0', borderRadius: 10, border: 'none',
138-
background: loading ? 'var(--dag-input-bg)' : 'linear-gradient(135deg, #00E0C4, #0066FF)',
139-
color: loading ? 'var(--dag-text-faint)' : '#fff',
140-
fontSize: 13, fontWeight: 700, cursor: loading ? 'default' : 'pointer',
141-
boxShadow: loading ? 'none' : '0 2px 12px rgba(0,224,196,0.2)',
142-
transition: 'all 0.2s',
138+
...primaryButtonStyle, width: '100%', padding: '12px 0',
139+
opacity: loading ? 0.5 : 1,
140+
cursor: loading ? 'default' : 'pointer',
143141
}}>
144142
{loading ? 'Sending...' : `Pay ${amount || '0'} UDAG`}
145143
</button>

dashboard/src/components/explorer/RoundTable.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Link } from 'react-router-dom';
22
import { Badge } from '../shared/Badge.tsx';
33
import { DisplayIdentity } from '../shared/DisplayIdentity.tsx';
4+
import { tableHeaderStyle, tableCellStyle } from '../../lib/theme';
45

56
interface Vertex {
67
hash: string;
@@ -19,48 +20,61 @@ interface RoundTableProps {
1920
}>;
2021
}
2122

23+
const thStyle: React.CSSProperties = {
24+
...tableHeaderStyle,
25+
padding: '8px 12px',
26+
textAlign: 'left',
27+
};
28+
29+
const tdStyle: React.CSSProperties = {
30+
...tableCellStyle,
31+
padding: '10px 12px',
32+
};
33+
2234
export function RoundTable({ rounds }: RoundTableProps) {
2335
if (rounds.length === 0) {
24-
return <p className="text-slate-500 text-sm py-8 text-center">No rounds to display</p>;
36+
return <p style={{ color: 'var(--dag-text-faint)', fontSize: 12, padding: '32px 0', textAlign: 'center' }}>No rounds to display</p>;
2537
}
2638

2739
return (
28-
<div className="overflow-x-auto">
29-
<table className="w-full text-sm">
40+
<div style={{ overflowX: 'auto' }}>
41+
<table style={{ width: '100%', fontSize: 12, borderCollapse: 'collapse' }}>
3042
<thead>
31-
<tr className="text-left text-slate-400 border-b border-slate-700">
32-
<th className="py-2 px-3 font-medium w-28">Round</th>
33-
<th className="py-2 px-3 font-medium w-20 text-center">Vertices</th>
34-
<th className="py-2 px-3 font-medium w-16 text-center">Txns</th>
35-
<th className="py-2 px-3 font-medium">Validators</th>
36-
<th className="py-2 px-3 font-medium w-24">Status</th>
43+
<tr>
44+
<th style={{ ...thStyle, width: 112 }}>Round</th>
45+
<th style={{ ...thStyle, width: 80, textAlign: 'center' }}>Vertices</th>
46+
<th style={{ ...thStyle, width: 64, textAlign: 'center' }}>Txns</th>
47+
<th style={thStyle}>Validators</th>
48+
<th style={{ ...thStyle, width: 96 }}>Status</th>
3749
</tr>
3850
</thead>
3951
<tbody>
4052
{rounds.map((r) => {
4153
const totalTxs = r.vertices.reduce((sum, v) => sum + v.tx_count, 0);
4254
return (
43-
<tr key={r.round} className="border-b border-slate-800 hover:bg-slate-800/50 transition-colors">
44-
<td className="py-2.5 px-3">
45-
<Link to={`/round/${r.round}`} className="text-blue-400 hover:text-blue-300 font-mono font-bold text-base">
55+
<tr key={r.round} style={{ transition: 'background 0.15s' }}>
56+
<td style={tdStyle}>
57+
<Link to={`/round/${r.round}`} style={{ color: '#00E0C4', textDecoration: 'none', fontFamily: "'DM Mono',monospace", fontWeight: 700, fontSize: 14 }}>
4658
#{r.round.toLocaleString()}
4759
</Link>
4860
</td>
49-
<td className="py-2.5 px-3 font-mono text-center text-slate-300">{r.vertices.length}</td>
50-
<td className="py-2.5 px-3 font-mono text-center text-slate-300">{totalTxs > 0 ? totalTxs : <span className="text-slate-600">0</span>}</td>
51-
<td className="py-2.5 px-3">
52-
<div className="flex flex-wrap gap-1">
61+
<td style={{ ...tdStyle, fontFamily: "'DM Mono',monospace", textAlign: 'center', color: 'var(--dag-text-secondary)' }}>{r.vertices.length}</td>
62+
<td style={{ ...tdStyle, fontFamily: "'DM Mono',monospace", textAlign: 'center', color: 'var(--dag-text-secondary)' }}>
63+
{totalTxs > 0 ? totalTxs : <span style={{ color: 'var(--dag-text-faint)' }}>0</span>}
64+
</td>
65+
<td style={tdStyle}>
66+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
5367
{r.vertices.slice(0, 3).map((v) => (
54-
<span key={v.hash} className="inline-flex items-center gap-1 text-xs">
68+
<span key={v.hash} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 11 }}>
5569
<DisplayIdentity address={v.validator} link size="xs" />
5670
</span>
5771
))}
5872
{r.vertices.length > 3 && (
59-
<span className="text-xs text-slate-500">+{r.vertices.length - 3} more</span>
73+
<span style={{ fontSize: 10, color: 'var(--dag-text-faint)' }}>+{r.vertices.length - 3} more</span>
6074
)}
6175
</div>
6276
</td>
63-
<td className="py-2.5 px-3">
77+
<td style={tdStyle}>
6478
<Badge label={r.finalized ? 'Finalized' : 'Pending'} variant={r.finalized ? 'green' : 'yellow'} />
6579
</td>
6680
</tr>

dashboard/src/components/explorer/VertexCard.tsx

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,58 @@ interface VertexCardProps {
1313
showLink?: boolean;
1414
}
1515

16+
const cardStyle: React.CSSProperties = {
17+
background: 'var(--dag-card)',
18+
border: '1px solid var(--dag-border)',
19+
borderRadius: 10,
20+
padding: 16,
21+
transition: 'border-color 0.2s',
22+
};
23+
24+
const labelStyle: React.CSSProperties = {
25+
fontSize: 10, color: 'var(--dag-text-faint)', letterSpacing: 1,
26+
textTransform: 'uppercase',
27+
};
28+
29+
const valueStyle: React.CSSProperties = {
30+
fontFamily: "'DM Mono',monospace", fontSize: 12,
31+
color: 'var(--dag-text-secondary)',
32+
};
33+
1634
export function VertexCard({ hash, validator, reward, reward_udag, tx_count, parent_count, showLink = true }: VertexCardProps) {
1735
const rewardDisplay = reward_udag != null ? `${reward_udag} UDAG` : reward != null ? formatUdag(reward) + ' UDAG' : '--';
1836

1937
return (
20-
<div className="bg-slate-800 border border-slate-700 rounded-lg p-4 hover:border-slate-600 transition-colors">
21-
<div className="flex items-start justify-between mb-3">
22-
<div className="flex items-center gap-2">
23-
<span className="text-xs text-slate-500 uppercase tracking-wide">Vertex</span>
38+
<div style={cardStyle}>
39+
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 12 }}>
40+
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
41+
<span style={{ fontSize: 10, color: 'var(--dag-text-faint)', letterSpacing: 1, textTransform: 'uppercase' }}>Vertex</span>
2442
{showLink ? (
25-
<Link to={`/vertex/${hash}`} className="font-mono text-sm text-blue-400 hover:text-blue-300">
43+
<Link to={`/vertex/${hash}`} style={{ fontFamily: "'DM Mono',monospace", fontSize: 12, color: '#00E0C4', textDecoration: 'none' }}>
2644
{shortHash(hash)}
2745
</Link>
2846
) : (
29-
<span className="font-mono text-sm text-slate-200">{shortHash(hash)}</span>
47+
<span style={{ fontFamily: "'DM Mono',monospace", fontSize: 12, color: 'var(--dag-text)' }}>{shortHash(hash)}</span>
3048
)}
3149
<CopyButton text={hash} />
3250
</div>
3351
</div>
34-
<div className="grid grid-cols-2 gap-3 text-sm">
52+
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, fontSize: 12 }}>
3553
<div>
36-
<span className="text-slate-500 text-xs">Validator</span>
54+
<span style={labelStyle}>Validator</span>
3755
<DisplayIdentity address={validator} link size="xs" />
3856
</div>
3957
<div>
40-
<span className="text-slate-500 text-xs">Reward</span>
41-
<p className="text-slate-300 font-mono text-xs">{rewardDisplay}</p>
58+
<span style={labelStyle}>Reward</span>
59+
<p style={valueStyle}>{rewardDisplay}</p>
4260
</div>
4361
<div>
44-
<span className="text-slate-500 text-xs">Transactions</span>
45-
<p className="text-slate-300 font-mono">{tx_count}</p>
62+
<span style={labelStyle}>Transactions</span>
63+
<p style={valueStyle}>{tx_count}</p>
4664
</div>
4765
<div>
48-
<span className="text-slate-500 text-xs">Parents</span>
49-
<p className="text-slate-300 font-mono">{parent_count}</p>
66+
<span style={labelStyle}>Parents</span>
67+
<p style={valueStyle}>{parent_count}</p>
5068
</div>
5169
</div>
5270
</div>

0 commit comments

Comments
 (0)