Improve experiment form UI - make it more compact

- Reduced modal max-width and padding
- Changed from buttons to select dropdowns for Type/Marketplace
- Smaller text sizes and spacing throughout
- Shorter placeholder texts
- More compact ASIN tags with max-height scroll
- Reduced textarea rows
- Smaller button labels

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Christian Vidal Wolf
2026-02-21 00:31:26 +01:00
co-authored by Qwen-Coder
parent aebebecf1b
commit 9736a3d591
+67 -81
View File
@@ -89,87 +89,73 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
return ( return (
<div className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center p-4"> <div className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="bg-slate-900 border border-slate-700 rounded-2xl w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col"> <div className="bg-slate-900 border border-slate-700 rounded-2xl w-full max-w-3xl max-h-[85vh] overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between p-6 border-b border-slate-700"> <div className="flex items-center justify-between p-4 border-b border-slate-700">
<h2 className="text-xl font-bold text-white">🧪 Create New Experiment</h2> <h2 className="text-lg font-bold text-white">🧪 New Experiment</h2>
<button <button
onClick={onClose} onClick={onClose}
className="p-2 text-slate-400 hover:text-white hover:bg-slate-800 rounded-lg transition-colors" className="p-1.5 text-slate-400 hover:text-white hover:bg-slate-800 rounded-lg transition-colors"
> >
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor"> <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" /> <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg> </svg>
</button> </button>
</div> </div>
{/* Form */} {/* Form */}
<form onSubmit={handleSubmit} className="flex-1 overflow-y-auto p-6 space-y-6"> <form onSubmit={handleSubmit} className="flex-1 overflow-y-auto p-4 space-y-4">
{/* Name */} {/* Name */}
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Experiment Name <span className="text-red-400">*</span> Name <span className="text-red-400">*</span>
</label> </label>
<input <input
type="text" type="text"
value={formData.name} value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })} onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
placeholder="e.g., Q1 Price Reduction Test" placeholder="e.g., Q1 Price Reduction Test"
required required
/> />
</div> </div>
{/* Type */} {/* Type & Marketplace */}
<div> <div className="grid grid-cols-2 gap-4">
<label className="block text-sm font-medium text-slate-300 mb-2"> <div>
Experiment Type <span className="text-red-400">*</span> <label className="block text-xs font-medium text-slate-300 mb-1">
</label> Type <span className="text-red-400">*</span>
<div className="grid grid-cols-2 gap-2"> </label>
{typeOptions.map((opt) => ( <select
<button value={formData.type}
key={opt.value} onChange={(e) => setFormData({ ...formData, type: e.target.value as ExperimentType })}
type="button" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
onClick={() => setFormData({ ...formData, type: opt.value })} >
className={`p-3 rounded-lg border text-sm font-medium transition-colors flex items-center gap-2 ${ <option value="pricing">💰 Pricing</option>
formData.type === opt.value <option value="advertising">📢 Advertising</option>
? 'bg-indigo-600/20 border-indigo-500 text-indigo-400' <option value="content">📝 Content</option>
: 'bg-slate-800 border-slate-600 text-slate-400 hover:border-slate-500' <option value="promotion">🏷 Promotion</option>
}`} </select>
>
<span className="text-lg">{opt.icon}</span>
{opt.label}
</button>
))}
</div> </div>
</div> <div>
<label className="block text-xs font-medium text-slate-300 mb-1">
{/* Marketplace */} Marketplace <span className="text-red-400">*</span>
<div> </label>
<label className="block text-sm font-medium text-slate-300 mb-2"> <select
Marketplace <span className="text-red-400">*</span> value={formData.marketplace}
</label> onChange={(e) => setFormData({ ...formData, marketplace: e.target.value })}
<div className="flex gap-2"> className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
{marketplaceOptions.map((mp) => ( >
<button {marketplaceOptions.map((mp) => (
key={mp} <option key={mp} value={mp}>{mp}</option>
type="button" ))}
onClick={() => setFormData({ ...formData, marketplace: mp })} </select>
className={`px-4 py-2 rounded-lg border text-sm font-medium transition-colors ${
formData.marketplace === mp
? 'bg-indigo-600/20 border-indigo-500 text-indigo-400'
: 'bg-slate-800 border-slate-600 text-slate-400 hover:border-slate-500'
}`}
>
{mp}
</button>
))}
</div> </div>
</div> </div>
{/* ASINs */} {/* ASINs */}
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Target ASINs <span className="text-red-400">*</span> Target ASINs <span className="text-red-400">*</span>
</label> </label>
<div className="flex gap-2 mb-2"> <div className="flex gap-2 mb-2">
@@ -178,23 +164,23 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
value={asinInput} value={asinInput}
onChange={(e) => setAsinInput(e.target.value)} onChange={(e) => setAsinInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), handleAddAsin())} onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), handleAddAsin())}
className="flex-1 bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" className="flex-1 bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
placeholder="Enter ASINs (comma-separated)" placeholder="ASINs (comma-separated)"
/> />
<button <button
type="button" type="button"
onClick={handleAddAsin} onClick={handleAddAsin}
className="px-4 py-2 bg-slate-700 hover:bg-slate-600 text-white rounded-lg transition-colors" className="px-3 py-1.5 bg-slate-700 hover:bg-slate-600 text-white rounded-lg text-sm transition-colors"
> >
Add Add
</button> </button>
</div> </div>
{formData.asins.length > 0 && ( {formData.asins.length > 0 && (
<div className="flex flex-wrap gap-2 p-3 bg-slate-800/50 border border-slate-700 rounded-lg"> <div className="flex flex-wrap gap-1.5 p-2 bg-slate-800/50 border border-slate-700 rounded-lg max-h-20 overflow-y-auto">
{formData.asins.map((asin) => ( {formData.asins.map((asin) => (
<span <span
key={asin} key={asin}
className="inline-flex items-center gap-1 px-2.5 py-1 bg-slate-700 border border-slate-600 rounded-lg text-sm text-slate-300 font-mono" className="inline-flex items-center gap-1 px-2 py-1 bg-slate-700 border border-slate-600 rounded text-xs text-slate-300 font-mono"
> >
{asin} {asin}
<button <button
@@ -202,7 +188,7 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
onClick={() => handleRemoveAsin(asin)} onClick={() => handleRemoveAsin(asin)}
className="text-slate-400 hover:text-red-400 transition-colors" className="text-slate-400 hover:text-red-400 transition-colors"
> >
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor"> <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" /> <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg> </svg>
</button> </button>
@@ -215,54 +201,54 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
{/* Timeline */} {/* Timeline */}
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Start Date <span className="text-red-400">*</span> Start Date <span className="text-red-400">*</span>
</label> </label>
<input <input
type="date" type="date"
value={formData.start_date} value={formData.start_date}
onChange={(e) => setFormData({ ...formData, start_date: e.target.value })} onChange={(e) => setFormData({ ...formData, start_date: e.target.value })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-2 py-1.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
required required
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
End Date End Date
</label> </label>
<input <input
type="date" type="date"
value={formData.end_date} value={formData.end_date}
onChange={(e) => setFormData({ ...formData, end_date: e.target.value })} onChange={(e) => setFormData({ ...formData, end_date: e.target.value })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-2 py-1.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
/> />
</div> </div>
</div> </div>
{/* Hypothesis */} {/* Hypothesis */}
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Hypothesis Hypothesis
</label> </label>
<textarea <textarea
value={formData.hypothesis} value={formData.hypothesis}
onChange={(e) => setFormData({ ...formData, hypothesis: e.target.value })} onChange={(e) => setFormData({ ...formData, hypothesis: e.target.value })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 resize-none"
rows={3} rows={2}
placeholder="What do you expect to happen? e.g., 'Reducing price by 10% will increase units sold by 25%'" placeholder="What do you expect to happen?"
/> />
</div> </div>
{/* Primary Metric & Target Lift */} {/* Metric & Target */}
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Primary Metric Primary Metric
</label> </label>
<select <select
value={formData.primary_metric} value={formData.primary_metric}
onChange={(e) => setFormData({ ...formData, primary_metric: e.target.value as ExperimentMetric })} onChange={(e) => setFormData({ ...formData, primary_metric: e.target.value as ExperimentMetric })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-2 py-1.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
> >
{metricOptions.map((opt) => ( {metricOptions.map((opt) => (
<option key={opt.value} value={opt.value}>{opt.label}</option> <option key={opt.value} value={opt.value}>{opt.label}</option>
@@ -270,14 +256,14 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Target Lift (%) Target Lift (%)
</label> </label>
<input <input
type="number" type="number"
value={formData.target_lift_percent} value={formData.target_lift_percent}
onChange={(e) => setFormData({ ...formData, target_lift_percent: parseFloat(e.target.value) || 0 })} onChange={(e) => setFormData({ ...formData, target_lift_percent: parseFloat(e.target.value) || 0 })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-2 py-1.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
min="0" min="0"
max="1000" max="1000"
/> />
@@ -286,29 +272,29 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
{/* Owner */} {/* Owner */}
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Owner Owner
</label> </label>
<input <input
type="text" type="text"
value={formData.owner} value={formData.owner}
onChange={(e) => setFormData({ ...formData, owner: e.target.value })} onChange={(e) => setFormData({ ...formData, owner: e.target.value })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
placeholder="Your name" placeholder="Your name"
/> />
</div> </div>
{/* Description */} {/* Description */}
<div> <div>
<label className="block text-sm font-medium text-slate-300 mb-2"> <label className="block text-xs font-medium text-slate-300 mb-1">
Description Description
</label> </label>
<textarea <textarea
value={formData.description} value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })} onChange={(e) => setFormData({ ...formData, description: e.target.value })}
className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-1.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 resize-none"
rows={3} rows={2}
placeholder="Additional details about this experiment..." placeholder="Additional details..."
/> />
</div> </div>
@@ -317,16 +303,16 @@ const ExperimentForm: React.FC<ExperimentFormProps> = ({
<button <button
type="button" type="button"
onClick={onClose} onClick={onClose}
className="flex-1 px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-white rounded-lg font-medium transition-colors" className="flex-1 px-4 py-2 bg-slate-800 hover:bg-slate-700 text-white rounded-lg text-sm font-medium transition-colors"
> >
Cancel Cancel
</button> </button>
<button <button
type="submit" type="submit"
disabled={loading} disabled={loading}
className="flex-1 px-4 py-2.5 bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-600/50 text-white rounded-lg font-medium transition-colors" className="flex-1 px-4 py-2 bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-600/50 text-white rounded-lg text-sm font-medium transition-colors"
> >
{loading ? 'Creating...' : 'Create Experiment'} {loading ? 'Creating...' : 'Create'}
</button> </button>
</div> </div>
</form> </form>