feat(profile): add App Passwords UI to profile page
Add complete app password management UI with generate, copy, revoke functionality. Includes auto-generated client session passwords section, CSP-compliant event handlers, and dark mode support.
This commit is contained in:
@@ -4,7 +4,7 @@ body{background:#f5f7fa;color:#1e293b;min-height:100vh;height:auto;display:flex;
|
||||
.link-reset-flex{text-decoration:none;color:inherit;display:flex;align-items:center;gap:14px}
|
||||
.width-zero{width:0%}
|
||||
|
||||
#main-content{display:none}
|
||||
/* #main-content and #auth-error start hidden via .hidden class */
|
||||
|
||||
/* ── Scrollbar ── */
|
||||
::-webkit-scrollbar{width:8px}
|
||||
@@ -104,11 +104,60 @@ body{background:#f5f7fa;color:#1e293b;min-height:100vh;height:auto;display:flex;
|
||||
.alert-success{background:#ecfdf5;color:#065f46;border:1px solid #a7f3d0}
|
||||
.alert-error{background:#fef2f2;color:#991b1b;border:1px solid #fecaca}
|
||||
|
||||
/* ── App Passwords ── */
|
||||
.section-desc{font-size:13px;color:#64748b;margin-bottom:16px;line-height:1.5}
|
||||
.scope-checkboxes{display:flex;gap:16px;flex-wrap:wrap}
|
||||
.checkbox-label{display:flex;align-items:center;gap:5px;font-size:13px;font-weight:500;color:#334155;cursor:pointer}
|
||||
.checkbox-label input[type="checkbox"]{accent-color:#ff5e3a;width:16px;height:16px}
|
||||
.form-select{
|
||||
width:100%;padding:10px 14px;border:2px solid #e2e8f0;border-radius:10px;font-size:14px;
|
||||
background:#f8fafc;color:#1e293b;font-family:inherit;transition:all .2s;appearance:auto;
|
||||
}
|
||||
.form-select:focus{outline:none;border-color:#ff5e3a;background:#fff;box-shadow:0 0 0 3px rgba(255,94,58,.1)}
|
||||
.btn-secondary{background:#f1f5f9;color:#334155;border:2px solid #e2e8f0}
|
||||
.btn-secondary:hover{background:#e2e8f0}
|
||||
.btn-danger{background:linear-gradient(135deg,#dc2626,#ef4444);color:#fff;box-shadow:0 2px 8px rgba(220,38,38,.2)}
|
||||
.btn-danger:hover{box-shadow:0 4px 14px rgba(220,38,38,.3);transform:translateY(-1px)}
|
||||
.btn-sm{padding:6px 12px;font-size:12px;border-radius:8px}
|
||||
|
||||
.app-pw-table{width:100%;border-collapse:collapse;font-size:13px}
|
||||
.app-pw-table th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8;font-weight:700;padding:8px 10px;border-bottom:2px solid #e2e8f0}
|
||||
.app-pw-table td{padding:10px;border-bottom:1px solid #f1f5f9;vertical-align:middle}
|
||||
.app-pw-table tr:last-child td{border-bottom:none}
|
||||
.app-pw-label-cell{font-weight:600;color:#1e293b}
|
||||
.app-pw-prefix code{font-size:12px;background:#f1f5f9;padding:2px 8px;border-radius:6px;color:#64748b}
|
||||
|
||||
.badge{display:inline-block;font-size:11px;font-weight:600;padding:2px 10px;border-radius:12px}
|
||||
.badge-active{background:#ecfdf5;color:#065f46}
|
||||
.badge-expired{background:#fef2f2;color:#991b1b}
|
||||
|
||||
@media(max-width:640px){
|
||||
.app-pw-table{font-size:12px}
|
||||
.app-pw-table th:nth-child(3),.app-pw-table td:nth-child(3),
|
||||
.app-pw-table th:nth-child(5),.app-pw-table td:nth-child(5){display:none}
|
||||
}
|
||||
.app-pw-empty{text-align:center;padding:24px;color:#94a3b8;font-size:13px}
|
||||
.app-pw-empty i{margin-right:6px}
|
||||
|
||||
.hidden{display:none}
|
||||
.app-pw-warn{margin-bottom:8px}
|
||||
.app-pw-dismiss{margin-top:10px}
|
||||
.app-pw-actions{display:flex;gap:8px}
|
||||
.app-pw-new-btn{margin-top:14px}
|
||||
.app-pw-created-box{position:relative}
|
||||
.app-pw-token-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}
|
||||
.app-pw-token-input{
|
||||
flex:1;padding:10px 14px;border:2px solid #a7f3d0;border-radius:10px;font-size:14px;
|
||||
font-family:'Courier New',Courier,monospace;background:#f0fdf4;color:#065f46;
|
||||
}
|
||||
.app-pw-instr-list{font-size:12px;line-height:1.8;margin-top:8px}
|
||||
.app-pw-instr-list code{background:#f0fdf4;padding:1px 6px;border-radius:4px;font-size:12px}
|
||||
|
||||
/* ── Loading / Error ── */
|
||||
#loading{text-align:center;padding:80px;color:#94a3b8;font-size:15px}
|
||||
#loading i{font-size:32px;color:#ff5e3a;display:block;margin-bottom:12px;animation:spin 1s linear infinite}
|
||||
@keyframes spin{to{transform:rotate(360deg)}}
|
||||
#auth-error{display:none;text-align:center;padding:80px 20px}
|
||||
#auth-error{text-align:center;padding:80px 20px}
|
||||
#auth-error .err-icon{width:80px;height:80px;background:#fef2f2;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 20px}
|
||||
#auth-error .err-icon i{font-size:32px;color:#ef4444}
|
||||
#auth-error h2{color:#991b1b;margin-bottom:8px;font-size:20px}
|
||||
@@ -190,6 +239,21 @@ body{background:#f5f7fa;color:#1e293b;min-height:100vh;height:auto;display:flex;
|
||||
[data-theme="dark"] #auth-error .err-icon{background:#3b1111}
|
||||
[data-theme="dark"] #auth-error h2{color:#fca5a5}
|
||||
[data-theme="dark"] #auth-error p{color:#94a3b8}
|
||||
[data-theme="dark"] .section-desc{color:#64748b}
|
||||
[data-theme="dark"] .checkbox-label{color:#94a3b8}
|
||||
[data-theme="dark"] .form-select{background:#0f172a;border-color:#334155;color:#e2e8f0}
|
||||
[data-theme="dark"] .form-select:focus{border-color:#ff5e3a;background:#0f172a;box-shadow:0 0 0 3px rgba(255,94,58,.15)}
|
||||
[data-theme="dark"] .btn-secondary{background:#334155;color:#e2e8f0;border-color:#475569}
|
||||
[data-theme="dark"] .btn-secondary:hover{background:#475569}
|
||||
[data-theme="dark"] .app-pw-table th{color:#64748b;border-bottom-color:#334155}
|
||||
[data-theme="dark"] .app-pw-table td{border-bottom-color:#1e293b}
|
||||
[data-theme="dark"] .app-pw-label-cell{color:#f1f5f9}
|
||||
[data-theme="dark"] .app-pw-prefix code{background:#334155;color:#94a3b8}
|
||||
[data-theme="dark"] .badge-active{background:#052e16;color:#86efac}
|
||||
[data-theme="dark"] .badge-expired{background:#3b1111;color:#fca5a5}
|
||||
[data-theme="dark"] .app-pw-empty{color:#64748b}
|
||||
[data-theme="dark"] .app-pw-token-input{background:#052e16;border-color:#065f46;color:#86efac}
|
||||
[data-theme="dark"] .app-pw-instr-list code{background:#052e16;color:#86efac}
|
||||
[data-theme="dark"] #loading{color:#64748b}
|
||||
[data-theme="dark"] .app-pw-desc{color:#94a3b8}
|
||||
[data-theme="dark"] .app-pw-create input{background:#0f172a;border-color:#334155;color:#e2e8f0}
|
||||
|
||||
Reference in New Issue
Block a user