mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
rover based colors!
This commit is contained in:
@@ -127,7 +127,7 @@ export default function ButtonBoxPanel() {
|
||||
}, [effectiveAlertVolume, socket]);
|
||||
|
||||
return (
|
||||
<CardFrame title="Button Box" accent="#eab308" bodyClassName="space-y-0.5 text-base">
|
||||
<CardFrame title="Button Box" bodyClassName="space-y-0.5 text-base">
|
||||
<div className="grid grid-cols-4 gap-0.5">
|
||||
{buttons.map((button) => {
|
||||
const id = Number(button.id);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
|
||||
// Utilities
|
||||
function cx(...values) {
|
||||
return values.filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
// Color helpers
|
||||
function hexToRgb(hex) {
|
||||
const raw = String(hex || '').trim();
|
||||
const normalized = raw.startsWith('#') ? raw.slice(1) : raw;
|
||||
@@ -24,21 +28,29 @@ function rgba(rgb, alpha) {
|
||||
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
||||
}
|
||||
|
||||
// Component
|
||||
export default function CardFrame({
|
||||
title = '',
|
||||
meta = null,
|
||||
actions = null,
|
||||
accent = null,
|
||||
hideHeader = false,
|
||||
className = '',
|
||||
headerClassName = '',
|
||||
bodyClassName = '',
|
||||
fillHeight = false,
|
||||
clipOverflow = true,
|
||||
children,
|
||||
}) {
|
||||
const showHeader = !hideHeader && (title || meta != null || actions);
|
||||
const accentRgb = hexToRgb(accent);
|
||||
const cardStyle = accentRgb ? { borderColor: rgba(accentRgb, 0.65) } : undefined;
|
||||
const ownRoverColor = useSessionSelector((state) => {
|
||||
const roverId = String(state.session?.assignment?.roverId || '').trim();
|
||||
if (!roverId) return null;
|
||||
const roster = Array.isArray(state.session?.roster) ? state.session.roster : [];
|
||||
const rover = roster.find((entry) => String(entry?.id) === roverId);
|
||||
return rover?.color || null;
|
||||
});
|
||||
const accentRgb = hexToRgb(ownRoverColor);
|
||||
const cardStyle = accentRgb ? { borderColor: rgba(accentRgb, 0.35) } : undefined;
|
||||
const headerStyle = accentRgb
|
||||
? {
|
||||
backgroundImage: `linear-gradient(90deg, rgba(23,23,23,0.96) 0%, rgba(38,38,38,0.94) 58%, ${rgba(accentRgb, 0.18)} 100%)`,
|
||||
@@ -48,28 +60,30 @@ export default function CardFrame({
|
||||
return (
|
||||
<section
|
||||
className={cx(
|
||||
'panel-section overflow-hidden border border-neutral-600/55 bg-neutral-900/95 shadow-[0_1px_0_rgba(255,255,255,0.04)_inset,0_10px_24px_rgba(0,0,0,0.3)]',
|
||||
'panel-section border border-neutral-500/60 bg-neutral-900/95 shadow-[0_1px_0_rgba(255,255,255,0.05)_inset,0_10px_24px_rgba(0,0,0,0.28)]',
|
||||
clipOverflow ? 'overflow-hidden' : 'overflow-visible',
|
||||
fillHeight && 'flex h-full min-h-0 flex-col',
|
||||
className,
|
||||
)}
|
||||
style={cardStyle}
|
||||
>
|
||||
{showHeader ? (
|
||||
// Header row
|
||||
<header
|
||||
className={cx(
|
||||
'flex items-center justify-between gap-0.5 border-b border-neutral-600/45 bg-gradient-to-r from-neutral-900 via-neutral-800 to-neutral-700 px-0.5 py-0.5',
|
||||
'flex items-center justify-between gap-0.5 border-b border-neutral-500/50 bg-gradient-to-r from-neutral-800 via-neutral-700 to-neutral-600 px-0.5 py-0.5',
|
||||
headerClassName,
|
||||
)}
|
||||
style={headerStyle}
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-0.5">
|
||||
{title ? <p className="m-0 text-[0.78rem] font-semibold leading-none text-neutral-100">{title}</p> : null}
|
||||
{meta != null ? <span className="text-[0.68rem] font-medium leading-none text-neutral-300">{meta}</span> : null}
|
||||
{title ? <p className="m-0 text-[0.78rem] font-semibold leading-none text-neutral-50">{title}</p> : null}
|
||||
{meta != null ? <span className="text-[0.68rem] font-medium leading-none text-neutral-200">{meta}</span> : null}
|
||||
</div>
|
||||
{actions ? <div className="flex flex-wrap items-center justify-end gap-0.5">{actions}</div> : null}
|
||||
</header>
|
||||
) : null}
|
||||
<div className={cx('', fillHeight && 'flex flex-1 min-h-0 flex-col', bodyClassName)}>{children}</div>
|
||||
<div className={cx(fillHeight && 'flex flex-1 min-h-0 flex-col', bodyClassName)}>{children}</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export default function ChatPanel({
|
||||
return (
|
||||
<CardFrame
|
||||
title={title}
|
||||
accent="#22c55e"
|
||||
|
||||
hideHeader={!title}
|
||||
fillHeight={fillHeight}
|
||||
bodyClassName="space-y-0.5 text-base"
|
||||
|
||||
@@ -8,11 +8,40 @@ const MOBILE_DISMISS_MS = 10000;
|
||||
const MAX_FONT_PX = 28;
|
||||
const MIN_FONT_PX = 14;
|
||||
|
||||
function hexToRgb(hex) {
|
||||
const raw = String(hex || '').trim();
|
||||
const normalized = raw.startsWith('#') ? raw.slice(1) : raw;
|
||||
if (!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(normalized)) return null;
|
||||
const expanded =
|
||||
normalized.length === 3
|
||||
? normalized
|
||||
.split('')
|
||||
.map((ch) => ch + ch)
|
||||
.join('')
|
||||
: normalized;
|
||||
return {
|
||||
r: Number.parseInt(expanded.slice(0, 2), 16),
|
||||
g: Number.parseInt(expanded.slice(2, 4), 16),
|
||||
b: Number.parseInt(expanded.slice(4, 6), 16),
|
||||
};
|
||||
}
|
||||
|
||||
function rgba(rgb, alpha) {
|
||||
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
||||
}
|
||||
|
||||
export default function GlobalObjectiveBanner({ layout = 'desktop', className = '', dismissable = true }) {
|
||||
const goalText = useSessionSelector((state) => {
|
||||
const text = state.session?.globalObjective?.text;
|
||||
return text ? String(text).trim() : '';
|
||||
});
|
||||
const ownRoverColor = useSessionSelector((state) => {
|
||||
const roverId = String(state.session?.assignment?.roverId || '').trim();
|
||||
if (!roverId) return null;
|
||||
const roster = Array.isArray(state.session?.roster) ? state.session.roster : [];
|
||||
const rover = roster.find((entry) => String(entry?.id) === roverId);
|
||||
return rover?.color || null;
|
||||
});
|
||||
const isMobile = layout === 'mobile-portrait' || layout === 'mobile-landscape' || layout === 'mobile';
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [fontSize, setFontSize] = useState(MAX_FONT_PX);
|
||||
@@ -72,7 +101,7 @@ export default function GlobalObjectiveBanner({ layout = 'desktop', className =
|
||||
const containerClass = useMemo(
|
||||
() =>
|
||||
[
|
||||
'panel-section flex w-full items-center justify-center',
|
||||
'panel-section flex w-full items-center justify-center border border-neutral-500/60 shadow-[0_1px_0_rgba(255,255,255,0.05)_inset,0_10px_24px_rgba(0,0,0,0.28)]',
|
||||
isMobile ? 'rounded-none' : 'rounded',
|
||||
'px-1 py-1 text-center font-semibold tracking-tight',
|
||||
className,
|
||||
@@ -81,6 +110,13 @@ export default function GlobalObjectiveBanner({ layout = 'desktop', className =
|
||||
.join(' '),
|
||||
[className, isMobile],
|
||||
);
|
||||
const accentRgb = hexToRgb(ownRoverColor);
|
||||
const frameStyle = accentRgb
|
||||
? {
|
||||
borderColor: rgba(accentRgb, 0.35),
|
||||
backgroundImage: `linear-gradient(90deg, rgba(23,23,23,0.96) 0%, rgba(38,38,38,0.94) 58%, ${rgba(accentRgb, 0.18)} 100%)`,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
if (!goalText || !visible) return null;
|
||||
|
||||
@@ -94,7 +130,7 @@ export default function GlobalObjectiveBanner({ layout = 'desktop', className =
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={containerClass}
|
||||
style={{ fontSize: `${fontSize}px`, lineHeight: 1.1 }}
|
||||
style={{ ...(frameStyle || {}), fontSize: `${fontSize}px`, lineHeight: 1.1 }}
|
||||
{...dismissProps}
|
||||
>
|
||||
<span className="flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md">
|
||||
|
||||
@@ -256,7 +256,7 @@ export default function HomeAssistantControls() {
|
||||
|
||||
if (!ha?.enabled) {
|
||||
return (
|
||||
<CardFrame title="Room Controls" accent="#14b8a6" bodyClassName="space-y-0.5 text-sm text-slate-400">
|
||||
<CardFrame title="Room Controls" bodyClassName="space-y-0.5 text-sm text-slate-400">
|
||||
<p className="text-slate-500">Not configured on the server.</p>
|
||||
</CardFrame>
|
||||
);
|
||||
@@ -264,7 +264,7 @@ export default function HomeAssistantControls() {
|
||||
|
||||
if (entities.length === 0) {
|
||||
return (
|
||||
<CardFrame title="Room Controls" accent="#14b8a6" bodyClassName="space-y-0.5 text-sm text-slate-400">
|
||||
<CardFrame title="Room Controls" bodyClassName="space-y-0.5 text-sm text-slate-400">
|
||||
<p className="text-slate-500">No lights or switches configured.</p>
|
||||
</CardFrame>
|
||||
);
|
||||
@@ -290,7 +290,7 @@ export default function HomeAssistantControls() {
|
||||
);
|
||||
|
||||
return (
|
||||
<CardFrame title="Room Controls" accent="#14b8a6" actions={actions} bodyClassName="space-y-0.5 text-base">
|
||||
<CardFrame title="Room Controls" actions={actions} bodyClassName="space-y-0.5 text-base">
|
||||
{controlsLocked ? (
|
||||
<p className="rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100">
|
||||
{lockState === 'off'
|
||||
|
||||
@@ -9,7 +9,7 @@ export default function LogPanel() {
|
||||
const logs = useSessionSelector((state) => state.logs);
|
||||
const rendered = useMemo(() => logs.slice().reverse(), [logs]);
|
||||
return (
|
||||
<CardFrame title="Server logs" accent="#f97316" bodyClassName="space-y-0.5 text-base">
|
||||
<CardFrame title="Server logs" bodyClassName="space-y-0.5 text-base">
|
||||
<div className="surface h-64 overflow-y-auto font-mono text-xs">
|
||||
{logs.length === 0 ? (
|
||||
<p>No logs yet.</p>
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function OverseerPreferencePanel() {
|
||||
};
|
||||
|
||||
return (
|
||||
<CardFrame title="Overseer vote" accent="#10b981" bodyClassName="space-y-0.5 text-center text-xs text-slate-200">
|
||||
<CardFrame title="Overseer vote" bodyClassName="space-y-0.5 text-center text-xs text-slate-200">
|
||||
<label
|
||||
className={`flex items-center justify-center gap-1.5 rounded px-1 py-0.5 ${
|
||||
enabled ? 'bg-emerald-600/80 text-emerald-50' : 'bg-slate-600/70 text-slate-100'
|
||||
|
||||
@@ -60,7 +60,7 @@ export default function RawUserPilePanel({
|
||||
return (
|
||||
<CardFrame
|
||||
title={!hideHeader ? 'Users' : ''}
|
||||
accent="#94a3b8"
|
||||
|
||||
hideHeader={hideHeader}
|
||||
fillHeight={fillHeight}
|
||||
className={className}
|
||||
|
||||
@@ -150,7 +150,7 @@ export default function ReplaySourcesPanel({ panelId = 'replay-sources', fillHei
|
||||
const listWrapClass = fillHeight ? 'flex-1 min-h-0 overflow-y-auto' : '';
|
||||
|
||||
return (
|
||||
<CardFrame title="Replay Sources" accent="#06b6d4" fillHeight={fillHeight} bodyClassName="space-y-0.5 text-sm">
|
||||
<CardFrame title="Replay Sources" fillHeight={fillHeight} bodyClassName="space-y-0.5 text-sm">
|
||||
<div className={`grid gap-0.5 md:grid-cols-2 ${listWrapClass}`}>
|
||||
<GroupList title="Rovers" items={grouped.rovers} selected={selected} onToggle={toggleKey} />
|
||||
<GroupList title="Room Cams" items={grouped.rooms} selected={selected} onToggle={toggleKey} />
|
||||
|
||||
@@ -36,7 +36,7 @@ function TopDownMapPanel() {
|
||||
const sensors = frame?.sensors || {};
|
||||
|
||||
return (
|
||||
<CardFrame hideHeader accent="#0067f7">
|
||||
<CardFrame hideHeader>
|
||||
<div className="aspect-square w-full">
|
||||
<TopDownMap sensors={sensors} />
|
||||
</div>
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function RoomCameraPanel({
|
||||
return (
|
||||
<CardFrame
|
||||
title="Room cameras"
|
||||
accent="#38bdf8"
|
||||
|
||||
actions={actions}
|
||||
hideHeader={hideHeader}
|
||||
bodyClassName="space-y-0.5 text-base"
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function RoverQueuesPanel({ title = 'Rovers' }) {
|
||||
users.find((u) => u.socketId === socketId) || { socketId, nickname: null, role: null };
|
||||
|
||||
return (
|
||||
<CardFrame title={title} accent="#f59e0b" bodyClassName="space-y-0.5 text-sm">
|
||||
<CardFrame title={title} bodyClassName="space-y-0.5 text-sm">
|
||||
{rosterItems.length === 0 ? (
|
||||
<p className="text-sm text-slate-500">No rovers registered.</p>
|
||||
) : (
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Purpose: Defines the Tabs module and the local helpers/components used in this file.
|
||||
// Scope: Keeps behavior unchanged while isolating this concern into a clear, single-responsibility unit.
|
||||
import { createContext, useCallback, useContext, useMemo, useState, useEffect } from 'react';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
|
||||
const TabsContext = createContext(null);
|
||||
|
||||
@@ -33,6 +34,28 @@ function classNames(...parts) {
|
||||
return parts.filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
function hexToRgb(hex) {
|
||||
const raw = String(hex || '').trim();
|
||||
const normalized = raw.startsWith('#') ? raw.slice(1) : raw;
|
||||
if (!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(normalized)) return null;
|
||||
const expanded =
|
||||
normalized.length === 3
|
||||
? normalized
|
||||
.split('')
|
||||
.map((ch) => ch + ch)
|
||||
.join('')
|
||||
: normalized;
|
||||
return {
|
||||
r: Number.parseInt(expanded.slice(0, 2), 16),
|
||||
g: Number.parseInt(expanded.slice(2, 4), 16),
|
||||
b: Number.parseInt(expanded.slice(4, 6), 16),
|
||||
};
|
||||
}
|
||||
|
||||
function rgba(rgb, alpha) {
|
||||
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
||||
}
|
||||
|
||||
export default function Tabs({ children, defaultTab, currentTab, onTabChange, variant = DEFAULT_VARIANT }) {
|
||||
const [internalTab, setInternalTab] = useState(defaultTab ?? null);
|
||||
const [tabOrder, setTabOrder] = useState([]);
|
||||
@@ -95,7 +118,32 @@ export default function Tabs({ children, defaultTab, currentTab, onTabChange, va
|
||||
}
|
||||
|
||||
export function TabList({ children, className = '' }) {
|
||||
return <div className={classNames('flex gap-0.5', className)}>{children}</div>;
|
||||
const ownRoverColor = useSessionSelector((state) => {
|
||||
const roverId = String(state.session?.assignment?.roverId || '').trim();
|
||||
if (!roverId) return null;
|
||||
const roster = Array.isArray(state.session?.roster) ? state.session.roster : [];
|
||||
const rover = roster.find((entry) => String(entry?.id) === roverId);
|
||||
return rover?.color || null;
|
||||
});
|
||||
const accentRgb = hexToRgb(ownRoverColor);
|
||||
const frameStyle = accentRgb ? { borderColor: rgba(accentRgb, 0.35) } : undefined;
|
||||
const headerStyle = accentRgb
|
||||
? {
|
||||
backgroundImage: `linear-gradient(90deg, rgba(23,23,23,0.96) 0%, rgba(38,38,38,0.94) 58%, ${rgba(accentRgb, 0.18)} 100%)`,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'panel-section overflow-hidden border border-neutral-500/60 bg-neutral-900/95 p-0.5 shadow-[0_1px_0_rgba(255,255,255,0.05)_inset,0_10px_24px_rgba(0,0,0,0.28)]',
|
||||
className
|
||||
)}
|
||||
style={frameStyle}
|
||||
>
|
||||
<div className="flex gap-0.5" style={headerStyle}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Tab({ id, children, className = '', disabled = false, highlight = 'none' }) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useMemo } from 'react';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useTelemetryFrame } from '../../context/TelemetryContext.jsx';
|
||||
import { useDockIr } from '../../hooks/useDockIr.js';
|
||||
import CardFrame from '../CardFrame/index.jsx';
|
||||
|
||||
function formatMetric(value, fallback = '--') {
|
||||
if (value == null || value === '') return fallback;
|
||||
@@ -39,7 +40,7 @@ export default function TelemetryPanel() {
|
||||
}, [activeDriverId, roverId, selfSocketId, users]);
|
||||
|
||||
return (
|
||||
<section className="panel-section space-y-0.5 text-base text-slate-100">
|
||||
<CardFrame hideHeader clipOverflow={false} bodyClassName="space-y-0.5 text-base text-slate-100">
|
||||
{/* <div className="text-sm text-slate-400">
|
||||
<span>{connected ? 'online' : 'offline'}</span>
|
||||
<span> · role {session?.role || 'unknown'}</span>
|
||||
@@ -60,7 +61,7 @@ export default function TelemetryPanel() {
|
||||
{rawSnippet && (
|
||||
<pre className="surface whitespace-pre-wrap break-words text-xs text-lime-300">{rawSnippet}</pre>
|
||||
)}
|
||||
</section>
|
||||
</CardFrame>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export function NicknameEntryPanel({ compact = false }) {
|
||||
|
||||
export function LinkButtonsPanel() {
|
||||
return (
|
||||
<CardFrame title="Socials" accent="#3030f5" fillHeight bodyClassName="flex flex-1 min-h-0 flex-col gap-0.5 text-base">
|
||||
<CardFrame title="Socials" fillHeight bodyClassName="flex flex-1 min-h-0 flex-col gap-0.5 text-base">
|
||||
<SocialButtonsGrid className="flex-1 min-h-0" />
|
||||
</CardFrame>
|
||||
);
|
||||
|
||||
@@ -530,7 +530,7 @@ export default function VipAudioUploadCard({
|
||||
);
|
||||
|
||||
return (
|
||||
<CardFrame title="Audio Controls" accent="#a78bfa">
|
||||
<CardFrame title="Audio Controls">
|
||||
<div className="grid gap-1">
|
||||
<section className="surface">
|
||||
<div className="flex items-center justify-center gap-0.5 py-0.25 text-xs text-slate-300">
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function VipIdentityCard({ currentStoredKey, applyIdentityKey, on
|
||||
const wrapClass = fullWidth ? 'w-full' : flowWrapClass;
|
||||
|
||||
return (
|
||||
<CardFrame title="Identity key" accent="#60a5fa" className={wrapClass}>
|
||||
<CardFrame title="Identity key" className={wrapClass}>
|
||||
<div className={innerFlowClass}>
|
||||
<p className="text-xs text-slate-500">Current: {maskKey(currentStoredKey) || 'not set yet'}</p>
|
||||
<input
|
||||
|
||||
@@ -70,7 +70,7 @@ export default function VipLiftCard({ lift, onUp, onDown, fullWidth = false }) {
|
||||
return (
|
||||
<CardFrame
|
||||
title="Lift Controls"
|
||||
accent="#06b6d4"
|
||||
|
||||
className={`relative ${wrapClass}`}
|
||||
bodyClassName="text-sm text-slate-200"
|
||||
actions={
|
||||
|
||||
@@ -101,7 +101,7 @@ export default function VipNeatoCard({
|
||||
return (
|
||||
<CardFrame
|
||||
title="Neato Controls"
|
||||
accent="#22c55e"
|
||||
|
||||
className={wrapClass}
|
||||
bodyClassName="text-sm text-slate-200"
|
||||
actions={
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function VipPrivateRoverAccessCard({
|
||||
};
|
||||
|
||||
return (
|
||||
<CardFrame title="Private rover access requests" accent="#f43f5e" className={wrapClass} bodyClassName="text-sm text-slate-300">
|
||||
<CardFrame title="Private rover access requests" className={wrapClass} bodyClassName="text-sm text-slate-300">
|
||||
<div className={innerFlowClass}>
|
||||
{requestableRovers.length === 0 ? (
|
||||
<p className="text-xs text-slate-500">No closed private rovers are available to request right now.</p>
|
||||
|
||||
@@ -55,7 +55,7 @@ export default function VipProfileImageCard({ isVerified = false, fullWidth = fa
|
||||
};
|
||||
|
||||
return (
|
||||
<CardFrame title="Chat profile image URL" accent="#f59e0b" className={wrapClass} bodyClassName="text-sm text-slate-300">
|
||||
<CardFrame title="Chat profile image URL" className={wrapClass} bodyClassName="text-sm text-slate-300">
|
||||
<form className={innerFlowClass} onSubmit={handleSave}>
|
||||
<p className="text-xs text-slate-500">
|
||||
Verified users can set a custom avatar for chat and Discord bridge messages.
|
||||
|
||||
@@ -62,7 +62,7 @@ export default function VipVerificationCard({
|
||||
|
||||
if (pendingRequestId) {
|
||||
return (
|
||||
<CardFrame title="Verification" accent="#eab308" className={wrapClass} bodyClassName="text-sm text-slate-300">
|
||||
<CardFrame title="Verification" className={wrapClass} bodyClassName="text-sm text-slate-300">
|
||||
<div className={innerFlowClass}>Verification request pending: {pendingRequestId}</div>
|
||||
</CardFrame>
|
||||
);
|
||||
@@ -70,7 +70,7 @@ export default function VipVerificationCard({
|
||||
|
||||
if (requestFlowStep === 0) {
|
||||
return (
|
||||
<CardFrame title="Verification" accent="#eab308" className={wrapClass}>
|
||||
<CardFrame title="Verification" className={wrapClass}>
|
||||
<div className={innerFlowClass}>
|
||||
<button type="button" className="button-dark text-sm" onClick={beginRequestFlow} disabled={working}>
|
||||
Request Verification
|
||||
@@ -81,7 +81,7 @@ export default function VipVerificationCard({
|
||||
}
|
||||
|
||||
return (
|
||||
<CardFrame title="Request verification" accent="#eab308" className={wrapClass}>
|
||||
<CardFrame title="Request verification" className={wrapClass}>
|
||||
<form onSubmit={handleRequestSubmit}>
|
||||
<div className={innerFlowClass}>
|
||||
<p className="text-xs text-slate-500">
|
||||
|
||||
Reference in New Issue
Block a user