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 @@
@@ -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;
+}