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:
@ -679,7 +679,6 @@ export default function BookingCalendar({
|
||||
<textarea
|
||||
required
|
||||
rows={3}
|
||||
placeholder="e.g. Validating STP failover convergence times..."
|
||||
value={bookingNotes}
|
||||
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"
|
||||
|
||||
@ -255,7 +255,6 @@ export default function DeviceInventory({
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search by hostname, IP address, rack location..."
|
||||
value={searchTerm}
|
||||
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"
|
||||
@ -497,7 +496,6 @@ Pick a box from the list to see its specs and break-glass playbook.
|
||||
value={formData.hostname}
|
||||
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"
|
||||
placeholder="SW-CORE-03"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -508,7 +506,6 @@ Pick a box from the list to see its specs and break-glass playbook.
|
||||
value={formData.ip}
|
||||
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"
|
||||
placeholder="172.16.x.x"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -522,7 +519,6 @@ Pick a box from the list to see its specs and break-glass playbook.
|
||||
value={formData.location}
|
||||
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"
|
||||
placeholder="Server Room R02, Rack C4..."
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -554,7 +550,6 @@ Pick a box from the list to see its specs and break-glass playbook.
|
||||
value={formData.type}
|
||||
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"
|
||||
placeholder="Enter new device class (e.g. Router, Load-Balancer)"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@ -567,7 +562,6 @@ Pick a box from the list to see its specs and break-glass playbook.
|
||||
value={formData.notes}
|
||||
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"
|
||||
placeholder="Serial numbers, module slots, connected uplinks, license status..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@ -401,7 +401,6 @@ export default function LabTemplates({
|
||||
value={formData.name}
|
||||
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"
|
||||
placeholder="e.g. Campus Core OSPF Backup Route"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -412,7 +411,6 @@ export default function LabTemplates({
|
||||
value={formData.location}
|
||||
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"
|
||||
placeholder="e.g. Server Room R01, Cabinet B"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -427,7 +425,6 @@ export default function LabTemplates({
|
||||
value={formData.contactPerson}
|
||||
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"
|
||||
placeholder="e.g. Jane Doe"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -438,7 +435,6 @@ export default function LabTemplates({
|
||||
value={formData.description}
|
||||
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"
|
||||
placeholder="Purpose, VLAN mappings, target device models..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -541,7 +537,6 @@ export default function LabTemplates({
|
||||
<input
|
||||
type="text"
|
||||
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}
|
||||
onChange={(e) => setLinkType(e.target.value)}
|
||||
/>
|
||||
@ -634,7 +629,6 @@ export default function LabTemplates({
|
||||
value={formData.semaphoreSetupTemplateId}
|
||||
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"
|
||||
placeholder="e.g. 3"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -645,7 +639,6 @@ export default function LabTemplates({
|
||||
value={formData.semaphoreTeardownTemplateId}
|
||||
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"
|
||||
placeholder="e.g. 4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -664,7 +657,7 @@ export default function LabTemplates({
|
||||
type="submit"
|
||||
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>
|
||||
</div>
|
||||
|
||||
|
||||
@ -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>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search links by name, host, category…"
|
||||
value={search}
|
||||
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"
|
||||
@ -263,7 +262,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
|
||||
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"
|
||||
placeholder="Add a description…"
|
||||
/>
|
||||
) : (
|
||||
<p
|
||||
@ -325,7 +323,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
|
||||
required autoFocus
|
||||
value={draft.title}
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
@ -336,7 +333,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
|
||||
required
|
||||
value={draft.url}
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
@ -347,7 +343,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
|
||||
list="link-categories"
|
||||
value={draft.category}
|
||||
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"
|
||||
/>
|
||||
<datalist id="link-categories">
|
||||
@ -361,7 +356,6 @@ export default function LinkDashboard({ links, currentUser, onAddLink, onUpdateL
|
||||
rows={2}
|
||||
value={draft.description}
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -117,7 +117,6 @@ export default function Logbook({ logs, devices, users, currentUser, onAddLog }:
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Filter audit log entries..."
|
||||
value={searchTerm}
|
||||
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"
|
||||
@ -239,7 +238,6 @@ export default function Logbook({ logs, devices, users, currentUser, onAddLog }:
|
||||
value={logMessage}
|
||||
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"
|
||||
placeholder="Describe SFP fiber replacements, port trunking alterations, routing table diagnostic evaluations..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@ -102,7 +102,6 @@ export default function LoginPage({ onLogin, onNavigateToRegister, authError }:
|
||||
value={email}
|
||||
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"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -119,7 +118,6 @@ export default function LoginPage({ onLogin, onNavigateToRegister, authError }:
|
||||
value={password}
|
||||
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"
|
||||
placeholder=""
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@ -106,7 +106,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
|
||||
value={name}
|
||||
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"
|
||||
placeholder="Max Mustermann"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -122,7 +121,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
|
||||
value={email}
|
||||
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"
|
||||
placeholder="you@example.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -139,7 +137,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
|
||||
value={password}
|
||||
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"
|
||||
placeholder="Min. 8 characters"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@ -174,7 +171,6 @@ export default function RegisterPage({ onLogin, onNavigateToLogin }: RegisterPag
|
||||
? 'border-red-700 focus:ring-red-500/50'
|
||||
: 'border-slate-700 focus:ring-cyan-500/50 focus:border-cyan-500/50'
|
||||
}`}
|
||||
placeholder="Repeat password"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@ -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;
|
||||
onChange: (v: string) => void;
|
||||
alreadySet: boolean;
|
||||
show: boolean;
|
||||
onToggleShow: () => void;
|
||||
}) {
|
||||
@ -125,7 +124,6 @@ function SecretInput({ value, onChange, alreadySet, show, onToggleShow }: {
|
||||
type={show ? 'text' : 'password'}
|
||||
value={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"
|
||||
/>
|
||||
<button
|
||||
@ -175,7 +173,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
|
||||
const [checkmkEnabled, setCheckmkEnabled] = useState(false);
|
||||
const [checkmkApiUrl, setCheckmkApiUrl] = useState('');
|
||||
const [checkmkApiUser, setCheckmkApiUser] = useState('automation');
|
||||
const [checkmkApiUser, setCheckmkApiUser] = useState('');
|
||||
const [checkmkApiSecret, setCheckmkApiSecret] = useState('');
|
||||
const [checkmkSecretSet, setCheckmkSecretSet] = useState(false);
|
||||
const [checkmkSyncInterval, setCheckmkSyncInterval] = useState('60000');
|
||||
@ -255,7 +253,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
setAzureAllowedGroup(data.azure_allowed_group || '');
|
||||
setCheckmkEnabled(data.checkmk_enabled === 'true');
|
||||
setCheckmkApiUrl(data.checkmk_api_url || '');
|
||||
setCheckmkApiUser(data.checkmk_api_user || 'automation');
|
||||
setCheckmkApiUser(data.checkmk_api_user || '');
|
||||
setCheckmkSecretSet(data.checkmk_api_secret === SECRET_SENTINEL);
|
||||
setCheckmkApiSecret('');
|
||||
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' : ''}`}>
|
||||
<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 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
|
||||
label="Client Secret"
|
||||
@ -646,7 +644,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<SecretInput
|
||||
value={azureClientSecret}
|
||||
onChange={setAzureClientSecret}
|
||||
alreadySet={azureSecretSet}
|
||||
show={showAzureSecret}
|
||||
onToggleShow={() => setShowAzureSecret(v => !v)}
|
||||
/>
|
||||
@ -659,7 +656,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={azureRedirectUri}
|
||||
onChange={setAzureRedirectUri}
|
||||
placeholder={effectiveRedirectUri || 'https://…/api/auth/azure/callback'}
|
||||
monospace
|
||||
/>
|
||||
</FieldRow>
|
||||
@ -671,7 +667,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={azureAllowedGroup}
|
||||
onChange={setAzureAllowedGroup}
|
||||
placeholder="Leave blank to allow all tenant users"
|
||||
monospace
|
||||
icon={<Users className="w-3.5 h-3.5" />}
|
||||
/>
|
||||
@ -742,7 +737,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={checkmkApiUrl}
|
||||
onChange={setCheckmkApiUrl}
|
||||
placeholder="https://checkmk/<site>/check_mk/api/1.0"
|
||||
monospace
|
||||
icon={<Globe className="w-3.5 h-3.5" />}
|
||||
/>
|
||||
@ -752,7 +746,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={checkmkApiUser}
|
||||
onChange={setCheckmkApiUser}
|
||||
placeholder="automation"
|
||||
monospace
|
||||
icon={<KeyRound className="w-3.5 h-3.5" />}
|
||||
/>
|
||||
@ -765,7 +758,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<SecretInput
|
||||
value={checkmkApiSecret}
|
||||
onChange={setCheckmkApiSecret}
|
||||
alreadySet={checkmkSecretSet}
|
||||
show={showCheckmkSecret}
|
||||
onToggleShow={() => setShowCheckmkSecret(v => !v)}
|
||||
/>
|
||||
@ -774,7 +766,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={checkmkSyncInterval}
|
||||
onChange={setCheckmkSyncInterval}
|
||||
placeholder="60000"
|
||||
monospace
|
||||
icon={<Clock className="w-3.5 h-3.5" />}
|
||||
/>
|
||||
@ -835,7 +826,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={semaphoreApiUrl}
|
||||
onChange={setSemaphoreApiUrl}
|
||||
placeholder="https://semaphore/api/v1alpha"
|
||||
monospace
|
||||
icon={<Globe className="w-3.5 h-3.5" />}
|
||||
/>
|
||||
@ -849,7 +839,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<SecretInput
|
||||
value={semaphoreApiToken}
|
||||
onChange={setSemaphoreApiToken}
|
||||
alreadySet={semaphoreTokenSet}
|
||||
show={showSemaphoreToken}
|
||||
onToggleShow={() => setShowSemaphoreToken(v => !v)}
|
||||
/>
|
||||
@ -858,7 +847,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<Input
|
||||
value={semaphoreProjectId}
|
||||
onChange={setSemaphoreProjectId}
|
||||
placeholder="1"
|
||||
monospace
|
||||
icon={<KeyRound className="w-3.5 h-3.5" />}
|
||||
/>
|
||||
@ -945,7 +933,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
{caddyManaged && (
|
||||
<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">
|
||||
<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>
|
||||
|
||||
{/* Route list */}
|
||||
@ -974,11 +962,11 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<div className="flex items-end gap-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<Label>Hostname</Label>
|
||||
<Input value={editHostname} onChange={setEditHostname} placeholder="hostname" monospace />
|
||||
<Input value={editHostname} onChange={setEditHostname} monospace />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<Label>Upstream</Label>
|
||||
<Input value={editUpstream} onChange={setEditUpstream} placeholder="127.0.0.1:3000" monospace />
|
||||
<Input value={editUpstream} onChange={setEditUpstream} monospace />
|
||||
</div>
|
||||
<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>
|
||||
@ -1003,7 +991,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
<X className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
<Input value={editRedirect} onChange={setEditRedirect} placeholder="root redirect" monospace />
|
||||
<Input value={editRedirect} onChange={setEditRedirect} monospace />
|
||||
</div>
|
||||
) : (
|
||||
<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-1 min-w-0">
|
||||
<Label>Hostname</Label>
|
||||
<Input value={newHostname} onChange={setNewHostname} placeholder="semaphore" monospace />
|
||||
<Input value={newHostname} onChange={setNewHostname} monospace />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<Label>Upstream</Label>
|
||||
<Input value={newUpstream} onChange={setNewUpstream} placeholder="127.0.0.1:3000" monospace />
|
||||
<Input value={newUpstream} onChange={setNewUpstream} monospace />
|
||||
</div>
|
||||
<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>
|
||||
@ -1071,7 +1059,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
|
||||
{addingRoute ? 'Adding…' : 'Add'}
|
||||
</button>
|
||||
</div>
|
||||
<Input value={newRedirect} onChange={setNewRedirect} placeholder="Root redirect (optional), e.g. /site1/" monospace />
|
||||
<Input value={newRedirect} onChange={setNewRedirect} monospace />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -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>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search operators by name, email or role…"
|
||||
value={search}
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user