diff --git a/frontend/src/components/common/ErrorBoundary.tsx b/frontend/src/components/common/ErrorBoundary.tsx
index bdee3079..e2f4a371 100644
--- a/frontend/src/components/common/ErrorBoundary.tsx
+++ b/frontend/src/components/common/ErrorBoundary.tsx
@@ -1,5 +1,5 @@
import { Component, type ReactNode } from 'react'
-import { cn } from '@/lib/utils'
+import { Button } from '@/components/ui/Button'
interface Props {
children: ReactNode
@@ -45,15 +45,9 @@ export class ErrorBoundary extends Component {
{this.state.error.message}
)}
- window.location.reload()}
- className={cn(
- 'rounded-xl bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
- 'hover:opacity-90'
- )}
- >
+ window.location.reload()}>
Refresh Page
-
+
)
diff --git a/frontend/src/components/common/RouteError.tsx b/frontend/src/components/common/RouteError.tsx
index 71e9ae63..01931aea 100644
--- a/frontend/src/components/common/RouteError.tsx
+++ b/frontend/src/components/common/RouteError.tsx
@@ -1,6 +1,6 @@
import { useEffect } from 'react'
import { useRouteError, isRouteErrorResponse, useNavigate } from 'react-router-dom'
-import { cn } from '@/lib/utils'
+import { Button } from '@/components/ui/Button'
function isChunkLoadError(error: unknown): boolean {
if (!(error instanceof Error)) return false
@@ -55,24 +55,12 @@ export function RouteError() {
{errorDetails}
)}
- navigate(-1)}
- className={cn(
- 'rounded-xl border border-border px-4 py-2 text-sm font-medium text-muted-foreground',
- 'hover:bg-accent hover:text-foreground'
- )}
- >
+ navigate(-1)}>
Go Back
-
- navigate('/trees')}
- className={cn(
- 'rounded-xl bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
- 'hover:opacity-90'
- )}
- >
+
+ navigate('/trees')}>
Go Home
-
+
diff --git a/frontend/src/components/procedural/CompletionSummary.tsx b/frontend/src/components/procedural/CompletionSummary.tsx
index a563e2eb..0f283c5e 100644
--- a/frontend/src/components/procedural/CompletionSummary.tsx
+++ b/frontend/src/components/procedural/CompletionSummary.tsx
@@ -1,4 +1,5 @@
import { CheckCircle2, Clock, FileText, Download } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import type { ProceduralStep } from '@/types'
interface StepCompletion {
@@ -128,19 +129,13 @@ export function CompletionSummary({
{/* Actions */}
-
+
Export Report
-
-
+
+
Done
-
+
)
diff --git a/frontend/src/components/step-library/StepLibraryBrowser.tsx b/frontend/src/components/step-library/StepLibraryBrowser.tsx
index ad71e7da..3f28805e 100644
--- a/frontend/src/components/step-library/StepLibraryBrowser.tsx
+++ b/frontend/src/components/step-library/StepLibraryBrowser.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useMemo } from 'react'
import { Search, ChevronDown, ChevronUp, Loader2 } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { cn } from '@/lib/utils'
import { stepsApi } from '@/api/steps'
import { stepCategoriesApi } from '@/api/stepCategories'
@@ -253,12 +254,9 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
) : error ? (
{error}
-
setRetryCount(c => c + 1)}
- className="rounded-md border border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
- >
+ setRetryCount(c => c + 1)}>
Try again
-
+
) : steps.length === 0 ? (
@@ -374,12 +372,9 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
{/* Footer - Optional Create Button */}
{showCreateButton && onCreateNew && (
-
+
+ Create New Step
-
+
)}
diff --git a/frontend/src/pages/AccountSettingsPage.tsx b/frontend/src/pages/AccountSettingsPage.tsx
index 156a9c6e..51bd8bdb 100644
--- a/frontend/src/pages/AccountSettingsPage.tsx
+++ b/frontend/src/pages/AccountSettingsPage.tsx
@@ -6,6 +6,7 @@ import type { Account, AccountMember, AccountInvite } from '@/types'
import { TransferOwnershipModal } from '@/components/account/TransferOwnershipModal'
import { LeaveAccountModal } from '@/components/account/LeaveAccountModal'
import { DeleteAccountModal } from '@/components/account/DeleteAccountModal'
+import { Button } from '@/components/ui/Button'
import { Spinner } from '@/components/common/Spinner'
import { cn } from '@/lib/utils'
import { usePermissions } from '@/hooks/usePermissions'
@@ -200,29 +201,23 @@ export function AccountSettingsPage() {
}
}}
/>
-
- {isSavingName ? (
-
- ) : (
-
- )}
-
-
+
+
{
setEditedName(account?.name ?? '')
setIsEditingName(false)
}}
- className="rounded-md border border-border p-2 text-muted-foreground hover:bg-accent"
>
-
+
) : (
@@ -429,23 +424,13 @@ export function AccountSettingsPage() {
Engineer
Viewer
-
- {isInviting ? (
-
-
- Sending...
-
- ) : (
- 'Send Invite'
- )}
-
+ {isInviting ? 'Sending...' : 'Send Invite'}
+
{inviteError && (
@@ -633,30 +618,27 @@ export function AccountSettingsPage() {
Transfer Ownership
Make another member the account owner
- setShowTransferModal(true)}
- className={cn(
- 'rounded-[10px] px-3 py-1.5 text-sm font-medium',
- 'border border-amber-500/30 text-amber-400 hover:bg-amber-500/10'
- )}
+ className="border-amber-500/30 text-amber-400 hover:bg-amber-500/10"
>
Transfer
-
+
Delete Account
Permanently delete your account and all data
-
setShowDeleteModal(true)}
- className={cn(
- 'rounded-[10px] px-3 py-1.5 text-sm font-medium',
- 'border border-rose-500/30 text-rose-400 hover:bg-rose-500/10'
- )}
>
Delete
-
+
>
) : (
@@ -665,15 +647,13 @@ export function AccountSettingsPage() {
Leave Account
Leave this account and create a personal one
- setShowLeaveModal(true)}
- className={cn(
- 'rounded-[10px] px-3 py-1.5 text-sm font-medium',
- 'border border-rose-500/30 text-rose-400 hover:bg-rose-500/10'
- )}
>
Leave
-
+
)}
diff --git a/frontend/src/pages/MySharesPage.tsx b/frontend/src/pages/MySharesPage.tsx
index 17ea9a4a..020f7bfd 100644
--- a/frontend/src/pages/MySharesPage.tsx
+++ b/frontend/src/pages/MySharesPage.tsx
@@ -1,6 +1,7 @@
import { useState, useEffect, useCallback } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { Globe, Users, Copy, Check, Link2, ExternalLink, Trash2, ArrowLeft } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { Spinner } from '@/components/common/Spinner'
import { EmptyState } from '@/components/common/EmptyState'
import { ConfirmDialog } from '@/components/common/ConfirmDialog'
@@ -110,12 +111,9 @@ export default function MySharesPage() {
{error}
-
+
Try again
-
+
@@ -147,12 +145,9 @@ export default function MySharesPage() {
title="No shared sessions"
description="Share a session from the session detail page to create a link"
action={
- navigate('/sessions')}
- className="bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90 rounded-md px-4 py-2 text-sm font-medium transition-colors"
- >
+ navigate('/sessions')}>
Go to Sessions
-
+
}
/>
@@ -201,14 +196,10 @@ export default function MySharesPage() {
{/* Actions */}
- handleCopyLink(share)}
- className={cn(
- 'inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
- isCopied
- ? 'bg-emerald-400/10 text-emerald-400'
- : 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90'
- )}
+ className={isCopied ? 'bg-emerald-400/10 text-emerald-400 shadow-none hover:opacity-100' : ''}
>
{isCopied ? (
@@ -216,7 +207,7 @@ export default function MySharesPage() {
)}
{isCopied ? 'Copied' : 'Copy Link'}
-
+
- setRevokeTarget(share)}
- className="inline-flex items-center gap-1.5 text-red-400 hover:text-red-300 hover:bg-red-400/10 rounded-md px-3 py-1.5 text-sm transition-colors"
>
Revoke
-
+
)
diff --git a/frontend/src/pages/MyTreesPage.tsx b/frontend/src/pages/MyTreesPage.tsx
index 38e6df6f..44dabe7f 100644
--- a/frontend/src/pages/MyTreesPage.tsx
+++ b/frontend/src/pages/MyTreesPage.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react'
import { useNavigate, Link } from 'react-router-dom'
import { Play, Pencil, Share2, Trash2, GitBranch, Clock, TrendingUp, FolderTree, Plus, ListOrdered, ChevronDown, Wrench } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { treesApi } from '@/api/trees'
import { sessionsApi } from '@/api/sessions'
import type { TreeListItem } from '@/types'
@@ -125,14 +126,13 @@ export function MyTreesPage() {
{canCreateTrees && (
-
setShowCreateMenu(!showCreateMenu)}
- className="flex items-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
>
Create New
-
+
{showCreateMenu && (
<>
setShowCreateMenu(false)} />
@@ -297,17 +297,13 @@ export function MyTreesPage() {
{/* Actions */}
-
handleStartSession(tree)}
- className={cn(
- 'flex flex-1 items-center justify-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium',
- 'hover:opacity-90'
- )}
+ className="flex-1"
>
Start
-
+
{canEditTree({ author_id: tree.author_id, account_id: tree.account_id }) && (
)}
-
{
setTreeToShare(tree)
setShowShareModal(true)
}}
- className={cn(
- 'rounded-md border border-border p-2 text-muted-foreground',
- 'hover:bg-accent hover:text-foreground'
- )}
title="Share tree"
>
-
-
+ setForkTarget(tree)}
- className="rounded-md border border-border p-2 text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
title="Fork flow"
>
-
-
+ {
setTreeToDelete(tree)
setShowDeleteConfirm(true)
}}
- className={cn(
- 'rounded-md border border-border p-2 text-muted-foreground',
- 'hover:bg-red-400/10 hover:text-red-400'
- )}
title="Delete tree"
>
-
+
))}
diff --git a/frontend/src/pages/ProceduralEditorPage.tsx b/frontend/src/pages/ProceduralEditorPage.tsx
index 5419b0ce..b1c6a73e 100644
--- a/frontend/src/pages/ProceduralEditorPage.tsx
+++ b/frontend/src/pages/ProceduralEditorPage.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState, useCallback } from 'react'
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'
import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText, Calendar, Sparkles, Layers } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { treesApi } from '@/api/trees'
import { useProceduralEditorStore } from '@/store/proceduralEditorStore'
import { CollapsibleEditorSection } from '@/components/procedural-editor/CollapsibleEditorSection'
@@ -220,21 +221,20 @@ export function ProceduralEditorPage() {
AI Assist
-
handleSave('draft')}
disabled={isSaving}
- className="flex items-center gap-1.5 rounded-md border border-border px-3 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50"
>
Save Draft
-
-
+ handleSave('published')}
- disabled={isSaving}
- className="flex items-center gap-1.5 rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90 disabled:opacity-50"
+ loading={isSaving}
>
{isSaving ? 'Saving...' : 'Publish'}
-
+
diff --git a/frontend/src/pages/SessionDetailPage.tsx b/frontend/src/pages/SessionDetailPage.tsx
index 0c1a6074..71710514 100644
--- a/frontend/src/pages/SessionDetailPage.tsx
+++ b/frontend/src/pages/SessionDetailPage.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { Copy, Check, Eye, Save, Share2, CheckCircle2, AlertTriangle, ArrowUpRight, HelpCircle, Flag } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { sessionsApi } from '@/api/sessions'
import { stepsApi } from '@/api/steps'
import { ExportPreviewModal } from '@/components/session/ExportPreviewModal'
@@ -391,13 +392,10 @@ export function SessionDetailPage() {
{/* Primary action: Copy for Ticket */}
-
+
{copiedPsa ? : }
{copiedPsa ? 'Copied!' : 'Copy for Ticket'}
-
+
) : !session.completed_at ? (
@@ -410,12 +408,9 @@ export function SessionDetailPage() {
Set an outcome to finalize this session and generate documentation.
- setShowOutcomeModal(true)}
- className="shrink-0 rounded-lg bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
- >
+ setShowOutcomeModal(true)} className="shrink-0">
Complete Session
-
+
) : null}
@@ -462,14 +457,15 @@ export function SessionDetailPage() {
>
{copied ? : }
-
{isExporting ? 'Loading...' : 'Preview'}
-
+
{/* Copy for ticket (secondary position when session is complete) */}
{session.completed_at && (
{canCreateSteps && (
- setCreateOpen(true)}
- className="rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
- >
+ setCreateOpen(true)}>
+ Create Step
-
+
)}
@@ -147,20 +145,22 @@ export default function StepLibraryPage() {
{deleteError}
)}
- { setDeletingStep(null); setDeleteError(null) }}
disabled={isDeleting}
- className="flex-1 rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50"
+ className="flex-1"
>
Cancel
-
-
+
{isDeleting ? 'Deleting...' : 'Delete'}
-
+
diff --git a/frontend/src/pages/TreeEditorPage.tsx b/frontend/src/pages/TreeEditorPage.tsx
index 344a5284..2b47b0ee 100644
--- a/frontend/src/pages/TreeEditorPage.tsx
+++ b/frontend/src/pages/TreeEditorPage.tsx
@@ -2,6 +2,7 @@ import { useEffect, useState, useCallback, useRef } from 'react'
import { useParams, useNavigate, useBlocker } from 'react-router-dom'
import { useStore } from 'zustand'
import { Undo2, Redo2, Save, CheckCircle2, Monitor, FileText, Code2, LayoutList, BarChart3, Settings, Download, Sparkles } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { getMonacoEditor } from '@/components/tree-editor/code-mode'
import { treesApi } from '@/api/trees'
import { treeMarkdownApi } from '@/api/treeMarkdown'
@@ -508,15 +509,9 @@ export function TreeEditorPage() {
The tree editor requires a larger screen for the best experience. Please open this page on a desktop or tablet in landscape mode.
- navigate('/trees')}
- className={cn(
- 'rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
- 'hover:opacity-90'
- )}
- >
+ navigate('/trees')}>
Back to Library
-
+
)
}
@@ -535,24 +530,12 @@ export function TreeEditorPage() {
You have an unsaved draft from a previous session. Would you like to restore it?
-
+
Restore Draft
-
-
+
+
Start Fresh
-
+
@@ -567,24 +550,12 @@ export function TreeEditorPage() {
You have unsaved changes. Are you sure you want to leave?
-
+
Stay
-
-
+
+
Leave Without Saving
-
+
@@ -787,32 +758,26 @@ export function TreeEditorPage() {
{/* Save Draft */}
-
Save Draft
-
+
{/* Publish */}
-
{isSaving ? 'Publishing...' : 'Publish'}
-
+
diff --git a/frontend/src/pages/TreeLibraryPage.tsx b/frontend/src/pages/TreeLibraryPage.tsx
index aed0be7d..1865314c 100644
--- a/frontend/src/pages/TreeLibraryPage.tsx
+++ b/frontend/src/pages/TreeLibraryPage.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState, useCallback, useMemo } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { X, RotateCcw, Play, FileUp } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { treesApi } from '@/api/trees'
import { categoriesApi } from '@/api/categories'
import { foldersApi } from '@/api/folders'
@@ -283,13 +284,13 @@ export function TreeLibraryPage() {
{canCreateTrees && (
- setShowImportModal(true)}
- className="flex items-center gap-2 rounded-lg border border-border bg-[rgba(255,255,255,0.04)] px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] transition-colors"
>
Import
-
+
-
+
Search
-
+
-
navigate(getSessionResumePath(s.tree_id, s.tree_snapshot?.tree_type), { state: { sessionId: s.id } })}
- className="flex items-center gap-1.5 rounded-md bg-gradient-brand px-3 py-1.5 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
>
Resume
-
+
dismissSession(s.id)}
className="rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground"
diff --git a/frontend/src/pages/TreeNavigationPage.tsx b/frontend/src/pages/TreeNavigationPage.tsx
index 1de7c257..c273e680 100644
--- a/frontend/src/pages/TreeNavigationPage.tsx
+++ b/frontend/src/pages/TreeNavigationPage.tsx
@@ -21,6 +21,7 @@ import { StepFeedback } from '@/components/session/StepFeedback'
import { buildSessionShareUrl, getLatestActiveShareForSession } from '@/lib/sessionShare'
import { CopilotPanel } from '@/components/copilot/CopilotPanel'
import { CopilotToggle } from '@/components/copilot/CopilotToggle'
+import { Button } from '@/components/ui/Button'
interface LocationState {
sessionId?: string
@@ -601,15 +602,9 @@ export function TreeNavigationPage() {
/>
-
+
Start Troubleshooting
-
+
)
@@ -940,17 +935,14 @@ export function TreeNavigationPage() {
const targetLabel = targetNode?.question || targetNode?.title || 'next step'
return (
-
Continue to: {targetLabel.length > 50 ? `${targetLabel.slice(0, 50)}...` : targetLabel}
-
+
)
})()}
@@ -1063,15 +1055,9 @@ export function TreeNavigationPage() {
)}
{currentNode.next_node_id && (
- handleContinue()}
- className={cn(
- 'rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
- 'hover:opacity-90'
- )}
- >
+ handleContinue()}>
Continue
-
+
)}
>
)}
diff --git a/frontend/src/pages/account/TeamCategoriesPage.tsx b/frontend/src/pages/account/TeamCategoriesPage.tsx
index c2665cdc..ffa5c3b9 100644
--- a/frontend/src/pages/account/TeamCategoriesPage.tsx
+++ b/frontend/src/pages/account/TeamCategoriesPage.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react'
import { Plus, Trash2, Pencil, FolderTree } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { cn } from '@/lib/utils'
import { toast } from '@/lib/toast'
import { Modal } from '@/components/common/Modal'
@@ -86,10 +87,10 @@ export function TeamCategoriesPage() {
title="Team Categories"
description="Manage tree categories for your team"
action={(
- setCreateOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
+ setCreateOpen(true)}>
Create Category
-
+
)}
/>
@@ -132,8 +133,8 @@ export function TeamCategoriesPage() {
setCreateOpen(false)} title="Create Category" size="sm"
footer={
- setCreateOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Create
+ setCreateOpen(false)}>Cancel
+ Create
}
>
@@ -157,8 +158,8 @@ export function TeamCategoriesPage() {
setEditCategory(null)} title="Edit Category" size="sm"
footer={
- setEditCategory(null)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Save
+ setEditCategory(null)}>Cancel
+ Save
}
>
diff --git a/frontend/src/pages/admin/FeatureFlagsPage.tsx b/frontend/src/pages/admin/FeatureFlagsPage.tsx
index 26f0d077..42ecf482 100644
--- a/frontend/src/pages/admin/FeatureFlagsPage.tsx
+++ b/frontend/src/pages/admin/FeatureFlagsPage.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react'
import { Plus, Trash2, ToggleLeft } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { DataTable, PageHeader, StatusBadge, ActionMenu, EmptyState } from '@/components/admin'
import type { Column } from '@/components/admin'
import { Modal } from '@/components/common/Modal'
@@ -153,10 +154,10 @@ export function FeatureFlagsPage() {
title="Feature Flags"
description="Manage feature availability per plan and account"
action={
- setCreateOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
+ setCreateOpen(true)}>
Create Flag
-
+
}
/>
@@ -172,10 +173,10 @@ export function FeatureFlagsPage() {
Account Overrides
-
setOverrideOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
+ setOverrideOpen(true)}>
Add Override
-
+
o.id} isLoading={loading}
@@ -188,8 +189,8 @@ export function FeatureFlagsPage() {
setCreateOpen(false)} title="Create Feature Flag" size="sm"
footer={
- setCreateOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Create
+ setCreateOpen(false)}>Cancel
+ Create
}
>
@@ -213,8 +214,8 @@ export function FeatureFlagsPage() {
setOverrideOpen(false)} title="Add Account Override" size="sm"
footer={
- setOverrideOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Create
+ setOverrideOpen(false)}>Cancel
+ Create
}
>
diff --git a/frontend/src/pages/admin/GlobalCategoriesPage.tsx b/frontend/src/pages/admin/GlobalCategoriesPage.tsx
index cc42e109..aa1d8158 100644
--- a/frontend/src/pages/admin/GlobalCategoriesPage.tsx
+++ b/frontend/src/pages/admin/GlobalCategoriesPage.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react'
import { Plus, Trash2, Pencil, FolderTree } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { DataTable, PageHeader, ActionMenu, EmptyState } from '@/components/admin'
import type { Column } from '@/components/admin'
import { Modal } from '@/components/common/Modal'
@@ -95,10 +96,10 @@ export function GlobalCategoriesPage() {
title="Global Categories"
description="Manage tree categories available to all accounts"
action={
- setCreateOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
+ setCreateOpen(true)}>
Create Category
-
+
}
/>
@@ -118,8 +119,8 @@ export function GlobalCategoriesPage() {
size="sm"
footer={
- setCreateOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Create
+ setCreateOpen(false)}>Cancel
+ Create
}
>
@@ -147,8 +148,8 @@ export function GlobalCategoriesPage() {
size="sm"
footer={
- setEditCategory(null)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Save
+ setEditCategory(null)}>Cancel
+ Save
}
>
diff --git a/frontend/src/pages/admin/InviteCodesPage.tsx b/frontend/src/pages/admin/InviteCodesPage.tsx
index 05788ce5..d938d3b7 100644
--- a/frontend/src/pages/admin/InviteCodesPage.tsx
+++ b/frontend/src/pages/admin/InviteCodesPage.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react'
import { Plus, Copy, Trash2, Ticket, Mail, MailCheck, RefreshCw } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { DataTable, PageHeader, StatusBadge, ActionMenu, EmptyState } from '@/components/admin'
import type { Column } from '@/components/admin'
import { Modal } from '@/components/common/Modal'
@@ -215,16 +216,10 @@ export function InviteCodesPage() {
title="Invite Codes"
description="Create and manage registration invite codes with plan assignment"
action={
- setCreateOpen(true)}
- className={cn(
- 'flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium',
- 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90'
- )}
- >
+ setCreateOpen(true)}>
Create Code
-
+
}
/>
@@ -249,19 +244,10 @@ export function InviteCodesPage() {
size="sm"
footer={
- { setCreateOpen(false); resetForm() }}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
- >
- Cancel
-
-
+ { setCreateOpen(false); resetForm() }}>Cancel
+
{creating ? 'Creating...' : 'Create'}
-
+
}
>
diff --git a/frontend/src/pages/admin/PlanLimitsPage.tsx b/frontend/src/pages/admin/PlanLimitsPage.tsx
index 63026298..a7778d1e 100644
--- a/frontend/src/pages/admin/PlanLimitsPage.tsx
+++ b/frontend/src/pages/admin/PlanLimitsPage.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react'
import { Plus, Trash2, Gauge } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { DataTable, PageHeader, ActionMenu, EmptyState } from '@/components/admin'
import type { Column } from '@/components/admin'
import { Modal } from '@/components/common/Modal'
@@ -127,13 +128,10 @@ export function PlanLimitsPage() {
Account Overrides
-
setCreateOverride(true)}
- className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}
- >
+ setCreateOverride(true)}>
Add Override
-
+
- setEditPlan(null)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Save
+ setEditPlan(null)}>Cancel
+ Save
}
>
@@ -185,8 +183,8 @@ export function PlanLimitsPage() {
size="sm"
footer={
- setCreateOverride(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel
- Create
+ setCreateOverride(false)}>Cancel
+ Create
}
>
diff --git a/frontend/src/pages/admin/UserDetailPage.tsx b/frontend/src/pages/admin/UserDetailPage.tsx
index 40deb024..019e83ae 100644
--- a/frontend/src/pages/admin/UserDetailPage.tsx
+++ b/frontend/src/pages/admin/UserDetailPage.tsx
@@ -1,6 +1,7 @@
import { useState, useEffect, useCallback } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { ArrowLeft, Shield, Crown, UserCheck, UserX, Clock, Ticket, KeyRound, Copy, Check, Archive, ArchiveRestore, Trash2 } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { StatusBadge } from '@/components/admin'
import { Modal } from '@/components/common/Modal'
import { Spinner } from '@/components/common/Spinner'
@@ -205,12 +206,9 @@ export function UserDetailPage() {
title="User not found"
description="This user may have been removed or is unavailable."
action={(
-
navigate('/admin/users')}
- className="rounded-md border border-border px-4 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
- >
+ navigate('/admin/users')}>
Back to Users
-
+
)}
/>
)
@@ -525,18 +523,8 @@ export function UserDetailPage() {
size="sm"
footer={
- setPlanModalOpen(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
- >
- Cancel
-
-
- Update Plan
-
+ setPlanModalOpen(false)}>Cancel
+ Update Plan
}
>
@@ -563,19 +551,10 @@ export function UserDetailPage() {
size="sm"
footer={
- setResetModalOpen(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
- >
- Cancel
-
-
+ setResetModalOpen(false)}>Cancel
+
{resetLoading ? 'Resetting...' : 'Reset Password'}
-
+
}
>
@@ -624,12 +603,7 @@ export function UserDetailPage() {
size="sm"
footer={
- { setResetTempPassword(null); setResetModalOpen(false) }}
- className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
- >
- Done
-
+ { setResetTempPassword(null); setResetModalOpen(false) }}>Done
}
>
@@ -663,18 +637,10 @@ export function UserDetailPage() {
size="sm"
footer={
- setTrialModalOpen(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
- >
- Cancel
-
-
+ setTrialModalOpen(false)}>Cancel
+
{user.subscription?.status === 'trialing' ? 'Extend' : 'Start Trial'}
-
+
}
>
@@ -700,23 +666,13 @@ export function UserDetailPage() {
size="sm"
footer={
- setSuperAdminModalOpen(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
- >
- Cancel
-
- setSuperAdminModalOpen(false)}>Cancel
+
{user.is_super_admin ? 'Remove Access' : 'Promote'}
-
+
}
>
@@ -741,19 +697,11 @@ export function UserDetailPage() {
size="sm"
footer={
- setHardDeleteModalOpen(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
- >
- Cancel
-
+ setHardDeleteModalOpen(false)}>Cancel
{hardDeleteBlockers && Object.keys(hardDeleteBlockers).length === 0 && (
-
+
Delete Permanently
-
+
)}
}
diff --git a/frontend/src/pages/admin/UsersPage.tsx b/frontend/src/pages/admin/UsersPage.tsx
index 7a372610..f982acef 100644
--- a/frontend/src/pages/admin/UsersPage.tsx
+++ b/frontend/src/pages/admin/UsersPage.tsx
@@ -1,6 +1,7 @@
import { useState, useEffect, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { UserCheck, UserX, Shield, ArrowRightLeft, ExternalLink, UserPlus, Copy, Check, Mail } from 'lucide-react'
+import { Button } from '@/components/ui/Button'
import { DataTable, Pagination, SearchInput, PageHeader, StatusBadge, ActionMenu } from '@/components/admin'
import type { Column } from '@/components/admin'
import { Modal } from '@/components/common/Modal'
@@ -266,20 +267,14 @@ export function UsersPage() {
- setShowInviteModal(true)}
- className="flex items-center gap-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-accent transition-colors"
- >
+ setShowInviteModal(true)}>
Invite User
-
- setShowCreateModal(true)}
- className="flex items-center gap-2 rounded-lg bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 transition-colors"
- >
+
+ setShowCreateModal(true)}>
Create User
-
+
@@ -324,18 +319,8 @@ export function UsersPage() {
size="sm"
footer={
- setRoleModalUser(null)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
- >
- Cancel
-
-
- Save
-
+ setRoleModalUser(null)}>Cancel
+ Save
}
>
@@ -365,19 +350,8 @@ export function UsersPage() {
size="sm"
footer={
- setMoveModalUser(null)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
- >
- Cancel
-
-
- Move
-
+ setMoveModalUser(null)}>Cancel
+ Move
}
>
@@ -409,19 +383,10 @@ export function UsersPage() {
size="sm"
footer={
- setShowCreateModal(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
- >
- Cancel
-
-
+ setShowCreateModal(false)}>Cancel
+
{createLoading ? 'Creating...' : 'Create User'}
-
+
}
>
@@ -520,12 +485,7 @@ export function UsersPage() {
size="sm"
footer={
- setTempPassword(null)}
- className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
- >
- Done
-
+ setTempPassword(null)}>Done
}
>
@@ -562,19 +522,10 @@ export function UsersPage() {
size="sm"
footer={
- setShowInviteModal(false)}
- className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
- >
- Cancel
-
-
+ setShowInviteModal(false)}>Cancel
+
{inviteLoading ? 'Sending...' : 'Send Invite'}
-
+
}
>