chore: Tailwind CSS v3 → v4 migration (#99)
* chore: run Tailwind v4 upgrade tool (Phase 1) - Upgraded tailwindcss v3 → v4.2.1, postcss plugin to @tailwindcss/postcss - Deleted tailwind.config.js, migrated theme to CSS @theme block in index.css - Replaced @tailwind directives with @import 'tailwindcss' - Added @custom-variant dark, @utility blocks for custom utilities - Updated class names across 128 files (shadow-sm → shadow-xs, etc.) - Removed autoprefixer (built into v4) - Added migration plan doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: switch from @tailwindcss/postcss to @tailwindcss/vite (Phase 2) - Replaced @tailwindcss/postcss with @tailwindcss/vite plugin - Deleted postcss.config.js (no longer needed) - Tailwind now runs as a native Vite plugin for faster HMR Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: convert to OKLCH colors, move keyframes into @theme (Phase 3-4) - Replaced all HSL color indirection with direct OKLCH values in @theme - Moved all keyframes inside @theme block (v4 pattern) - Eliminated hsl(var(--x)) double-indirection across 17 component files - Replaced hsl() inline styles with var(--color-*) theme references - Cleaned up redundant rdp-* utility blocks - Fixed @custom-variant dark syntax to use :where() - Added sidebar/glass/shadow vars as OKLCH in :root Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #99.
This commit is contained in:
@@ -135,7 +135,7 @@ export function AuditLogsPage() {
|
||||
placeholder="Filter by action..."
|
||||
className={cn(
|
||||
'h-9 rounded-md border border-border bg-card px-3 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
<input
|
||||
@@ -145,7 +145,7 @@ export function AuditLogsPage() {
|
||||
placeholder="Filter by resource type..."
|
||||
className={cn(
|
||||
'h-9 rounded-md border border-border bg-card px-3 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -145,7 +145,7 @@ export function FeatureFlagsPage() {
|
||||
},
|
||||
]
|
||||
|
||||
const inputCn = cn('w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground', 'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20')
|
||||
const inputCn = cn('w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground', 'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20')
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
|
||||
@@ -87,7 +87,7 @@ export function GlobalCategoriesPage() {
|
||||
},
|
||||
]
|
||||
|
||||
const inputCn = cn('w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground', 'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20')
|
||||
const inputCn = cn('w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground', 'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20')
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
|
||||
@@ -109,7 +109,7 @@ export function InviteCodesPage() {
|
||||
|
||||
const inputClass = cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)
|
||||
|
||||
const columns: Column<InviteCodeResponse>[] = [
|
||||
|
||||
@@ -110,7 +110,7 @@ export function PlanLimitsPage() {
|
||||
|
||||
const inputCn = cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
@@ -100,7 +100,7 @@ export function SettingsPage() {
|
||||
placeholder="We're performing scheduled maintenance. Please check back later."
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -74,7 +74,7 @@ export default function SurveyInvitesPage() {
|
||||
<h3 className="font-heading text-sm font-semibold text-foreground mb-4">Create Invite</h3>
|
||||
<div className="flex flex-col gap-3 sm:flex-row sm:items-end">
|
||||
<div className="flex-1">
|
||||
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5 block">
|
||||
<label className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground mb-1.5 block">
|
||||
Recipient Name
|
||||
</label>
|
||||
<input
|
||||
@@ -82,11 +82,11 @@ export default function SurveyInvitesPage() {
|
||||
value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
placeholder="John Smith"
|
||||
className="w-full rounded-[10px] border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
|
||||
className="w-full rounded-[10px] border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5 block">
|
||||
<label className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground mb-1.5 block">
|
||||
Email (optional)
|
||||
</label>
|
||||
<input
|
||||
@@ -94,14 +94,14 @@ export default function SurveyInvitesPage() {
|
||||
value={email}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
placeholder="john@example.com"
|
||||
className="w-full rounded-[10px] border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
|
||||
className="w-full rounded-[10px] border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => handleCreate(false)}
|
||||
disabled={creating || !name.trim()}
|
||||
className="inline-flex items-center gap-2 rounded-[10px] bg-gradient-brand px-4 py-2 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] disabled:opacity-50 disabled:cursor-not-allowed transition-all"
|
||||
className="inline-flex items-center gap-2 rounded-[10px] bg-gradient-brand px-4 py-2 text-sm font-semibold text-brand-dark shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] disabled:opacity-50 disabled:cursor-not-allowed transition-all"
|
||||
>
|
||||
{creating ? <Loader2 className="h-4 w-4 animate-spin" /> : <Link2 className="h-4 w-4" />}
|
||||
Generate Link
|
||||
@@ -109,7 +109,7 @@ export default function SurveyInvitesPage() {
|
||||
<button
|
||||
onClick={() => handleCreate(true)}
|
||||
disabled={creating || !name.trim() || !email.trim()}
|
||||
className="inline-flex items-center gap-2 rounded-[10px] bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] active:scale-[0.97] disabled:opacity-50 disabled:cursor-not-allowed transition-all"
|
||||
className="inline-flex items-center gap-2 rounded-[10px] bg-[rgba(255,255,255,0.04)] border border-brand-border px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] active:scale-[0.97] disabled:opacity-50 disabled:cursor-not-allowed transition-all"
|
||||
>
|
||||
{creating ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
|
||||
Send Email
|
||||
@@ -132,7 +132,7 @@ export default function SurveyInvitesPage() {
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleCopy(lastCreated.survey_url)}
|
||||
className="shrink-0 rounded-lg p-2 text-muted-foreground hover:bg-[rgba(255,255,255,0.06)] hover:text-foreground transition-colors"
|
||||
className="shrink-0 rounded-lg p-2 text-muted-foreground hover:bg-brand-border hover:text-foreground transition-colors"
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
|
||||
</button>
|
||||
@@ -147,13 +147,13 @@ export default function SurveyInvitesPage() {
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="border-b border-border">
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Name</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Email</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Status</th>
|
||||
<th className="px-4 py-3 text-center font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Sent</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Created</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Completed</th>
|
||||
<th className="px-4 py-3 text-center font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Link</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Name</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Email</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Status</th>
|
||||
<th className="px-4 py-3 text-center font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Sent</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Created</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Completed</th>
|
||||
<th className="px-4 py-3 text-center font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">Link</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -188,7 +188,7 @@ export default function SurveyInvitesPage() {
|
||||
<td className="px-4 py-3 text-center">
|
||||
<button
|
||||
onClick={() => handleCopy(invite.survey_url)}
|
||||
className="rounded-lg p-1.5 text-muted-foreground hover:bg-[rgba(255,255,255,0.06)] hover:text-foreground transition-colors"
|
||||
className="rounded-lg p-1.5 text-muted-foreground hover:bg-brand-border hover:text-foreground transition-colors"
|
||||
title="Copy survey link"
|
||||
>
|
||||
<Copy className="h-3.5 w-3.5" />
|
||||
|
||||
@@ -104,7 +104,7 @@ function ExpandedDetail({ response }: { response: SurveyResponseDetail }) {
|
||||
border: '1px solid var(--glass-border)',
|
||||
}}
|
||||
>
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-primary mb-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-widest text-primary mb-1">
|
||||
Q{q.num}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground mb-2">{q.text}</p>
|
||||
@@ -151,7 +151,7 @@ function ResponseRow({
|
||||
<tr
|
||||
className={cn(
|
||||
'border-b border-border/50 transition-colors cursor-pointer',
|
||||
!response.is_read && 'bg-primary/[0.03]',
|
||||
!response.is_read && 'bg-primary/3',
|
||||
'hover:bg-[rgba(255,255,255,0.02)]'
|
||||
)}
|
||||
>
|
||||
@@ -194,7 +194,7 @@ function ResponseRow({
|
||||
)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 font-label text-[0.625rem] uppercase tracking-wider bg-[rgba(255,255,255,0.06)] text-muted-foreground">
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 font-label text-[0.625rem] uppercase tracking-wider bg-brand-border text-muted-foreground">
|
||||
<Link2 className="h-3 w-3" />
|
||||
Direct
|
||||
</span>
|
||||
@@ -214,7 +214,7 @@ function ResponseRow({
|
||||
<td className="px-3 py-3 w-10 relative">
|
||||
<button
|
||||
onClick={e => { e.stopPropagation(); setShowMenu(!showMenu) }}
|
||||
className="p-1.5 rounded-lg hover:bg-[rgba(255,255,255,0.06)] text-muted-foreground hover:text-foreground transition-colors"
|
||||
className="p-1.5 rounded-lg hover:bg-brand-border text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -437,7 +437,7 @@ export default function SurveyResponsesPage() {
|
||||
'inline-flex items-center gap-2 rounded-[10px] px-3 py-2 text-xs font-medium transition-colors border',
|
||||
showArchived
|
||||
? 'bg-primary/10 text-primary border-primary/20'
|
||||
: 'bg-[rgba(255,255,255,0.04)] text-muted-foreground border-[rgba(255,255,255,0.06)] hover:border-[rgba(255,255,255,0.12)]'
|
||||
: 'bg-[rgba(255,255,255,0.04)] text-muted-foreground border-brand-border hover:border-[rgba(255,255,255,0.12)]'
|
||||
)}
|
||||
>
|
||||
<Archive className="h-3.5 w-3.5" />
|
||||
@@ -446,7 +446,7 @@ export default function SurveyResponsesPage() {
|
||||
<button
|
||||
onClick={handleExport}
|
||||
disabled={exporting || responses.length === 0}
|
||||
className="inline-flex items-center gap-2 rounded-[10px] bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-foreground transition-colors hover:border-[rgba(255,255,255,0.12)] disabled:opacity-50"
|
||||
className="inline-flex items-center gap-2 rounded-[10px] bg-[rgba(255,255,255,0.04)] border border-brand-border px-4 py-2 text-sm font-medium text-foreground transition-colors hover:border-[rgba(255,255,255,0.12)] disabled:opacity-50"
|
||||
>
|
||||
{exporting ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
@@ -468,7 +468,7 @@ export default function SurveyResponsesPage() {
|
||||
{/* Stat cards */}
|
||||
<div className="flex gap-4">
|
||||
<div className="glass-card-static px-5 py-4 flex-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground mb-1">
|
||||
Total Responses
|
||||
</p>
|
||||
<p className="text-2xl font-heading font-bold text-gradient-brand">
|
||||
@@ -476,7 +476,7 @@ export default function SurveyResponsesPage() {
|
||||
</p>
|
||||
</div>
|
||||
<div className="glass-card-static px-5 py-4 flex-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground mb-1">
|
||||
This Week
|
||||
</p>
|
||||
<p className="text-2xl font-heading font-bold text-foreground">
|
||||
@@ -484,7 +484,7 @@ export default function SurveyResponsesPage() {
|
||||
</p>
|
||||
</div>
|
||||
<div className="glass-card-static px-5 py-4 flex-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1">
|
||||
<p className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground mb-1">
|
||||
Unread
|
||||
</p>
|
||||
<p className={cn(
|
||||
@@ -508,21 +508,21 @@ export default function SurveyResponsesPage() {
|
||||
<div className="flex-1" />
|
||||
<button
|
||||
onClick={() => handleBulkAction('mark_read')}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-brand-border transition-colors"
|
||||
>
|
||||
<Eye className="h-3.5 w-3.5" />
|
||||
Mark Read
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleBulkAction('mark_unread')}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-brand-border transition-colors"
|
||||
>
|
||||
<EyeOff className="h-3.5 w-3.5" />
|
||||
Mark Unread
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleBulkAction('archive')}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-brand-border transition-colors"
|
||||
>
|
||||
<Archive className="h-3.5 w-3.5" />
|
||||
Archive
|
||||
@@ -536,7 +536,7 @@ export default function SurveyResponsesPage() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedIds(new Set())}
|
||||
className="px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
|
||||
className="px-3 py-1.5 rounded-lg text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-brand-border transition-colors"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
@@ -559,19 +559,19 @@ export default function SurveyResponsesPage() {
|
||||
</th>
|
||||
<th className="px-1 py-3 w-6" />
|
||||
<th className="px-2 py-3 w-8" />
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
#
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
Respondent
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
Source
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
Date
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
|
||||
<th className="px-4 py-3 text-left font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
Answered
|
||||
</th>
|
||||
<th className="px-3 py-3 w-10" />
|
||||
|
||||
@@ -188,7 +188,7 @@ export function UserDetailPage() {
|
||||
|
||||
const inputClass = cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)
|
||||
|
||||
if (loading) {
|
||||
|
||||
@@ -348,7 +348,7 @@ export function UsersPage() {
|
||||
onChange={(e) => setNewRole(e.target.value)}
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
>
|
||||
<option value="engineer">Engineer</option>
|
||||
@@ -394,7 +394,7 @@ export function UsersPage() {
|
||||
placeholder="e.g. ABC-1234"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -435,7 +435,7 @@ export function UsersPage() {
|
||||
placeholder="Full name"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -448,7 +448,7 @@ export function UsersPage() {
|
||||
placeholder="user@example.com"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -459,7 +459,7 @@ export function UsersPage() {
|
||||
onChange={(e) => setCreateForm(f => ({ ...f, account_mode: e.target.value as 'existing' | 'personal' }))}
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
>
|
||||
<option value="personal">Personal (new account)</option>
|
||||
@@ -477,7 +477,7 @@ export function UsersPage() {
|
||||
placeholder="e.g. ABC12345"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -488,7 +488,7 @@ export function UsersPage() {
|
||||
onChange={(e) => setCreateForm(f => ({ ...f, account_role: e.target.value as 'engineer' | 'viewer' }))}
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
>
|
||||
<option value="engineer">Engineer</option>
|
||||
@@ -588,7 +588,7 @@ export function UsersPage() {
|
||||
placeholder="user@example.com"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -601,7 +601,7 @@ export function UsersPage() {
|
||||
placeholder="e.g. ABC12345"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -612,7 +612,7 @@ export function UsersPage() {
|
||||
onChange={(e) => setInviteForm(f => ({ ...f, role: e.target.value as 'engineer' | 'viewer' }))}
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
|
||||
'focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
'focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
>
|
||||
<option value="engineer">Engineer</option>
|
||||
|
||||
Reference in New Issue
Block a user