diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 96df492..4f11f4a 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -55,17 +55,10 @@
-
- - - - - -
Cargando usuarios…
+ @toggleDisable="toggleDisable" @remove="removeUser" @edit="openEditUser" />
@@ -96,6 +89,11 @@ + + + + diff --git a/frontend/src/components/UserCard.js b/frontend/src/components/UserCard.js index 62d21c5..baf6c99 100644 --- a/frontend/src/components/UserCard.js +++ b/frontend/src/components/UserCard.js @@ -5,16 +5,18 @@ const html = htm.bind(h); export default defineComponent({ name: 'UserCard', props: { item: { type: Object, required: true }, mode: { type: String, default: 'user' } }, - emits: ['toggleDisable', 'remove'], + emits: ['toggleDisable', 'remove', 'edit'], setup(props, { emit }) { function toggle() { emit('toggleDisable', props.item); } function remove() { emit('remove', props.item); } + function edit() { emit('edit', props.item); } return () => html`
${props.mode === 'user' ? props.item.username : (props.item.device || props.item.username)} VLAN ${props.item.vlan} ${props.item.disabled ? html`deshabilitado` : html`activo`} +
@@ -22,4 +24,3 @@ export default defineComponent({
`; } }); - diff --git a/frontend/src/components/UserForm.vue b/frontend/src/components/UserForm.vue new file mode 100644 index 0000000..3c1aa37 --- /dev/null +++ b/frontend/src/components/UserForm.vue @@ -0,0 +1,50 @@ + + + + diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 4e3a22d..2cd96fd 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -7,6 +7,12 @@ --border: 255 255 255 / 0.12; --glass-blur: 14px; --radius: 14px; + /* Scrollbar */ + --sb-size: 10px; + --sb-thumb: rgba(255, 159, 203, 0.55); + --sb-thumb-hover: rgba(255, 159, 203, 0.75); + --sb-thumb-active: rgba(255, 127, 187, 0.9); + --sb-track: rgba(255,255,255,0.05); } :root.light { --bg: 245 245 248; @@ -15,6 +21,10 @@ --accent: 18 108 242; --card: 255 255 255 / 0.6; --border: 0 0 0 / 0.08; + --sb-thumb: rgba(255, 127, 187, 0.65); + --sb-thumb-hover: rgba(255, 127, 187, 0.82); + --sb-thumb-active: rgba(255, 110, 178, 0.95); + --sb-track: rgba(0,0,0,0.06); } * { box-sizing: border-box; } html, body, #app { height: 100%; } @@ -28,8 +38,16 @@ a { color: inherit; } position: sticky; top: 0; z-index: 10; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 10px 14px; backdrop-filter: blur(var(--glass-blur)); - background: linear-gradient(180deg, rgba(var(--card)), rgba(var(--card)) 60%, rgba(0,0,0,0)); - border-bottom: 1px solid rgba(var(--border)); + border: 1px solid transparent; + background: + linear-gradient(rgba(var(--card)), rgba(var(--card))) padding-box, + linear-gradient(135deg, #ff9fcb, #ff7fbb) border-box; +} +:root:not(.light) .topbar { + background: + linear-gradient(rgba(var(--card)), rgba(var(--card))) padding-box, + linear-gradient(135deg, #ff2e86, #ff6bb0) border-box; + box-shadow: 0 0 18px rgba(255, 46, 134, 0.25), 0 0 6px rgba(255, 107, 176, 0.2); } .title { font-size: 16px; font-weight: 700; letter-spacing: .2px; flex: 1 1 auto; } .actions { display: inline-flex; flex-wrap: wrap; gap: 8px; align-items: center; } @@ -40,7 +58,17 @@ a { color: inherit; } /* Layout */ .shell { height: calc(100vh - 54px); display: grid; grid-template-columns: 360px 1fr; gap: 12px; padding: 12px; } -.panel { border: 1px solid rgba(var(--border)); background: rgba(var(--card)); border-radius: var(--radius); backdrop-filter: blur(var(--glass-blur)); overflow: hidden; display: flex; flex-direction: column; min-height: 0; } +.panel { border: 1px solid transparent; background: rgba(var(--card)); border-radius: var(--radius); backdrop-filter: blur(var(--glass-blur)); overflow: hidden; display: flex; flex-direction: column; min-height: 0; + background: + linear-gradient(rgba(var(--card)), rgba(var(--card))) padding-box, + linear-gradient(135deg, #ff9fcb, #ff7fbb) border-box; +} +:root:not(.light) .panel { + background: + linear-gradient(rgba(var(--card)), rgba(var(--card))) padding-box, + linear-gradient(135deg, #ff2e86, #ff6bb0) border-box; + box-shadow: 0 0 22px rgba(255, 46, 134, 0.18), 0 0 8px rgba(255, 107, 176, 0.15); +} .panel-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid rgba(var(--border)); } .panel-title { font-weight: 600; } .panel-actions { display: inline-flex; flex-wrap: wrap; gap: 6px; } @@ -73,3 +101,33 @@ a { color: inherit; } .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; } .spacer { flex: 1; } .toggle { padding: 6px 10px; border-radius: 8px; border: 1px solid rgba(var(--border)); background: rgba(var(--card)); } + +/* Scrollbars */ +/* Firefox */ +html, body, .scroll { + scrollbar-width: thin; + scrollbar-color: var(--sb-thumb) transparent; +} +/* WebKit */ +html::-webkit-scrollbar, body::-webkit-scrollbar, .scroll::-webkit-scrollbar { + width: var(--sb-size); + height: var(--sb-size); +} +html::-webkit-scrollbar-track, body::-webkit-scrollbar-track, .scroll::-webkit-scrollbar-track { + background: transparent; +} +html::-webkit-scrollbar-thumb, body::-webkit-scrollbar-thumb, .scroll::-webkit-scrollbar-thumb { + background: var(--sb-thumb); + border-radius: 999px; + border: 2px solid transparent; /* creates inset padding */ + background-clip: content-box; + box-shadow: 0 0 10px rgba(255, 46, 134, 0.15); +} +html::-webkit-scrollbar-thumb:hover, body::-webkit-scrollbar-thumb:hover, .scroll::-webkit-scrollbar-thumb:hover { + background: var(--sb-thumb-hover); + background-clip: content-box; +} +html::-webkit-scrollbar-thumb:active, body::-webkit-scrollbar-thumb:active, .scroll::-webkit-scrollbar-thumb:active { + background: var(--sb-thumb-active); + background-clip: content-box; +}