Implement dark-first design system with Geist typography (#28)
Co-authored-by: Julian Tabel <juliantabel.jt@gmail.com> Co-committed-by: Julian Tabel <juliantabel.jt@gmail.com>
This commit was merged in pull request #28.
This commit is contained in:
@@ -23,7 +23,7 @@ export function AdminLayout() {
|
||||
`block px-3 py-2 rounded-md text-sm font-medium whitespace-nowrap ${
|
||||
isActive
|
||||
? 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-200'
|
||||
: 'hover:bg-gray-100 dark:hover:bg-gray-700'
|
||||
: 'hover:bg-surface-2'
|
||||
}`
|
||||
}
|
||||
>
|
||||
|
||||
@@ -61,26 +61,26 @@ export function AdminTable<T>({
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
|
||||
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead className="bg-gray-50 dark:bg-gray-800">
|
||||
<div className="border border-border-default rounded-lg overflow-hidden">
|
||||
<table className="min-w-full divide-y divide-border-default">
|
||||
<thead className="bg-surface-1">
|
||||
<tr>
|
||||
{columns.map((col) => (
|
||||
<th
|
||||
key={col.header}
|
||||
className={`px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider ${col.className ?? ''}`}
|
||||
className={`px-4 py-3 text-left text-xs font-medium text-text-tertiary uppercase tracking-wider ${col.className ?? ''}`}
|
||||
>
|
||||
{col.header}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tbody className="bg-surface-0 divide-y divide-border-default">
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<tr key={i}>
|
||||
{columns.map((col) => (
|
||||
<td key={col.header} className={`px-4 py-3 ${col.className ?? ''}`}>
|
||||
<div className="h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
|
||||
<div className="h-4 bg-surface-3 rounded animate-pulse" />
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
@@ -93,17 +93,17 @@ export function AdminTable<T>({
|
||||
|
||||
if (data.length === 0) {
|
||||
return (
|
||||
<div className="text-center py-8 text-gray-500 dark:text-gray-400 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<div className="text-center py-8 text-text-tertiary border border-border-default rounded-lg">
|
||||
{emptyMessage}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
|
||||
<div className="border border-border-default rounded-lg overflow-hidden">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead className="bg-gray-50 dark:bg-gray-800">
|
||||
<table className="min-w-full divide-y divide-border-default">
|
||||
<thead className="bg-surface-1">
|
||||
<tr>
|
||||
{columns.map((col) => {
|
||||
const sortable = !!col.sortKey
|
||||
@@ -112,7 +112,7 @@ export function AdminTable<T>({
|
||||
<th
|
||||
key={col.header}
|
||||
onClick={sortable ? () => handleSort(col.header) : undefined}
|
||||
className={`px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider ${col.className ?? ''} ${sortable ? 'cursor-pointer select-none hover:text-gray-700 dark:hover:text-gray-200' : ''}`}
|
||||
className={`px-4 py-3 text-left text-xs font-medium text-text-tertiary uppercase tracking-wider ${col.className ?? ''} ${sortable ? 'cursor-pointer select-none hover:text-text-primary' : ''}`}
|
||||
>
|
||||
<span className="inline-flex items-center gap-1">
|
||||
{col.header}
|
||||
@@ -127,14 +127,12 @@ export function AdminTable<T>({
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tbody className="bg-surface-0 divide-y divide-border-default">
|
||||
{sortedData.map((row) => (
|
||||
<tr
|
||||
key={keyFn(row)}
|
||||
onClick={onRowClick ? () => onRowClick(row) : undefined}
|
||||
className={
|
||||
onRowClick ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800' : ''
|
||||
}
|
||||
className={onRowClick ? 'cursor-pointer hover:bg-surface-2' : ''}
|
||||
>
|
||||
{columns.map((col) => (
|
||||
<td
|
||||
|
||||
@@ -107,7 +107,7 @@ export function BossBattleFormModal({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onEditTeam}
|
||||
className="text-sm text-blue-600 dark:text-blue-400 hover:underline"
|
||||
className="text-sm text-text-link hover:underline"
|
||||
>
|
||||
Edit Team ({boss?.pokemon.length ?? 0})
|
||||
</button>
|
||||
@@ -123,7 +123,7 @@ export function BossBattleFormModal({
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="e.g. Brock"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -131,7 +131,7 @@ export function BossBattleFormModal({
|
||||
<select
|
||||
value={bossType}
|
||||
onChange={(e) => setBossType(e.target.value as typeof bossType)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
>
|
||||
{BOSS_TYPES.map((t) => (
|
||||
<option key={t.value} value={t.value}>
|
||||
@@ -145,7 +145,7 @@ export function BossBattleFormModal({
|
||||
<select
|
||||
value={specialtyType}
|
||||
onChange={(e) => setSpecialtyType(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600 capitalize"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default capitalize"
|
||||
>
|
||||
<option value="">None</option>
|
||||
{POKEMON_TYPES.map((t) => (
|
||||
@@ -165,7 +165,7 @@ export function BossBattleFormModal({
|
||||
value={location}
|
||||
onChange={(e) => setLocation(e.target.value)}
|
||||
placeholder="e.g. Pewter City Gym"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -178,7 +178,7 @@ export function BossBattleFormModal({
|
||||
min={1}
|
||||
value={levelCap}
|
||||
onChange={(e) => setLevelCap(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -189,7 +189,7 @@ export function BossBattleFormModal({
|
||||
min={1}
|
||||
value={order}
|
||||
onChange={(e) => setOrder(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -202,7 +202,7 @@ export function BossBattleFormModal({
|
||||
value={section}
|
||||
onChange={(e) => setSection(e.target.value)}
|
||||
placeholder="e.g. Main Story, Endgame"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
{games && games.length > 1 && (
|
||||
@@ -211,7 +211,7 @@ export function BossBattleFormModal({
|
||||
<select
|
||||
value={gameId}
|
||||
onChange={(e) => setGameId(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
>
|
||||
<option value="">All games</option>
|
||||
{games.map((g) => (
|
||||
@@ -229,7 +229,7 @@ export function BossBattleFormModal({
|
||||
<select
|
||||
value={afterRouteId}
|
||||
onChange={(e) => setAfterRouteId(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
>
|
||||
<option value="">None</option>
|
||||
{sortedRoutes.map((r) => (
|
||||
@@ -248,7 +248,7 @@ export function BossBattleFormModal({
|
||||
value={badgeName}
|
||||
onChange={(e) => setBadgeName(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -258,7 +258,7 @@ export function BossBattleFormModal({
|
||||
value={badgeImageUrl}
|
||||
onChange={(e) => setBadgeImageUrl(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -270,7 +270,7 @@ export function BossBattleFormModal({
|
||||
value={spriteUrl}
|
||||
onChange={(e) => setSpriteUrl(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</FormModal>
|
||||
|
||||
@@ -150,13 +150,13 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-black/50" onClick={onClose} />
|
||||
<div className="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="relative bg-surface-1 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div className="px-6 py-4 border-b border-border-default">
|
||||
<h2 className="text-lg font-semibold">{boss.name}'s Team</h2>
|
||||
</div>
|
||||
|
||||
{/* Variant tabs */}
|
||||
<div className="px-6 pt-3 flex items-center gap-1 flex-wrap border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="px-6 pt-3 flex items-center gap-1 flex-wrap border-b border-border-default">
|
||||
{variants.map((v, i) => (
|
||||
<button
|
||||
key={v.label ?? '__default'}
|
||||
@@ -164,8 +164,8 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
||||
onClick={() => setActiveTab(i)}
|
||||
className={`px-3 py-1.5 text-sm font-medium rounded-t-md border border-b-0 transition-colors ${
|
||||
activeTab === i
|
||||
? 'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 text-gray-900 dark:text-gray-100'
|
||||
: 'bg-gray-50 dark:bg-gray-700 border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
|
||||
? 'bg-surface-1 border-border-default text-text-primary'
|
||||
: 'bg-surface-2 border-transparent text-text-tertiary hover:text-text-secondary'
|
||||
}`}
|
||||
>
|
||||
{v.label ?? 'Default'}
|
||||
@@ -187,7 +187,7 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowAddVariant(true)}
|
||||
className="px-2 py-1.5 text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
|
||||
className="px-2 py-1.5 text-sm text-text-link hover:text-blue-700 dark:hover:text-blue-300"
|
||||
title="Add variant"
|
||||
>
|
||||
+
|
||||
@@ -206,13 +206,13 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
||||
if (e.key === 'Escape') setShowAddVariant(false)
|
||||
}}
|
||||
placeholder="Variant name..."
|
||||
className="px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600 w-40"
|
||||
className="px-2 py-1 text-sm border rounded bg-surface-2 border-border-default w-40"
|
||||
autoFocus
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={addVariant}
|
||||
className="px-2 py-1 text-sm text-blue-600 dark:text-blue-400"
|
||||
className="px-2 py-1 text-sm text-text-link"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
@@ -247,7 +247,7 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
||||
max={100}
|
||||
value={slot.level}
|
||||
onChange={(e) => updateSlot(index, 'level', e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
@@ -265,25 +265,25 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
||||
<button
|
||||
type="button"
|
||||
onClick={addSlot}
|
||||
className="w-full py-2 text-sm text-blue-600 dark:text-blue-400 border border-dashed border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="w-full py-2 text-sm text-text-link border border-dashed border-border-default rounded-md hover:bg-surface-2"
|
||||
>
|
||||
+ Add Pokemon
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-3">
|
||||
<div className="px-6 py-4 border-t border-border-default flex justify-end gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSaving}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-accent-600 text-white hover:bg-accent-500 disabled:opacity-50"
|
||||
>
|
||||
{isSaving ? 'Saving...' : 'Save Team'}
|
||||
</button>
|
||||
|
||||
@@ -53,8 +53,8 @@ export function BulkImportModal({
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-black/50" onClick={onClose} />
|
||||
<div className="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="relative bg-surface-1 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div className="px-6 py-4 border-b border-border-default">
|
||||
<h2 className="text-lg font-semibold">{title}</h2>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
@@ -66,12 +66,12 @@ export function BulkImportModal({
|
||||
value={json}
|
||||
onChange={(e) => setJson(e.target.value)}
|
||||
placeholder={example}
|
||||
className="w-full px-3 py-2 border rounded-md font-mono text-sm dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md font-mono text-sm bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="p-3 bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300 rounded-md text-sm">
|
||||
<div className="p-3 bg-status-failed-bg text-status-failed rounded-md text-sm">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
@@ -82,7 +82,7 @@ export function BulkImportModal({
|
||||
{createdLabel}: {result.created}, {updatedLabel}: {result.updated}
|
||||
</p>
|
||||
{result.errors.length > 0 && (
|
||||
<ul className="mt-2 list-disc list-inside text-red-600 dark:text-red-400">
|
||||
<ul className="mt-2 list-disc list-inside text-status-failed">
|
||||
{result.errors.map((err, i) => (
|
||||
<li key={i}>{err}</li>
|
||||
))}
|
||||
@@ -91,18 +91,18 @@ export function BulkImportModal({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-3">
|
||||
<div className="px-6 py-4 border-t border-border-default flex justify-end gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting || !json.trim()}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-accent-600 text-white hover:bg-accent-500 disabled:opacity-50"
|
||||
>
|
||||
{isSubmitting ? 'Importing...' : 'Import'}
|
||||
</button>
|
||||
|
||||
@@ -18,17 +18,17 @@ export function DeleteConfirmModal({
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-black/50" onClick={onCancel} />
|
||||
<div className="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4">
|
||||
<div className="relative bg-surface-1 rounded-lg shadow-xl max-w-md w-full mx-4">
|
||||
<div className="px-6 py-4">
|
||||
<h2 className="text-lg font-semibold text-red-600 dark:text-red-400">{title}</h2>
|
||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-300">{message}</p>
|
||||
{error && <p className="mt-2 text-sm text-red-600 dark:text-red-400">{error}</p>}
|
||||
<h2 className="text-lg font-semibold text-status-failed">{title}</h2>
|
||||
<p className="mt-2 text-sm text-text-secondary">{message}</p>
|
||||
{error && <p className="mt-2 text-sm text-status-failed">{error}</p>}
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-3">
|
||||
<div className="px-6 py-4 border-t border-border-default flex justify-end gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
|
||||
@@ -74,7 +74,7 @@ export function EvolutionFormModal({
|
||||
<select
|
||||
value={trigger}
|
||||
onChange={(e) => setTrigger(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
>
|
||||
{TRIGGER_OPTIONS.map((t) => (
|
||||
<option key={t} value={t}>
|
||||
@@ -92,7 +92,7 @@ export function EvolutionFormModal({
|
||||
value={minLevel}
|
||||
onChange={(e) => setMinLevel(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -102,7 +102,7 @@ export function EvolutionFormModal({
|
||||
value={item}
|
||||
onChange={(e) => setItem(e.target.value)}
|
||||
placeholder="e.g. thunder-stone"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -112,7 +112,7 @@ export function EvolutionFormModal({
|
||||
value={heldItem}
|
||||
onChange={(e) => setHeldItem(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -122,7 +122,7 @@ export function EvolutionFormModal({
|
||||
value={condition}
|
||||
onChange={(e) => setCondition(e.target.value)}
|
||||
placeholder="e.g. high-happiness, daytime"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -132,7 +132,7 @@ export function EvolutionFormModal({
|
||||
value={region}
|
||||
onChange={(e) => setRegion(e.target.value)}
|
||||
placeholder="e.g. alola (blank = all regions)"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</FormModal>
|
||||
|
||||
@@ -33,14 +33,14 @@ export function FormModal({
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-black/50" onClick={onClose} />
|
||||
<div className="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="relative bg-surface-1 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div className="px-6 py-4 border-b border-border-default">
|
||||
<h2 className="text-lg font-semibold">{title}</h2>
|
||||
{headerExtra}
|
||||
</div>
|
||||
<form onSubmit={onSubmit}>
|
||||
<div className="px-6 py-4 space-y-4">{children}</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex items-center gap-3">
|
||||
<div className="px-6 py-4 border-t border-border-default flex items-center gap-3">
|
||||
{onDelete && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -53,7 +53,7 @@ export function FormModal({
|
||||
}
|
||||
}}
|
||||
onBlur={() => setConfirmingDelete(false)}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md text-red-600 dark:text-red-400 border border-red-300 dark:border-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md text-status-failed border border-red-300 dark:border-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 disabled:opacity-50"
|
||||
>
|
||||
{isDeleting ? 'Deleting...' : confirmingDelete ? 'Confirm?' : 'Delete'}
|
||||
</button>
|
||||
@@ -62,14 +62,14 @@ export function FormModal({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-accent-600 text-white hover:bg-accent-500 disabled:opacity-50"
|
||||
>
|
||||
{isSubmitting ? 'Saving...' : submitLabel}
|
||||
</button>
|
||||
|
||||
@@ -63,7 +63,7 @@ export function GameFormModal({
|
||||
isDeleting={isDeleting}
|
||||
headerExtra={
|
||||
detailUrl ? (
|
||||
<Link to={detailUrl} className="text-sm text-blue-600 dark:text-blue-400 hover:underline">
|
||||
<Link to={detailUrl} className="text-sm text-text-link hover:underline">
|
||||
View Routes & Bosses
|
||||
</Link>
|
||||
) : undefined
|
||||
@@ -76,7 +76,7 @@ export function GameFormModal({
|
||||
required
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -89,7 +89,7 @@ export function GameFormModal({
|
||||
setSlug(e.target.value)
|
||||
setAutoSlug(false)
|
||||
}}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
@@ -101,7 +101,7 @@ export function GameFormModal({
|
||||
min={1}
|
||||
value={generation}
|
||||
onChange={(e) => setGeneration(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -111,7 +111,7 @@ export function GameFormModal({
|
||||
required
|
||||
value={region}
|
||||
onChange={(e) => setRegion(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,7 +122,7 @@ export function GameFormModal({
|
||||
value={boxArtUrl}
|
||||
onChange={(e) => setBoxArtUrl(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -132,7 +132,7 @@ export function GameFormModal({
|
||||
value={releaseYear}
|
||||
onChange={(e) => setReleaseYear(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</FormModal>
|
||||
|
||||
@@ -86,16 +86,16 @@ export function PokemonFormModal({
|
||||
`px-3 py-1.5 text-sm font-medium rounded-t-md border-b-2 transition-colors ${
|
||||
activeTab === tab
|
||||
? 'border-blue-600 text-blue-600 dark:border-blue-400 dark:text-blue-400'
|
||||
: 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
|
||||
: 'border-transparent text-text-tertiary hover:text-text-secondary'
|
||||
}`
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-black/50" onClick={onClose} />
|
||||
<div className="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] flex flex-col">
|
||||
<div className="relative bg-surface-1 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] flex flex-col">
|
||||
{/* Header */}
|
||||
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700 shrink-0">
|
||||
<div className="px-6 py-4 border-b border-border-default shrink-0">
|
||||
<h2 className="text-lg font-semibold">{pokemon ? 'Edit Pokemon' : 'Add Pokemon'}</h2>
|
||||
{isEdit && (
|
||||
<div className="flex gap-1 mt-2">
|
||||
@@ -125,7 +125,7 @@ export function PokemonFormModal({
|
||||
min={1}
|
||||
value={pokeapiId}
|
||||
onChange={(e) => setPokeapiId(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -136,7 +136,7 @@ export function PokemonFormModal({
|
||||
min={1}
|
||||
value={nationalDex}
|
||||
onChange={(e) => setNationalDex(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -146,7 +146,7 @@ export function PokemonFormModal({
|
||||
required
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -157,7 +157,7 @@ export function PokemonFormModal({
|
||||
value={types}
|
||||
onChange={(e) => setTypes(e.target.value)}
|
||||
placeholder="Fire, Flying"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -167,11 +167,11 @@ export function PokemonFormModal({
|
||||
value={spriteUrl}
|
||||
onChange={(e) => setSpriteUrl(e.target.value)}
|
||||
placeholder="Optional"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex items-center gap-3 shrink-0">
|
||||
<div className="px-6 py-4 border-t border-border-default flex items-center gap-3 shrink-0">
|
||||
{onDelete && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -184,7 +184,7 @@ export function PokemonFormModal({
|
||||
}
|
||||
}}
|
||||
onBlur={() => setConfirmingDelete(false)}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md text-red-600 dark:text-red-400 border border-red-300 dark:border-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md text-status-failed border border-red-300 dark:border-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 disabled:opacity-50"
|
||||
>
|
||||
{isDeleting ? 'Deleting...' : confirmingDelete ? 'Confirm?' : 'Delete'}
|
||||
</button>
|
||||
@@ -193,14 +193,14 @@ export function PokemonFormModal({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md bg-accent-600 text-white hover:bg-accent-500 disabled:opacity-50"
|
||||
>
|
||||
{isSubmitting ? 'Saving...' : 'Save'}
|
||||
</button>
|
||||
@@ -212,11 +212,9 @@ export function PokemonFormModal({
|
||||
{activeTab === 'evolutions' && (
|
||||
<div className="flex flex-col min-h-0 flex-1">
|
||||
<div className="px-6 py-4 overflow-y-auto">
|
||||
{evolutionsLoading && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">Loading...</p>
|
||||
)}
|
||||
{evolutionsLoading && <p className="text-sm text-text-tertiary">Loading...</p>}
|
||||
{!evolutionsLoading && (!evolutionChain || evolutionChain.length === 0) && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">No evolutions</p>
|
||||
<p className="text-sm text-text-tertiary">No evolutions</p>
|
||||
)}
|
||||
{!evolutionsLoading && evolutionChain && evolutionChain.length > 0 && (
|
||||
<div className="space-y-1">
|
||||
@@ -225,22 +223,20 @@ export function PokemonFormModal({
|
||||
key={evo.id}
|
||||
type="button"
|
||||
onClick={() => setEditingEvolution(evo)}
|
||||
className="w-full text-left text-sm text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded px-2 py-1.5 -mx-2 transition-colors"
|
||||
className="w-full text-left text-sm text-text-tertiary hover:bg-surface-2 rounded px-2 py-1.5 -mx-2 transition-colors"
|
||||
>
|
||||
{evo.fromPokemon.name} → {evo.toPokemon.name}{' '}
|
||||
<span className="text-gray-400 dark:text-gray-500">
|
||||
({formatEvolutionMethod(evo)})
|
||||
</span>
|
||||
<span className="text-text-muted">({formatEvolutionMethod(evo)})</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end shrink-0">
|
||||
<div className="px-6 py-4 border-t border-border-default flex justify-end shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
@@ -252,32 +248,30 @@ export function PokemonFormModal({
|
||||
{activeTab === 'encounters' && (
|
||||
<div className="flex flex-col min-h-0 flex-1">
|
||||
<div className="px-6 py-4 overflow-y-auto">
|
||||
{encountersLoading && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">Loading...</p>
|
||||
)}
|
||||
{encountersLoading && <p className="text-sm text-text-tertiary">Loading...</p>}
|
||||
{!encountersLoading && (!encounterLocations || encounterLocations.length === 0) && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">No encounters</p>
|
||||
<p className="text-sm text-text-tertiary">No encounters</p>
|
||||
)}
|
||||
{!encountersLoading && encounterLocations && encounterLocations.length > 0 && (
|
||||
<div className="space-y-3">
|
||||
{encounterLocations.map((game) => (
|
||||
<div key={game.gameId}>
|
||||
<div className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
||||
<div className="text-sm font-medium text-text-secondary mb-1">
|
||||
{game.gameName}
|
||||
</div>
|
||||
<div className="space-y-0.5 pl-2">
|
||||
{game.encounters.map((enc, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1"
|
||||
className="text-sm text-text-tertiary flex items-center gap-1"
|
||||
>
|
||||
<Link
|
||||
to={`/admin/games/${game.gameId}/routes/${enc.routeId}`}
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline"
|
||||
className="text-text-link hover:underline"
|
||||
>
|
||||
{enc.routeName}
|
||||
</Link>
|
||||
<span className="text-gray-400 dark:text-gray-500">
|
||||
<span className="text-text-muted">
|
||||
— {enc.encounterMethod}, Lv. {enc.minLevel}–{enc.maxLevel}
|
||||
</span>
|
||||
</div>
|
||||
@@ -288,11 +282,11 @@ export function PokemonFormModal({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end shrink-0">
|
||||
<div className="px-6 py-4 border-t border-border-default flex justify-end shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
className="px-4 py-2 text-sm font-medium rounded-md border border-border-default hover:bg-surface-2"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
|
||||
@@ -44,11 +44,11 @@ export function PokemonSelector({
|
||||
}}
|
||||
onFocus={() => setOpen(true)}
|
||||
placeholder="Search pokemon..."
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
{selectedId && <input type="hidden" name={label} value={selectedId} required />}
|
||||
{open && pokemon.length > 0 && (
|
||||
<ul className="absolute z-10 mt-1 w-full bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-md shadow-lg max-h-48 overflow-y-auto">
|
||||
<ul className="absolute z-10 mt-1 w-full bg-surface-1 border border-border-default rounded-md shadow-lg max-h-48 overflow-y-auto">
|
||||
{pokemon.map((p) => (
|
||||
<li
|
||||
key={p.id}
|
||||
@@ -57,7 +57,7 @@ export function PokemonSelector({
|
||||
setSearch(p.name)
|
||||
setOpen(false)
|
||||
}}
|
||||
className={`px-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2 ${
|
||||
className={`px-3 py-2 cursor-pointer hover:bg-surface-2 text-sm flex items-center gap-2 ${
|
||||
p.id === selectedId ? 'bg-blue-50 dark:bg-blue-900/30' : ''
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -84,7 +84,7 @@ export function RouteEncounterFormModal({
|
||||
setSelectedMethod(e.target.value)
|
||||
if (e.target.value !== 'other') setCustomMethod('')
|
||||
}}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
>
|
||||
<option value="">Select method...</option>
|
||||
{METHOD_ORDER.map((m) => (
|
||||
@@ -108,7 +108,7 @@ export function RouteEncounterFormModal({
|
||||
value={customMethod}
|
||||
onChange={(e) => setCustomMethod(e.target.value)}
|
||||
placeholder="Custom method name"
|
||||
className="w-full mt-2 px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full mt-2 px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -121,7 +121,7 @@ export function RouteEncounterFormModal({
|
||||
max={100}
|
||||
value={encounterRate}
|
||||
onChange={(e) => setEncounterRate(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
@@ -134,7 +134,7 @@ export function RouteEncounterFormModal({
|
||||
max={100}
|
||||
value={minLevel}
|
||||
onChange={(e) => setMinLevel(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -146,7 +146,7 @@ export function RouteEncounterFormModal({
|
||||
max={100}
|
||||
value={maxLevel}
|
||||
onChange={(e) => setMaxLevel(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@ export function RouteFormModal({
|
||||
isDeleting={isDeleting}
|
||||
headerExtra={
|
||||
detailUrl ? (
|
||||
<Link to={detailUrl} className="text-sm text-blue-600 dark:text-blue-400 hover:underline">
|
||||
<Link to={detailUrl} className="text-sm text-text-link hover:underline">
|
||||
View Encounters
|
||||
</Link>
|
||||
) : undefined
|
||||
@@ -62,7 +62,7 @@ export function RouteFormModal({
|
||||
required
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -73,7 +73,7 @@ export function RouteFormModal({
|
||||
min={0}
|
||||
value={order}
|
||||
onChange={(e) => setOrder(e.target.value)}
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -84,9 +84,9 @@ export function RouteFormModal({
|
||||
value={pinwheelZone}
|
||||
onChange={(e) => setPinwheelZone(e.target.value)}
|
||||
placeholder="None"
|
||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||
className="w-full px-3 py-2 border rounded-md bg-surface-2 border-border-default"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||
<p className="text-xs text-text-tertiary mt-1">
|
||||
Routes in the same zone share an encounter when the Pinwheel Clause is active
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user