style(ui): remove placeholder text from all input fields

Strips example/hint placeholder attributes across all components for a cleaner, less cluttered form UX.
This commit is contained in:
Brückner
2026-06-10 16:25:28 +02:00
parent d78ade4629
commit c3931e7f36
9 changed files with 13 additions and 54 deletions

View File

@ -679,7 +679,6 @@ export default function BookingCalendar({
<textarea <textarea
required required
rows={3} rows={3}
placeholder="e.g. Validating STP failover convergence times..."
value={bookingNotes} value={bookingNotes}
onChange={(e) => setBookingNotes(e.target.value)} onChange={(e) => setBookingNotes(e.target.value)}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-indigo-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-indigo-500"

View File

@ -255,7 +255,6 @@ export default function DeviceInventory({
</span> </span>
<input <input
type="text" type="text"
placeholder="Search by hostname, IP address, rack location..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded-lg pl-9 pr-4 py-1.5 text-xs focus:outline-none focus:border-emerald-500 transition-colors placeholder:text-slate-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded-lg pl-9 pr-4 py-1.5 text-xs focus:outline-none focus:border-emerald-500 transition-colors placeholder:text-slate-500"
@ -497,7 +496,6 @@ Pick a box from the list to see its specs and break-glass playbook.
value={formData.hostname} value={formData.hostname}
onChange={(e) => setFormData({ ...formData, hostname: e.target.value })} onChange={(e) => setFormData({ ...formData, hostname: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500 font-mono" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500 font-mono"
placeholder="SW-CORE-03"
/> />
</div> </div>
<div> <div>
@ -508,7 +506,6 @@ Pick a box from the list to see its specs and break-glass playbook.
value={formData.ip} value={formData.ip}
onChange={(e) => setFormData({ ...formData, ip: e.target.value })} onChange={(e) => setFormData({ ...formData, ip: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500 font-mono" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500 font-mono"
placeholder="172.16.x.x"
/> />
</div> </div>
</div> </div>
@ -522,7 +519,6 @@ Pick a box from the list to see its specs and break-glass playbook.
value={formData.location} value={formData.location}
onChange={(e) => setFormData({ ...formData, location: e.target.value })} onChange={(e) => setFormData({ ...formData, location: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="Server Room R02, Rack C4..."
/> />
</div> </div>
<div> <div>
@ -554,7 +550,6 @@ Pick a box from the list to see its specs and break-glass playbook.
value={formData.type} value={formData.type}
onChange={(e) => setFormData({ ...formData, type: e.target.value as DeviceType })} onChange={(e) => setFormData({ ...formData, type: e.target.value as DeviceType })}
className="w-full mt-2 bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full mt-2 bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="Enter new device class (e.g. Router, Load-Balancer)"
/> />
)} )}
</div> </div>
@ -567,7 +562,6 @@ Pick a box from the list to see its specs and break-glass playbook.
value={formData.notes} value={formData.notes}
onChange={(e) => setFormData({ ...formData, notes: e.target.value })} onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="Serial numbers, module slots, connected uplinks, license status..."
/> />
</div> </div>

View File

@ -401,7 +401,6 @@ export default function LabTemplates({
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-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="e.g. Campus Core OSPF Backup Route"
/> />
</div> </div>
<div> <div>
@ -412,7 +411,6 @@ export default function LabTemplates({
value={formData.location} value={formData.location}
onChange={(e) => setFormData({ ...formData, location: e.target.value })} onChange={(e) => setFormData({ ...formData, location: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="e.g. Server Room R01, Cabinet B"
/> />
</div> </div>
</div> </div>
@ -427,7 +425,6 @@ export default function LabTemplates({
value={formData.contactPerson} value={formData.contactPerson}
onChange={(e) => setFormData({ ...formData, contactPerson: e.target.value })} onChange={(e) => setFormData({ ...formData, contactPerson: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="e.g. Jane Doe"
/> />
</div> </div>
<div> <div>
@ -438,7 +435,6 @@ export default function LabTemplates({
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-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-500"
placeholder="Purpose, VLAN mappings, target device models..."
/> />
</div> </div>
</div> </div>
@ -541,7 +537,6 @@ export default function LabTemplates({
<input <input
type="text" type="text"
className="w-full bg-slate-950 text-slate-250 border border-slate-805 p-1 rounded font-mono text-[11px]" className="w-full bg-slate-950 text-slate-250 border border-slate-805 p-1 rounded font-mono text-[11px]"
placeholder="e.g. LACP Port-Channel 1"
value={linkType} value={linkType}
onChange={(e) => setLinkType(e.target.value)} onChange={(e) => setLinkType(e.target.value)}
/> />
@ -634,7 +629,6 @@ export default function LabTemplates({
value={formData.semaphoreSetupTemplateId} value={formData.semaphoreSetupTemplateId}
onChange={(e) => setFormData({ ...formData, semaphoreSetupTemplateId: e.target.value })} onChange={(e) => setFormData({ ...formData, semaphoreSetupTemplateId: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 font-mono text-xs focus:outline-none focus:border-orange-500/60" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 font-mono text-xs focus:outline-none focus:border-orange-500/60"
placeholder="e.g. 3"
/> />
</div> </div>
<div> <div>
@ -645,7 +639,6 @@ export default function LabTemplates({
value={formData.semaphoreTeardownTemplateId} value={formData.semaphoreTeardownTemplateId}
onChange={(e) => setFormData({ ...formData, semaphoreTeardownTemplateId: e.target.value })} onChange={(e) => setFormData({ ...formData, semaphoreTeardownTemplateId: e.target.value })}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 font-mono text-xs focus:outline-none focus:border-orange-500/60" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 font-mono text-xs focus:outline-none focus:border-orange-500/60"
placeholder="e.g. 4"
/> />
</div> </div>
</div> </div>
@ -664,7 +657,7 @@ export default function LabTemplates({
type="submit" type="submit"
className="px-4 py-2 bg-emerald-600 hover:bg-emerald-500 text-slate-950 font-bold rounded text-xs animate-none" className="px-4 py-2 bg-emerald-600 hover:bg-emerald-500 text-slate-950 font-bold rounded text-xs animate-none"
> >
Save Lab Template Save
</button> </button>
</div> </div>

View File

@ -168,7 +168,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
<span className="absolute left-3 top-2.5 text-slate-550"><Search className="w-4 h-4" /></span> <span className="absolute left-3 top-2.5 text-slate-550"><Search className="w-4 h-4" /></span>
<input <input
type="text" type="text"
placeholder="Search links by name, host, category…"
value={search} value={search}
onChange={(e) => setSearch(e.target.value)} onChange={(e) => setSearch(e.target.value)}
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded-lg pl-9 pr-4 py-1.5 text-xs focus:outline-none focus:border-emerald-600" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded-lg pl-9 pr-4 py-1.5 text-xs focus:outline-none focus:border-emerald-600"
@ -263,7 +262,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
if (e.key === 'Escape') { setEditingDescId(null); } if (e.key === 'Escape') { setEditingDescId(null); }
}} }}
className="w-full mt-3 bg-slate-950 text-slate-200 text-[11px] border border-emerald-600 rounded px-2 py-1 resize-none focus:outline-none leading-relaxed" className="w-full mt-3 bg-slate-950 text-slate-200 text-[11px] border border-emerald-600 rounded px-2 py-1 resize-none focus:outline-none leading-relaxed"
placeholder="Add a description"
/> />
) : ( ) : (
<p <p
@ -325,7 +323,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
required autoFocus required autoFocus
value={draft.title} value={draft.title}
onChange={(e) => setDraft({ ...draft, title: e.target.value })} onChange={(e) => setDraft({ ...draft, title: e.target.value })}
placeholder="e.g. CheckMK Monitoring"
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600"
/> />
</div> </div>
@ -336,7 +333,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
required required
value={draft.url} value={draft.url}
onChange={(e) => setDraft({ ...draft, url: e.target.value })} onChange={(e) => setDraft({ ...draft, url: e.target.value })}
placeholder="https://checkmk.internal"
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600 font-mono" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600 font-mono"
/> />
</div> </div>
@ -347,7 +343,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
list="link-categories" list="link-categories"
value={draft.category} value={draft.category}
onChange={(e) => setDraft({ ...draft, category: e.target.value })} onChange={(e) => setDraft({ ...draft, category: e.target.value })}
placeholder="e.g. Monitoring, Automation, Docs"
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600"
/> />
<datalist id="link-categories"> <datalist id="link-categories">
@ -361,7 +356,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
rows={2} rows={2}
value={draft.description} value={draft.description}
onChange={(e) => setDraft({ ...draft, description: e.target.value })} onChange={(e) => setDraft({ ...draft, description: e.target.value })}
placeholder="What is this tool for?"
className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600 resize-none" className="w-full bg-slate-950 text-slate-100 border border-slate-800 rounded p-2 focus:outline-none focus:border-emerald-600 resize-none"
/> />
</div> </div>

View File

@ -117,7 +117,6 @@ export default function Logbook({ logs, devices, users, currentUser, onAddLog }:
</span> </span>
<input <input
type="text" type="text"
placeholder="Filter audit log entries..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
className="w-full bg-slate-950 text-slate-101 border border-slate-800 rounded-lg pl-9 pr-4 py-1.5 text-xs focus:outline-none" className="w-full bg-slate-950 text-slate-101 border border-slate-800 rounded-lg pl-9 pr-4 py-1.5 text-xs focus:outline-none"
@ -239,7 +238,6 @@ export default function Logbook({ logs, devices, users, currentUser, onAddLog }:
value={logMessage} value={logMessage}
onChange={(e) => setLogMessage(e.target.value)} onChange={(e) => setLogMessage(e.target.value)}
className="w-full bg-slate-950 text-slate-200 border border-slate-800 rounded p-2 focus:outline-none" className="w-full bg-slate-950 text-slate-200 border border-slate-800 rounded p-2 focus:outline-none"
placeholder="Describe SFP fiber replacements, port trunking alterations, routing table diagnostic evaluations..."
/> />
</div> </div>

View File

@ -102,7 +102,6 @@ export default function LoginPage({ onLogin, onNavigateToRegister, authError }:
value={email} value={email}
onChange={e => setEmail(e.target.value)} onChange={e => setEmail(e.target.value)}
className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all" className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
placeholder=""
/> />
</div> </div>
@ -119,7 +118,6 @@ export default function LoginPage({ onLogin, onNavigateToRegister, authError }:
value={password} value={password}
onChange={e => setPassword(e.target.value)} onChange={e => setPassword(e.target.value)}
className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 pr-10 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all" className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 pr-10 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
placeholder=""
/> />
<button <button
type="button" type="button"

View File

@ -106,7 +106,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
value={name} value={name}
onChange={e => setName(e.target.value)} onChange={e => setName(e.target.value)}
className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all" className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
placeholder="Max Mustermann"
/> />
</div> </div>
@ -122,7 +121,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
value={email} value={email}
onChange={e => setEmail(e.target.value)} onChange={e => setEmail(e.target.value)}
className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all" className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
placeholder="you@example.com"
/> />
</div> </div>
@ -139,7 +137,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
value={password} value={password}
onChange={e => setPassword(e.target.value)} onChange={e => setPassword(e.target.value)}
className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 pr-10 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all" className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2.5 pr-10 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
placeholder="Min. 8 characters"
/> />
<button <button
type="button" type="button"
@ -174,7 +171,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
? 'border-red-700 focus:ring-red-500/50' ? 'border-red-700 focus:ring-red-500/50'
: 'border-slate-700 focus:ring-cyan-500/50 focus:border-cyan-500/50' : 'border-slate-700 focus:ring-cyan-500/50 focus:border-cyan-500/50'
}`} }`}
placeholder="Repeat password"
/> />
</div> </div>

View File

@ -109,10 +109,9 @@ function Input({ value, onChange, placeholder, monospace, icon }: {
); );
} }
function SecretInput({ value, onChange, alreadySet, show, onToggleShow }: { function SecretInput({ value, onChange, show, onToggleShow }: {
value: string; value: string;
onChange: (v: string) => void; onChange: (v: string) => void;
alreadySet: boolean;
show: boolean; show: boolean;
onToggleShow: () => void; onToggleShow: () => void;
}) { }) {
@ -125,7 +124,6 @@ function SecretInput({ value, onChange, alreadySet, show, onToggleShow }: {
type={show ? 'text' : 'password'} type={show ? 'text' : 'password'}
value={value} value={value}
onChange={e => onChange(e.target.value)} onChange={e => onChange(e.target.value)}
placeholder={alreadySet ? '•••••••• (leave blank to keep)' : 'Secret'}
className="w-full bg-slate-900 border border-slate-700 rounded-lg pl-9 pr-10 py-2.5 text-xs font-mono text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all" className="w-full bg-slate-900 border border-slate-700 rounded-lg pl-9 pr-10 py-2.5 text-xs font-mono text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
/> />
<button <button
@ -175,7 +173,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
const [checkmkEnabled, setCheckmkEnabled] = useState(false); const [checkmkEnabled, setCheckmkEnabled] = useState(false);
const [checkmkApiUrl, setCheckmkApiUrl] = useState(''); const [checkmkApiUrl, setCheckmkApiUrl] = useState('');
const [checkmkApiUser, setCheckmkApiUser] = useState('automation'); const [checkmkApiUser, setCheckmkApiUser] = useState('');
const [checkmkApiSecret, setCheckmkApiSecret] = useState(''); const [checkmkApiSecret, setCheckmkApiSecret] = useState('');
const [checkmkSecretSet, setCheckmkSecretSet] = useState(false); const [checkmkSecretSet, setCheckmkSecretSet] = useState(false);
const [checkmkSyncInterval, setCheckmkSyncInterval] = useState('60000'); const [checkmkSyncInterval, setCheckmkSyncInterval] = useState('60000');
@ -255,7 +253,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
setAzureAllowedGroup(data.azure_allowed_group || ''); setAzureAllowedGroup(data.azure_allowed_group || '');
setCheckmkEnabled(data.checkmk_enabled === 'true'); setCheckmkEnabled(data.checkmk_enabled === 'true');
setCheckmkApiUrl(data.checkmk_api_url || ''); setCheckmkApiUrl(data.checkmk_api_url || '');
setCheckmkApiUser(data.checkmk_api_user || 'automation'); setCheckmkApiUser(data.checkmk_api_user || '');
setCheckmkSecretSet(data.checkmk_api_secret === SECRET_SENTINEL); setCheckmkSecretSet(data.checkmk_api_secret === SECRET_SENTINEL);
setCheckmkApiSecret(''); setCheckmkApiSecret('');
setCheckmkSyncInterval(data.checkmk_sync_interval_ms || '60000'); setCheckmkSyncInterval(data.checkmk_sync_interval_ms || '60000');
@ -634,10 +632,10 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<div className={`grid grid-cols-1 sm:grid-cols-2 gap-5 transition-opacity duration-200 ${!azureEnabled ? 'opacity-40 pointer-events-none' : ''}`}> <div className={`grid grid-cols-1 sm:grid-cols-2 gap-5 transition-opacity duration-200 ${!azureEnabled ? 'opacity-40 pointer-events-none' : ''}`}>
<FieldRow label="Tenant ID" hint="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"> <FieldRow label="Tenant ID" hint="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
<Input value={azureTenantId} onChange={setAzureTenantId} placeholder="Tenant ID" monospace /> <Input value={azureTenantId} onChange={setAzureTenantId} monospace />
</FieldRow> </FieldRow>
<FieldRow label="Client ID (Application ID)" hint="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"> <FieldRow label="Client ID (Application ID)" hint="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
<Input value={azureClientId} onChange={setAzureClientId} placeholder="Client ID" monospace /> <Input value={azureClientId} onChange={setAzureClientId} monospace />
</FieldRow> </FieldRow>
<FieldRow <FieldRow
label="Client Secret" label="Client Secret"
@ -646,7 +644,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<SecretInput <SecretInput
value={azureClientSecret} value={azureClientSecret}
onChange={setAzureClientSecret} onChange={setAzureClientSecret}
alreadySet={azureSecretSet}
show={showAzureSecret} show={showAzureSecret}
onToggleShow={() => setShowAzureSecret(v => !v)} onToggleShow={() => setShowAzureSecret(v => !v)}
/> />
@ -659,7 +656,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={azureRedirectUri} value={azureRedirectUri}
onChange={setAzureRedirectUri} onChange={setAzureRedirectUri}
placeholder={effectiveRedirectUri || 'https://…/api/auth/azure/callback'}
monospace monospace
/> />
</FieldRow> </FieldRow>
@ -671,7 +667,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={azureAllowedGroup} value={azureAllowedGroup}
onChange={setAzureAllowedGroup} onChange={setAzureAllowedGroup}
placeholder="Leave blank to allow all tenant users"
monospace monospace
icon={<Users className="w-3.5 h-3.5" />} icon={<Users className="w-3.5 h-3.5" />}
/> />
@ -742,7 +737,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={checkmkApiUrl} value={checkmkApiUrl}
onChange={setCheckmkApiUrl} onChange={setCheckmkApiUrl}
placeholder="https://checkmk/<site>/check_mk/api/1.0"
monospace monospace
icon={<Globe className="w-3.5 h-3.5" />} icon={<Globe className="w-3.5 h-3.5" />}
/> />
@ -752,7 +746,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={checkmkApiUser} value={checkmkApiUser}
onChange={setCheckmkApiUser} onChange={setCheckmkApiUser}
placeholder="automation"
monospace monospace
icon={<KeyRound className="w-3.5 h-3.5" />} icon={<KeyRound className="w-3.5 h-3.5" />}
/> />
@ -765,7 +758,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<SecretInput <SecretInput
value={checkmkApiSecret} value={checkmkApiSecret}
onChange={setCheckmkApiSecret} onChange={setCheckmkApiSecret}
alreadySet={checkmkSecretSet}
show={showCheckmkSecret} show={showCheckmkSecret}
onToggleShow={() => setShowCheckmkSecret(v => !v)} onToggleShow={() => setShowCheckmkSecret(v => !v)}
/> />
@ -774,7 +766,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={checkmkSyncInterval} value={checkmkSyncInterval}
onChange={setCheckmkSyncInterval} onChange={setCheckmkSyncInterval}
placeholder="60000"
monospace monospace
icon={<Clock className="w-3.5 h-3.5" />} icon={<Clock className="w-3.5 h-3.5" />}
/> />
@ -835,7 +826,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={semaphoreApiUrl} value={semaphoreApiUrl}
onChange={setSemaphoreApiUrl} onChange={setSemaphoreApiUrl}
placeholder="https://semaphore/api/v1alpha"
monospace monospace
icon={<Globe className="w-3.5 h-3.5" />} icon={<Globe className="w-3.5 h-3.5" />}
/> />
@ -849,7 +839,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<SecretInput <SecretInput
value={semaphoreApiToken} value={semaphoreApiToken}
onChange={setSemaphoreApiToken} onChange={setSemaphoreApiToken}
alreadySet={semaphoreTokenSet}
show={showSemaphoreToken} show={showSemaphoreToken}
onToggleShow={() => setShowSemaphoreToken(v => !v)} onToggleShow={() => setShowSemaphoreToken(v => !v)}
/> />
@ -858,7 +847,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<Input <Input
value={semaphoreProjectId} value={semaphoreProjectId}
onChange={setSemaphoreProjectId} onChange={setSemaphoreProjectId}
placeholder="1"
monospace monospace
icon={<KeyRound className="w-3.5 h-3.5" />} icon={<KeyRound className="w-3.5 h-3.5" />}
/> />
@ -945,7 +933,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
{caddyManaged && ( {caddyManaged && (
<div className={`space-y-5 transition-opacity duration-200 ${!caddyEnabled ? 'opacity-40 pointer-events-none' : ''}`}> <div className={`space-y-5 transition-opacity duration-200 ${!caddyEnabled ? 'opacity-40 pointer-events-none' : ''}`}>
<FieldRow label="Caddy Admin URL" hint="Default: http://127.0.0.1:2019"> <FieldRow label="Caddy Admin URL" hint="Default: http://127.0.0.1:2019">
<Input value={caddyAdminUrl} onChange={setCaddyAdminUrl} placeholder="http://172.0.0.1:2019" monospace icon={<Globe className="w-3.5 h-3.5" />} /> <Input value={caddyAdminUrl} onChange={setCaddyAdminUrl} monospace icon={<Globe className="w-3.5 h-3.5" />} />
</FieldRow> </FieldRow>
{/* Route list */} {/* Route list */}
@ -974,11 +962,11 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<div className="flex items-end gap-2"> <div className="flex items-end gap-2">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<Label>Hostname</Label> <Label>Hostname</Label>
<Input value={editHostname} onChange={setEditHostname} placeholder="hostname" monospace /> <Input value={editHostname} onChange={setEditHostname} monospace />
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<Label>Upstream</Label> <Label>Upstream</Label>
<Input value={editUpstream} onChange={setEditUpstream} placeholder="127.0.0.1:3000" monospace /> <Input value={editUpstream} onChange={setEditUpstream} monospace />
</div> </div>
<div className="flex flex-col items-center gap-1 pb-0.5"> <div className="flex flex-col items-center gap-1 pb-0.5">
<span className="text-[9px] font-semibold text-slate-400 uppercase tracking-wide">TLS</span> <span className="text-[9px] font-semibold text-slate-400 uppercase tracking-wide">TLS</span>
@ -1003,7 +991,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<X className="w-3.5 h-3.5" /> <X className="w-3.5 h-3.5" />
</button> </button>
</div> </div>
<Input value={editRedirect} onChange={setEditRedirect} placeholder="root redirect" monospace /> <Input value={editRedirect} onChange={setEditRedirect} monospace />
</div> </div>
) : ( ) : (
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
@ -1035,11 +1023,11 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
<div className="flex items-end gap-2"> <div className="flex items-end gap-2">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<Label>Hostname</Label> <Label>Hostname</Label>
<Input value={newHostname} onChange={setNewHostname} placeholder="semaphore" monospace /> <Input value={newHostname} onChange={setNewHostname} monospace />
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<Label>Upstream</Label> <Label>Upstream</Label>
<Input value={newUpstream} onChange={setNewUpstream} placeholder="127.0.0.1:3000" monospace /> <Input value={newUpstream} onChange={setNewUpstream} monospace />
</div> </div>
<div className="flex flex-col items-center gap-1 pb-0.5"> <div className="flex flex-col items-center gap-1 pb-0.5">
<span className="text-[9px] font-semibold text-slate-400 uppercase tracking-wide">TLS</span> <span className="text-[9px] font-semibold text-slate-400 uppercase tracking-wide">TLS</span>
@ -1071,7 +1059,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
{addingRoute ? 'Adding…' : 'Add'} {addingRoute ? 'Adding…' : 'Add'}
</button> </button>
</div> </div>
<Input value={newRedirect} onChange={setNewRedirect} placeholder="Root redirect (optional), e.g. /site1/" monospace /> <Input value={newRedirect} onChange={setNewRedirect} monospace />
</div> </div>
</div> </div>
)} )}

View File

@ -219,7 +219,6 @@ export default function UserDirectory({ users, currentUser, bookings, onDeleteUs
<span className="absolute left-3 top-2.5 text-slate-500"><Search className="w-4 h-4" /></span> <span className="absolute left-3 top-2.5 text-slate-500"><Search className="w-4 h-4" /></span>
<input <input
type="text" type="text"
placeholder="Search operators by name, email or role…"
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
className="w-full bg-[#1E293B] text-slate-100 border border-slate-800 rounded-xl pl-9 pr-4 py-2 text-xs focus:outline-none focus:border-emerald-600" className="w-full bg-[#1E293B] text-slate-100 border border-slate-800 rounded-xl pl-9 pr-4 py-2 text-xs focus:outline-none focus:border-emerald-600"