feat(desktop/ui): shadcn-like form polish (labels/fields), input-group with eye toggle for provisioning secret; CSS refinements for clarity

This commit is contained in:
Esdras Renan 2025-10-10 00:21:40 -03:00
parent 319e9d0eef
commit e3796a4154
2 changed files with 60 additions and 13 deletions

View file

@ -522,20 +522,32 @@ function renderProvisionForm(profile: MachineProfile) {
contentElement.innerHTML = `
<form id="provision-form">
<label>
Código de provisionamento
<input type="password" name="provisioningSecret" placeholder="Insira o código fornecido" required autocomplete="one-time-code" />
</label>
<label>
Tenant (opcional)
<div class="field">
<label class="label">Código de provisionamento</label>
<div class="input-group">
<input id="provisioningSecret" type="password" name="provisioningSecret" placeholder="Insira o código fornecido" required autocomplete="one-time-code" />
<button type="button" id="toggle-secret" class="icon-button" aria-label="Mostrar/ocultar">
<svg class="icon-eye" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 5C7 5 2.73 8.11 1 12c1.73 3.89 6 7 11 7s9.27-3.11 11-7c-1.73-3.89-6-7-11-7Z" stroke="currentColor" stroke-width="1.8"/>
<circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="1.8"/>
</svg>
</button>
</div>
<span class="optional">Segredo fornecido pelo servidor</span>
</div>
<div class="field">
<label class="label">Tenant (opcional)</label>
<span class="optional">Use apenas se houver múltiplos ambientes</span>
<input type="text" name="tenantId" placeholder="Ex.: tenant-atlas" />
</label>
<label>
Empresa (slug opcional)
</div>
<div class="field">
<label class="label">Empresa (slug opcional)</label>
<span class="optional">Informe para vincular à empresa correta</span>
<input type="text" name="companySlug" placeholder="Ex.: empresa-exemplo" />
</label>
</div>
<div class="actions">
<button type="submit">Registrar máquina</button>
<button type="button" class="secondary" id="refresh-profile">Atualizar dados</button>
@ -563,6 +575,19 @@ function renderProvisionForm(profile: MachineProfile) {
setAlert("Não foi possível atualizar as informações da máquina.", "error")
}
})
// Olhinho: mostrar/ocultar segredo
const toggleBtn = document.getElementById("toggle-secret") as HTMLButtonElement | null
const secretInput = document.getElementById("provisioningSecret") as HTMLInputElement | null
toggleBtn?.addEventListener("click", () => {
if (!secretInput) return
const isPw = secretInput.type === "password"
secretInput.type = isPw ? "text" : "password"
// alterna ícone
toggleBtn.innerHTML = isPw
? '<svg class="icon-eye-off" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 3l18 18" stroke="currentColor" stroke-width="1.8"/><path d="M10.58 10.58A3 3 0 0012 15a3 3 0 001.42-.38M9.9 4.24A10.94 10.94 0 0112 4c5 0 9.27 3.11 11 7a11.65 11.65 0 01-4.31 5.22M6.35 6.35C4 7.76 2.27 9.7 1 12c1.73 3.89 6 7 11 7 1.53 0 2.99-.29 4.31-.82" stroke="currentColor" stroke-width="1.8"/></svg>'
: '<svg class="icon-eye" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5C7 5 2.73 8.11 1 12c1.73 3.89 6 7 11 7s9.27-3.11 11-7c-1.73-3.89-6-7-11-7Z" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="1.8"/></svg>'
})
}
async function handleRegister(profile: MachineProfile, form: HTMLFormElement) {

View file

@ -71,9 +71,8 @@ form {
}
label {
display: grid;
gap: 6px;
font-weight: 500;
display: block;
font-weight: 600;
color: #0f172a;
}
@ -83,6 +82,29 @@ label span.optional {
font-size: 0.85rem;
}
.field { display: grid; gap: 6px; }
.label { font-size: 0.9rem; }
.input-group { position: relative; }
.input-group input { width: 100%; padding-right: 40px; }
.icon-button {
position: absolute;
top: 50%;
right: 8px;
transform: translateY(-50%);
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px; height: 28px;
border-radius: 6px;
border: 1px solid transparent;
background: #f1f5f9;
color: #334155;
cursor: pointer;
}
.icon-button:hover { background: #e2e8f0; }
.icon-eye, .icon-eye-off { width: 18px; height: 18px; }
input,
select {
padding: 10px 12px;