add modal for adding server
Build Mumble Web 2 / linux_build (push) Successful in 1m20s
Build Mumble Web 2 / windows_build (push) Successful in 2m31s
Build Mumble Web 2 / android_build (push) Successful in 5m49s

This commit is contained in:
2026-02-17 23:36:26 -07:00
parent 75990ca9ce
commit 2c22942fb3
2 changed files with 245 additions and 7 deletions
+154 -5
View File
@@ -499,7 +499,7 @@ a:visited {
}
.server-card__connect {
.server-card__action {
flex-shrink: 0;
display: flex;
align-items: center;
@@ -515,7 +515,7 @@ a:visited {
transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.server-card__connect img {
.server-card__action img {
width: 20px;
height: 20px;
filter: brightness(0) invert(0.8); /* light gray */
@@ -523,17 +523,17 @@ a:visited {
transition: opacity 0.15s;
}
.server-card__connect:hover {
.server-card__action:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.35);
transform: scale(1.08);
}
.server-card__connect:hover img {
.server-card__action:hover img {
opacity: 1.0;
}
.server-card__connect:active {
.server-card__action:active {
transform: scale(0.95);
}
@@ -556,3 +556,152 @@ a:visited {
border-color: rgba(255, 255, 255, 0.4);
color: rgba(255, 255, 255, 0.7);
}
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.0);
z-index: 999;
animation: backdrop-fade-in 150ms ease-out forwards;
}
.modal-container {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
pointer-events: none;
}
.modal {
pointer-events: auto;
/* Make this solid or nearly solid instead of see-through */
/* Old: background: rgba(255, 255, 255, 0.05); */
background: #141414; /* or #151822, or rgb(15, 15, 20) */
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
padding: 1.25rem 1.5rem 1.4rem;
width: 500px;
max-width: 90vw;
color: #fff;
display: flex;
flex-direction: column;
gap: 0.9rem;
opacity: 0;
transform: scale(0.9);
animation: modal-pop-in 160ms ease-out forwards;
}
.modal h2 {
font-size: 1.05rem;
font-weight: 600;
text-align: left;
margin: 0;
}
/* Form layout */
.modal-field {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.modal-field label {
font-size: 0.8rem;
opacity: 0.7;
}
.modal-field input {
padding: 0.55rem 0.6rem;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.18);
background: rgba(0, 0, 0, 0.35);
color: #fff;
font-size: 0.85rem;
outline: none;
transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.modal-field input::placeholder {
color: rgba(255, 255, 255, 0.45);
}
.modal-field input:focus {
border-color: rgba(255, 255, 255, 0.55);
background: rgba(0, 0, 0, 0.55);
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25);
}
/* Actions row */
.modal-actions {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
margin-top: 0.5rem;
}
/* Secondary button (Cancel) */
.modal-btn {
padding: 0.5rem 0.9rem;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.18);
background: rgba(255, 255, 255, 0.07);
color: rgba(255, 255, 255, 0.85);
font-size: 0.85rem;
cursor: pointer;
transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.modal-btn:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.35);
transform: translateY(-1px);
}
.modal-btn:active {
transform: translateY(0) scale(0.97);
}
/* Primary button (Save) */
.modal-btn--primary {
background: rgba(67, 156, 255, 0.85);
border-color: rgba(67, 156, 255, 1);
color: #ffffff;
}
.modal-btn--primary:hover {
background: rgba(92, 174, 255, 0.95);
border-color: rgba(135, 196, 255, 1);
}
/* Keyframes */
@keyframes backdrop-fade-in {
from { background: rgba(0, 0, 0, 0.0); }
to { background: rgba(0, 0, 0, 0.4); }
}
@keyframes modal-pop-in {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1.0);
}
}
+91 -2
View File
@@ -777,6 +777,7 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
},
];
let mut show_add_modal = use_signal(|| false);
let version = option_env!("MUMBLE_WEB2_VERSION");
rsx!(
div {
@@ -805,25 +806,113 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
span { class: "server-card__address", "{server.address}" }
}
button {
class: "server-card__connect",
class: "server-card__action",
onclick: move |_| { /* TODO: initiate connection */ },
img {
src: asset!("assets/edit-3-svgrepo-com.svg"),
alt: "Connect",
}
}
button {
class: "server-card__action",
onclick: move |_| { /* TODO: initiate connection */ },
img {
src: asset!("assets/arrow-right-svgrepo-com.svg"),
alt: "Connect",
}
}
}
}
}
button {
class: "add-server-btn",
onclick: move |_| {},
onclick: move |_| show_add_modal.set(true),
"+ Add Server"
}
// Conditionally render the modal
if *show_add_modal.read() {
AddServerModal { show: show_add_modal }
}
}
)
}
#[component]
fn AddServerModal(show: Signal<bool>) -> Element {
rsx! {
// Full-screen overlay
div {
class: "modal-backdrop",
onclick: move |_| show.set(false),
}
// Centering container
div {
class: "modal-container",
onclick: move |evt| evt.stop_propagation(),
div {
class: "modal",
h2 { "Add Server" }
div {
class: "modal-field",
label { "Name" }
input {
r#type: "text",
placeholder: "My Mumble Server",
}
}
div {
class: "modal-field",
label { "Address" }
input {
r#type: "text",
placeholder: "mumble.example.com",
}
}
div {
class: "modal-field",
label { "Port" }
input {
r#type: "number",
placeholder: "64738",
}
}
div {
class: "modal-field",
label { "Username" }
input {
r#type: "text",
placeholder: "Nickname",
}
}
div {
class: "modal-field",
label { "Password (optional)" }
input {
r#type: "password",
placeholder: "Password",
}
}
div {
class: "modal-actions",
button {
class: "modal-btn",
onclick: move |_| show.set(false),
"Cancel"
}
button {
class: "modal-btn modal-btn--primary",
onclick: move |_| { /* TODO: save server */ },
"Save"
}
}
}
}
}
}
pub fn app() -> Element {
static STYLE: Asset = asset!("/assets/main.scss");