feat(ui): redesign mappings page with design tokens and refined table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 00:11:40 -05:00
parent 8461bf788c
commit 400e74be51

View File

@@ -1,5 +1,5 @@
import { useState } from 'react' import { useState } from 'react'
import { Pencil, Trash2, Check, X, Plus } from 'lucide-react' import { Pencil, Trash2, Check, X, Plus, Link } from 'lucide-react'
import { useMappings, useCreateMapping, useUpdateMapping, useDeleteMapping } from '../api/mappings' import { useMappings, useCreateMapping, useUpdateMapping, useDeleteMapping } from '../api/mappings'
import { CATEGORY_COLORS } from '../lib/constants' import { CATEGORY_COLORS } from '../lib/constants'
import type { AppMapping } from '../types' import type { AppMapping } from '../types'
@@ -102,13 +102,13 @@ export default function Mappings() {
} }
const inputClass = const inputClass =
'bg-[#0f1117] text-white text-sm rounded border border-white/10 px-2 py-1.5 focus:outline-none focus:border-indigo-500 transition-colors w-full' 'bg-[var(--color-page)] text-[var(--color-text-primary)] text-sm rounded border border-[var(--color-border)] px-2 py-1.5 focus:outline-none focus:border-[var(--color-accent)] transition-colors w-full'
const selectClass = const selectClass =
'bg-[#0f1117] text-white text-sm rounded border border-white/10 px-2 py-1.5 focus:outline-none focus:border-indigo-500 transition-colors appearance-none cursor-pointer w-full' 'bg-[var(--color-page)] text-[var(--color-text-primary)] text-sm rounded border border-[var(--color-border)] px-2 py-1.5 focus:outline-none focus:border-[var(--color-accent)] transition-colors appearance-none cursor-pointer w-full'
function renderFormRow(form: FormData, setForm: (f: FormData) => void, onSave: () => void, onCancel: () => void, isSaving: boolean) { function renderFormRow(form: FormData, setForm: (f: FormData) => void, onSave: () => void, onCancel: () => void, isSaving: boolean) {
return ( return (
<tr className="bg-[#1a1d27]"> <tr className="bg-white/[0.04]">
<td className="px-4 py-3"> <td className="px-4 py-3">
<input <input
type="text" type="text"
@@ -162,7 +162,7 @@ export default function Mappings() {
</button> </button>
<button <button
onClick={onCancel} onClick={onCancel}
className="p-1.5 rounded text-[#94a3b8] hover:bg-white/5 transition-colors" className="p-1.5 rounded text-[var(--color-text-secondary)] hover:bg-white/5 transition-colors"
title="Cancel" title="Cancel"
> >
<X size={16} /> <X size={16} />
@@ -177,7 +177,7 @@ export default function Mappings() {
<div className="max-w-6xl mx-auto space-y-6"> <div className="max-w-6xl mx-auto space-y-6">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h1 className="text-xl font-semibold text-white">App Mappings</h1> <h1 className="text-xl font-semibold text-[var(--color-text-primary)]">App Mappings</h1>
<button <button
onClick={() => { onClick={() => {
setAddingNew(true) setAddingNew(true)
@@ -185,7 +185,7 @@ export default function Mappings() {
setNewForm(emptyForm) setNewForm(emptyForm)
}} }}
disabled={addingNew} disabled={addingNew}
className="flex items-center gap-1.5 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-sm font-medium px-3 py-1.5 rounded-lg transition-colors" className="flex items-center gap-1.5 bg-gradient-to-r from-[var(--color-accent)] to-[var(--color-accent-end)] hover:brightness-110 disabled:opacity-50 text-white text-sm font-medium px-3 py-1.5 rounded-lg transition-all"
> >
<Plus size={16} /> <Plus size={16} />
Add Rule Add Rule
@@ -194,33 +194,34 @@ export default function Mappings() {
{/* Table */} {/* Table */}
{isLoading ? ( {isLoading ? (
<div className="text-[#94a3b8] text-sm py-12 text-center">Loading mappings...</div> <div className="text-[var(--color-text-secondary)] text-sm py-12 text-center">Loading mappings...</div>
) : !mappings?.length && !addingNew ? ( ) : !mappings?.length && !addingNew ? (
<div className="bg-[#161922] rounded-xl border border-white/5 p-12 text-center"> <div className="bg-[var(--color-surface)] rounded-xl border border-[var(--color-border)] p-12 text-center">
<p className="text-[#94a3b8] text-sm mb-3">No mappings configured</p> <Link size={40} className="text-[var(--color-text-tertiary)] mx-auto mb-3" />
<p className="text-[var(--color-text-secondary)] text-sm mb-3">No mappings configured</p>
<button <button
onClick={() => { onClick={() => {
setAddingNew(true) setAddingNew(true)
setNewForm(emptyForm) setNewForm(emptyForm)
}} }}
className="text-indigo-400 hover:text-indigo-300 text-sm font-medium transition-colors" className="text-[var(--color-accent)] hover:brightness-110 text-sm font-medium transition-all"
> >
+ Add your first mapping rule + Add your first mapping rule
</button> </button>
</div> </div>
) : ( ) : (
<div className="bg-[#161922] rounded-xl border border-white/5 overflow-hidden"> <div className="bg-[var(--color-surface)] rounded-xl border border-[var(--color-border)] overflow-hidden">
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="bg-[#161922] border-b border-white/5"> <tr className="bg-[var(--color-surface)] border-b border-[var(--color-border)]">
<th className="text-left px-4 py-3 text-[#94a3b8] font-medium">Pattern</th> <th className="text-left px-4 py-3 text-[10px] uppercase tracking-wider text-[var(--color-text-tertiary)] font-medium">Pattern</th>
<th className="text-left px-4 py-3 text-[#94a3b8] font-medium">Match Type</th> <th className="text-left px-4 py-3 text-[10px] uppercase tracking-wider text-[var(--color-text-tertiary)] font-medium">Match Type</th>
<th className="text-left px-4 py-3 text-[#94a3b8] font-medium">Category</th> <th className="text-left px-4 py-3 text-[10px] uppercase tracking-wider text-[var(--color-text-tertiary)] font-medium">Category</th>
<th className="text-left px-4 py-3 text-[#94a3b8] font-medium">Friendly Name</th> <th className="text-left px-4 py-3 text-[10px] uppercase tracking-wider text-[var(--color-text-tertiary)] font-medium">Friendly Name</th>
<th className="text-left px-4 py-3 text-[#94a3b8] font-medium w-24">Actions</th> <th className="text-left px-4 py-3 text-[10px] uppercase tracking-wider text-[var(--color-text-tertiary)] font-medium w-24">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody className="divide-y divide-white/5"> <tbody>
{/* Add-new row */} {/* Add-new row */}
{addingNew && {addingNew &&
renderFormRow(newForm, setNewForm, handleAddSave, handleAddCancel, createMapping.isPending)} renderFormRow(newForm, setNewForm, handleAddSave, handleAddCancel, createMapping.isPending)}
@@ -232,9 +233,9 @@ export default function Mappings() {
) : ( ) : (
<tr <tr
key={m.id} key={m.id}
className="bg-[#1a1d27] hover:bg-[#1e2230] transition-colors" className="border-b border-[var(--color-border)] hover:bg-white/[0.03] transition-colors"
> >
<td className="px-4 py-3 text-white font-mono text-xs">{m.pattern}</td> <td className="px-4 py-3 text-[var(--color-text-primary)] font-mono text-xs">{m.pattern}</td>
<td className="px-4 py-3"> <td className="px-4 py-3">
<span <span
className="inline-block text-xs font-medium px-2 py-0.5 rounded-full" className="inline-block text-xs font-medium px-2 py-0.5 rounded-full"
@@ -247,7 +248,7 @@ export default function Mappings() {
</span> </span>
</td> </td>
<td className="px-4 py-3"> <td className="px-4 py-3">
<span className="inline-flex items-center gap-1.5 text-white text-xs"> <span className="inline-flex items-center gap-1.5 text-[var(--color-text-primary)] text-xs">
<span <span
className="w-2 h-2 rounded-full flex-shrink-0" className="w-2 h-2 rounded-full flex-shrink-0"
style={{ backgroundColor: CATEGORY_COLORS[m.category] ?? '#64748b' }} style={{ backgroundColor: CATEGORY_COLORS[m.category] ?? '#64748b' }}
@@ -255,21 +256,21 @@ export default function Mappings() {
{m.category} {m.category}
</span> </span>
</td> </td>
<td className="px-4 py-3 text-[#94a3b8]"> <td className="px-4 py-3 text-[var(--color-text-secondary)]">
{m.friendlyName ?? '\u2014'} {m.friendlyName ?? '\u2014'}
</td> </td>
<td className="px-4 py-3"> <td className="px-4 py-3">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<button <button
onClick={() => handleEditStart(m)} onClick={() => handleEditStart(m)}
className="p-1.5 rounded text-[#94a3b8] hover:text-white hover:bg-white/5 transition-colors" className="p-1.5 rounded text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-white/5 transition-colors"
title="Edit" title="Edit"
> >
<Pencil size={14} /> <Pencil size={14} />
</button> </button>
<button <button
onClick={() => handleDelete(m.id)} onClick={() => handleDelete(m.id)}
className="p-1.5 rounded text-[#94a3b8] hover:text-rose-400 hover:bg-rose-400/10 transition-colors" className="p-1.5 rounded text-[var(--color-text-secondary)] hover:text-rose-400 hover:bg-rose-400/10 transition-colors"
title="Delete" title="Delete"
> >
<Trash2 size={14} /> <Trash2 size={14} />