Apply VibeTorrent Glassmorphism Edition theme
Some checks failed
Build MIPS Binary / build (push) Failing after 3s

This commit is contained in:
spinline
2026-02-08 22:13:54 +03:00
parent d3792e78e0
commit 2d5c2325df
8 changed files with 285 additions and 80 deletions

View File

@@ -20,6 +20,11 @@
<link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" />
<link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Trunk Assets -->
<link data-trunk rel="rust" href="Cargo.toml" data-wasm-opt="0" />
<link data-trunk rel="css" href="public/tailwind.css" />

View File

@@ -3,14 +3,42 @@
@plugin "daisyui" {
themes:
light, dark, dim, nord, cupcake, dracula, cyberpunk, emerald, sunset,
abyss;
vibeglass, dark;
}
@layer base {
html {
font-family: 'Space Grotesk', sans-serif;
}
html,
body {
@apply min-h-dvh w-full overflow-hidden bg-base-100 text-base-content overscroll-y-none;
@apply min-h-dvh w-full overflow-hidden bg-[#0f172a] text-base-content overscroll-y-none;
background-image:
radial-gradient(circle at 15% 50%, rgba(244, 157, 37, 0.08), transparent 25%),
radial-gradient(circle at 85% 30%, rgba(59, 130, 246, 0.08), transparent 25%);
background-attachment: fixed;
}
/* Glassmorphism Utilities */
.glass-panel {
@apply bg-gray-800/40 backdrop-blur-xl border border-white/10 shadow-xl;
}
.glass-sidebar {
@apply bg-gray-900/60 backdrop-blur-xl border-r border-white/5;
}
.glass-header {
@apply bg-gray-900/40 backdrop-blur-md border-b border-white/5;
}
.glass-input {
@apply bg-gray-700/30 border border-white/10 text-white placeholder-gray-400 focus:border-primary focus:ring-1 focus:ring-primary transition-all backdrop-blur-sm;
}
.glass-card {
@apply bg-gray-800/30 backdrop-blur-md border border-white/5 shadow-lg hover:bg-gray-800/40 transition-colors;
}
}
@@ -30,3 +58,22 @@
:focus {
outline: none !important;
}
/* Scrollbar styling for glass theme */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.2);
}

View File

@@ -6,13 +6,13 @@ use crate::components::layout::toolbar::Toolbar;
#[component]
pub fn Protected(children: Children) -> impl IntoView {
view! {
<div class="drawer lg:drawer-open h-full w-full">
<div class="drawer lg:drawer-open h-full w-full bg-transparent">
<input id="my-drawer" type="checkbox" class="drawer-toggle" />
<div class="drawer-content flex flex-col h-full overflow-hidden bg-base-100 text-base-content text-sm select-none">
<div class="drawer-content flex flex-col h-full overflow-hidden text-base-content text-sm select-none">
<Toolbar />
<main class="flex-1 flex flex-col min-w-0 bg-base-100 overflow-hidden pb-8">
<main class="flex-1 flex flex-col min-w-0 overflow-hidden pb-8">
{children()}
</main>
@@ -21,7 +21,7 @@ pub fn Protected(children: Children) -> impl IntoView {
<div class="drawer-side z-40 transition-none duration-0">
<label for="my-drawer" aria-label="close sidebar" class="drawer-overlay transition-none duration-0"></label>
<div class="menu p-0 min-h-full bg-base-200 text-base-content border-r border-base-300 transition-none duration-0">
<div class="menu p-0 min-h-full bg-transparent border-r border-white/5 transition-none duration-0">
<Sidebar />
</div>
</div>

View File

@@ -104,17 +104,17 @@ pub fn Sidebar() -> impl IntoView {
view! {
<div class="w-64 min-h-[100dvh] flex flex-col bg-base-200 border-r border-base-300 pb-8" style="padding-top: env(safe-area-inset-top);">
<div class="w-64 min-h-[100dvh] flex flex-col glass-sidebar pb-8" style="padding-top: env(safe-area-inset-top);">
<div class="p-2 flex-1 overflow-y-auto">
<ul class="menu w-full rounded-box gap-1">
<ul class="menu w-full gap-1">
<li class="menu-title text-primary uppercase font-bold px-4">"Filters"</li>
<li class="menu-title text-primary uppercase font-bold px-4 tracking-wider text-xs opacity-80">"Filters"</li>
<li>
<button class={move || format!("cursor-pointer {}", filter_class(crate::store::FilterStatus::All))} on:click=move |_| set_filter(crate::store::FilterStatus::All)>
<button class={move || format!("cursor-pointer hover:bg-white/10 {}", filter_class(crate::store::FilterStatus::All))} on:click=move |_| set_filter(crate::store::FilterStatus::All)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
@@ -124,7 +124,7 @@ pub fn Sidebar() -> impl IntoView {
"All"
<span class="badge badge-sm badge-ghost ml-auto">{total_count}</span>
<span class="badge badge-sm badge-ghost ml-auto bg-white/10 border-0">{total_count}</span>
</button>
@@ -132,7 +132,7 @@ pub fn Sidebar() -> impl IntoView {
<li>
<button class={move || format!("cursor-pointer {}", filter_class(crate::store::FilterStatus::Downloading))} on:click=move |_| set_filter(crate::store::FilterStatus::Downloading)>
<button class={move || format!("cursor-pointer hover:bg-white/10 {}", filter_class(crate::store::FilterStatus::Downloading))} on:click=move |_| set_filter(crate::store::FilterStatus::Downloading)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
@@ -142,7 +142,7 @@ pub fn Sidebar() -> impl IntoView {
"Downloading"
<span class="badge badge-sm badge-ghost ml-auto">{downloading_count}</span>
<span class="badge badge-sm badge-ghost ml-auto bg-white/10 border-0">{downloading_count}</span>
</button>
@@ -150,7 +150,7 @@ pub fn Sidebar() -> impl IntoView {
<li>
<button class={move || format!("cursor-pointer {}", filter_class(crate::store::FilterStatus::Seeding))} on:click=move |_| set_filter(crate::store::FilterStatus::Seeding)>
<button class={move || format!("cursor-pointer hover:bg-white/10 {}", filter_class(crate::store::FilterStatus::Seeding))} on:click=move |_| set_filter(crate::store::FilterStatus::Seeding)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
@@ -160,7 +160,7 @@ pub fn Sidebar() -> impl IntoView {
"Seeding"
<span class="badge badge-sm badge-ghost ml-auto">{seeding_count}</span>
<span class="badge badge-sm badge-ghost ml-auto bg-white/10 border-0">{seeding_count}</span>
</button>
@@ -168,7 +168,7 @@ pub fn Sidebar() -> impl IntoView {
<li>
<button class={move || format!("cursor-pointer {}", filter_class(crate::store::FilterStatus::Completed))} on:click=move |_| set_filter(crate::store::FilterStatus::Completed)>
<button class={move || format!("cursor-pointer hover:bg-white/10 {}", filter_class(crate::store::FilterStatus::Completed))} on:click=move |_| set_filter(crate::store::FilterStatus::Completed)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
@@ -178,7 +178,7 @@ pub fn Sidebar() -> impl IntoView {
"Completed"
<span class="badge badge-sm badge-ghost ml-auto">{completed_count}</span>
<span class="badge badge-sm badge-ghost ml-auto bg-white/10 border-0">{completed_count}</span>
</button>
@@ -186,7 +186,7 @@ pub fn Sidebar() -> impl IntoView {
<li>
<button class={move || format!("cursor-pointer {}", filter_class(crate::store::FilterStatus::Paused))} on:click=move |_| set_filter(crate::store::FilterStatus::Paused)>
<button class={move || format!("cursor-pointer hover:bg-white/10 {}", filter_class(crate::store::FilterStatus::Paused))} on:click=move |_| set_filter(crate::store::FilterStatus::Paused)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
@@ -196,7 +196,7 @@ pub fn Sidebar() -> impl IntoView {
"Paused"
<span class="badge badge-sm badge-ghost ml-auto">{paused_count}</span>
<span class="badge badge-sm badge-ghost ml-auto bg-white/10 border-0">{paused_count}</span>
</button>
@@ -204,7 +204,7 @@ pub fn Sidebar() -> impl IntoView {
<li>
<button class={move || format!("cursor-pointer {}", filter_class(crate::store::FilterStatus::Inactive))} on:click=move |_| set_filter(crate::store::FilterStatus::Inactive)>
<button class={move || format!("cursor-pointer hover:bg-white/10 {}", filter_class(crate::store::FilterStatus::Inactive))} on:click=move |_| set_filter(crate::store::FilterStatus::Inactive)>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
@@ -214,7 +214,7 @@ pub fn Sidebar() -> impl IntoView {
"Inactive"
<span class="badge badge-sm badge-ghost ml-auto">{inactive_count}</span>
<span class="badge badge-sm badge-ghost ml-auto bg-white/10 border-0">{inactive_count}</span>
</button>
@@ -226,13 +226,13 @@ pub fn Sidebar() -> impl IntoView {
<div class="p-4 border-t border-base-300 bg-base-200/50">
<div class="p-4 border-t border-white/5 bg-black/20 backdrop-blur-sm">
<div class="flex items-center gap-3">
<div class="avatar">
<div class="w-8 rounded-full bg-neutral text-neutral-content ring ring-primary ring-offset-base-100 ring-offset-1">
<div class="w-8 rounded-full bg-primary/20 text-primary ring ring-primary ring-offset-base-100 ring-offset-1 ring-opacity-50">
<span class="text-sm font-bold flex items-center justify-center h-full">{first_letter}</span>
@@ -242,9 +242,9 @@ pub fn Sidebar() -> impl IntoView {
<div class="flex-1 overflow-hidden">
<div class="font-bold text-sm truncate">{username}</div>
<div class="font-bold text-sm truncate text-white">{username}</div>
<div class="text-[10px] text-base-content/60 truncate">"Online"</div>
<div class="text-[10px] text-white/50 truncate">"Online"</div>
</div>

View File

@@ -6,7 +6,7 @@ pub fn Toolbar() -> impl IntoView {
let store = use_context::<crate::store::TorrentStore>().expect("store not provided");
view! {
<div class="navbar min-h-14 h-auto bg-base-100 p-0" style="padding-top: env(safe-area-inset-top);">
<div class="navbar glass-header min-h-14 h-auto p-0" style="padding-top: env(safe-area-inset-top);">
<div class="navbar-start gap-4 px-4">
<label for="my-drawer" class="btn btn-square btn-ghost lg:hidden drawer-button">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-5 h-5 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
@@ -14,7 +14,7 @@ pub fn Toolbar() -> impl IntoView {
<div class="flex gap-2">
<button
class="btn btn-sm btn-primary gap-2 font-normal"
class="btn btn-sm btn-primary gap-2 font-normal border-0 bg-primary/80 hover:bg-primary backdrop-blur text-white shadow-lg shadow-primary/20"
title="Add Magnet Link"
on:click=move |_| set_show_add_modal.set(true)
>
@@ -29,11 +29,11 @@ pub fn Toolbar() -> impl IntoView {
</div>
<div class="navbar-end gap-2 px-4">
<div class="join">
<div class="join glass-input rounded-lg p-0.5">
<input
type="text"
placeholder="Search..."
class="input input-sm input-bordered join-item w-full max-w-xs focus:outline-none"
class="input input-sm input-ghost join-item w-full max-w-xs focus:outline-none focus:bg-transparent placeholder-gray-400 text-white"
prop:value=move || store.search_query.get()
on:input=move |ev| store.search_query.set(event_target_value(&ev))
on:keydown=move |ev: web_sys::KeyboardEvent| {
@@ -44,11 +44,11 @@ pub fn Toolbar() -> impl IntoView {
/>
<Show when=move || !store.search_query.get().is_empty()>
<button
class="btn btn-sm btn-ghost join-item border-base-content/20 border-l-0 px-2"
class="btn btn-sm btn-ghost join-item px-2 text-white/50 hover:text-white"
title="Clear Search"
on:click=move |_| store.search_query.set(String::new())
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 opacity-70">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>

View File

@@ -255,33 +255,33 @@ pub fn TorrentTable() -> impl IntoView {
};
view! {
<div class="overflow-x-auto h-full bg-base-100 relative">
<div class="hidden md:block h-full overflow-x-auto">
<div class="overflow-x-auto h-full relative p-4">
<div class="hidden md:block h-full overflow-x-auto glass-panel rounded-2xl">
<table class="table table-sm table-pin-rows w-full max-w-full whitespace-nowrap">
<thead>
<tr class="text-xs uppercase text-base-content/60 border-b border-base-200">
<th class="cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::Name)>
<tr class="text-xs uppercase text-white/50 border-b border-white/5 bg-gray-900/40 backdrop-blur-md">
<th class="cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::Name)>
<div class="flex items-center">"Name" {move || sort_arrow(SortColumn::Name)}</div>
</th>
<th class="w-24 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::Size)>
<th class="w-24 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::Size)>
<div class="flex items-center">"Size" {move || sort_arrow(SortColumn::Size)}</div>
</th>
<th class="w-48 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::Progress)>
<th class="w-48 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::Progress)>
<div class="flex items-center">"Progress" {move || sort_arrow(SortColumn::Progress)}</div>
</th>
<th class="w-24 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::Status)>
<th class="w-24 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::Status)>
<div class="flex items-center">"Status" {move || sort_arrow(SortColumn::Status)}</div>
</th>
<th class="w-24 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::DownSpeed)>
<th class="w-24 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::DownSpeed)>
<div class="flex items-center">"Down Speed" {move || sort_arrow(SortColumn::DownSpeed)}</div>
</th>
<th class="w-24 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::UpSpeed)>
<th class="w-24 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::UpSpeed)>
<div class="flex items-center">"Up Speed" {move || sort_arrow(SortColumn::UpSpeed)}</div>
</th>
<th class="w-24 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::ETA)>
<th class="w-24 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::ETA)>
<div class="flex items-center">"ETA" {move || sort_arrow(SortColumn::ETA)}</div>
</th>
<th class="w-32 cursor-pointer hover:bg-base-300 group select-none" on:click=move |_| handle_sort(SortColumn::AddedDate)>
<th class="w-32 cursor-pointer hover:bg-white/5 group select-none py-4" on:click=move |_| handle_sort(SortColumn::AddedDate)>
<div class="flex items-center">"Date" {move || sort_arrow(SortColumn::AddedDate)}</div>
</th>
</tr>
@@ -295,7 +295,7 @@ pub fn TorrentTable() -> impl IntoView {
shared::TorrentStatus::Downloading => "text-primary",
shared::TorrentStatus::Paused => "text-warning",
shared::TorrentStatus::Error => "text-error",
_ => "text-base-content/50"
_ => "text-white/50"
};
let t_hash = t.hash.clone();
let t_hash_click = t.hash.clone();
@@ -307,7 +307,7 @@ pub fn TorrentTable() -> impl IntoView {
view! {
<tr
class=move || {
let base = "hover border-b border-base-200 select-none";
let base = "hover:bg-white/5 border-b border-white/5 select-none transition-colors duration-150";
if is_selected_fn() {
format!("{} bg-primary/10", base)
} else {
@@ -323,21 +323,21 @@ pub fn TorrentTable() -> impl IntoView {
move |_| set_selected_hash.set(Some(t_hash.clone()))
}
>
<td class="font-medium truncate max-w-xs" title={t.name.clone()}>
<td class="font-medium truncate max-w-xs py-3 text-white" title={t.name.clone()}>
{t.name}
</td>
<td class="opacity-80 font-mono text-[11px]">{format_bytes(t.size)}</td>
<td>
<td class="opacity-80 font-mono text-[11px] py-3 text-white/70">{format_bytes(t.size)}</td>
<td class="py-3">
<div class="flex items-center gap-2">
<progress class={format!("progress w-24 {}", progress_class)} value={t.percent_complete} max="100"></progress>
<span class="text-[10px] opacity-70">{format!("{:.1}%", t.percent_complete)}</span>
<progress class={format!("progress w-24 h-1.5 {}", progress_class)} value={t.percent_complete} max="100"></progress>
<span class="text-[10px] opacity-70 text-white/70">{format!("{:.1}%", t.percent_complete)}</span>
</div>
</td>
<td class={format!("text-[11px] font-medium {}", status_class)}>{status_str}</td>
<td class="text-right font-mono text-[11px] opacity-80 text-success">{format_speed(t.down_rate)}</td>
<td class="text-right font-mono text-[11px] opacity-80 text-primary">{format_speed(t.up_rate)}</td>
<td class="text-right font-mono text-[11px] opacity-80">{format_duration(t.eta)}</td>
<td class="text-right font-mono text-[11px] opacity-80 whitespace-nowrap">{format_date(t.added_date)}</td>
<td class={format!("text-[11px] font-medium py-3 {}", status_class)}>{status_str}</td>
<td class="text-right font-mono text-[11px] opacity-80 text-success py-3">{format_speed(t.down_rate)}</td>
<td class="text-right font-mono text-[11px] opacity-80 text-primary py-3">{format_speed(t.up_rate)}</td>
<td class="text-right font-mono text-[11px] opacity-80 py-3 text-white/70">{format_duration(t.eta)}</td>
<td class="text-right font-mono text-[11px] opacity-80 whitespace-nowrap py-3 text-white/70">{format_date(t.added_date)}</td>
</tr>
}
}).collect::<Vec<_>>()}
@@ -345,19 +345,19 @@ pub fn TorrentTable() -> impl IntoView {
</table>
</div>
<div class="md:hidden flex flex-col h-full bg-base-200 relative cursor-pointer">
<div class="px-3 py-2 border-b border-base-200 flex justify-between items-center bg-base-100/95 backdrop-blur z-10 shrink-0 cursor-default">
<span class="text-xs font-bold opacity-50 uppercase tracking-wider">"Torrents"</span>
<div class="md:hidden flex flex-col h-full relative cursor-pointer">
<div class="px-3 py-2 flex justify-between items-center glass-header z-10 shrink-0 cursor-default rounded-b-xl mb-3">
<span class="text-xs font-bold text-primary uppercase tracking-wider">"Torrents"</span>
<details class="dropdown dropdown-end" node_ref=sort_details_ref>
<summary class="btn btn-ghost btn-xs gap-1 opacity-70 font-normal list-none [&::-webkit-details-marker]:hidden cursor-pointer">
<summary class="btn btn-ghost btn-xs gap-1 opacity-70 font-normal list-none [&::-webkit-details-marker]:hidden cursor-pointer text-white">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 7.5L7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5" />
</svg>
<span class="pointer-events-none">"Sort"</span>
</summary>
<ul class="dropdown-content z-[100] menu p-2 shadow bg-base-100 rounded-box w-48 mt-1 border border-base-200 text-xs cursor-default">
<li class="menu-title px-2 py-1 opacity-50 text-[10px] uppercase font-bold">"Sort By"</li>
<ul class="dropdown-content z-[100] menu p-2 shadow-xl glass-panel rounded-box w-48 mt-1 text-xs cursor-default">
<li class="menu-title px-2 py-1 opacity-50 text-[10px] uppercase font-bold text-white">"Sort By"</li>
{
let columns = vec![
(SortColumn::Name, "Name"),
@@ -378,7 +378,7 @@ pub fn TorrentTable() -> impl IntoView {
<li>
<button
type="button"
class=move || if is_active() { "bg-primary/10 text-primary font-bold flex justify-between" } else { "flex justify-between" }
class=move || if is_active() { "bg-primary/20 text-primary font-bold flex justify-between hover:bg-primary/30" } else { "flex justify-between text-white/80 hover:bg-white/10" }
on:click=move |_| {
handle_sort(col);
if let Some(el) = sort_details_ref.get_untracked() {
@@ -408,11 +408,11 @@ pub fn TorrentTable() -> impl IntoView {
let progress_class = if t.percent_complete >= 100.0 { "progress-success" } else { "progress-primary" };
let status_str = format!("{:?}", t.status);
let status_badge_class = match t.status {
shared::TorrentStatus::Seeding => "badge-success badge-soft",
shared::TorrentStatus::Downloading => "badge-primary badge-soft",
shared::TorrentStatus::Paused => "badge-warning badge-soft",
shared::TorrentStatus::Error => "badge-error badge-soft",
_ => "badge-ghost"
shared::TorrentStatus::Seeding => "badge-success badge-soft bg-success/20 text-success border-0",
shared::TorrentStatus::Downloading => "badge-primary badge-soft bg-primary/20 text-primary border-0",
shared::TorrentStatus::Paused => "badge-warning badge-soft bg-warning/20 text-warning border-0",
shared::TorrentStatus::Error => "badge-error badge-soft bg-error/20 text-error border-0",
_ => "badge-ghost bg-white/10 text-white/50 border-0"
};
let _t_hash = t.hash.clone();
let t_hash_click = t.hash.clone();
@@ -459,7 +459,7 @@ pub fn TorrentTable() -> impl IntoView {
view! {
<div
class=move || {
"card card-compact bg-base-100 shadow-sm border border-base-200 transition-transform active:scale-[0.99] select-none cursor-pointer"
"card card-compact glass-card transition-transform active:scale-[0.99] select-none cursor-pointer"
}
style="user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;"
on:contextmenu={
@@ -477,36 +477,36 @@ pub fn TorrentTable() -> impl IntoView {
>
<div class="card-body gap-3">
<div class="flex justify-between items-start gap-2">
<h3 class="font-medium text-sm line-clamp-2 leading-tight">{t.name}</h3>
<h3 class="font-medium text-sm line-clamp-2 leading-tight text-white">{t.name}</h3>
<div class={format!("badge badge-xs text-[10px] whitespace-nowrap {}", status_badge_class)}>
{status_str}
</div>
</div>
<div class="flex flex-col gap-1">
<div class="flex justify-between text-[10px] opacity-70">
<div class="flex justify-between text-[10px] opacity-70 text-white/70">
<span>{format_bytes(t.size)}</span>
<span>{format!("{:.1}%", t.percent_complete)}</span>
</div>
<progress class={format!("progress w-full h-1.5 {}", progress_class)} value={t.percent_complete} max="100"></progress>
</div>
<div class="grid grid-cols-4 gap-2 text-[10px] font-mono opacity-80 pt-1 border-t border-base-200/50">
<div class="grid grid-cols-4 gap-2 text-[10px] font-mono opacity-80 pt-1 border-t border-white/10">
<div class="flex flex-col">
<span class="text-[9px] opacity-60 uppercase">"Down"</span>
<span class="text-[9px] opacity-60 uppercase text-white/50">"Down"</span>
<span class="text-success">{format_speed(t.down_rate)}</span>
</div>
<div class="flex flex-col text-center border-l border-r border-base-200/50">
<span class="text-[9px] opacity-60 uppercase">"Up"</span>
<div class="flex flex-col text-center border-l border-r border-white/10">
<span class="text-[9px] opacity-60 uppercase text-white/50">"Up"</span>
<span class="text-primary">{format_speed(t.up_rate)}</span>
</div>
<div class="flex flex-col text-center border-r border-base-200/50">
<span class="text-[9px] opacity-60 uppercase">"ETA"</span>
<span>{format_duration(t.eta)}</span>
<div class="flex flex-col text-center border-r border-white/10">
<span class="text-[9px] opacity-60 uppercase text-white/50">"ETA"</span>
<span class="text-white/70">{format_duration(t.eta)}</span>
</div>
<div class="flex flex-col text-right">
<span class="text-[9px] opacity-60 uppercase">"Date"</span>
<span>{format_date(t.added_date)}</span>
<span class="text-[9px] opacity-60 uppercase text-white/50">"Date"</span>
<span class="text-white/70">{format_date(t.added_date)}</span>
</div>
</div>
</div>

View File

@@ -3,13 +3,56 @@ module.exports = {
content: ["./index.html", "./src/**/*.{rs,html}"],
theme: {
extend: {
fontFamily: {
sans: ['"Space Grotesk"', 'sans-serif'],
},
colors: {
primary: {
DEFAULT: "#f49d25",
focus: "#d68315",
content: "#ffffff",
},
gray: {
900: "#111827",
800: "#1f2937",
700: "#374151",
glass: "rgba(31, 41, 55, 0.7)",
},
glass: {
100: "rgba(255, 255, 255, 0.1)",
200: "rgba(255, 255, 255, 0.2)",
border: "rgba(255, 255, 255, 0.1)",
}
},
backgroundImage: {
'glass-gradient': 'linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.01) 100%)',
}
},
},
};
plugins: [require("daisyui")],
daisyui: {
themes: [
{
vibeglass: {
"primary": "#f49d25",
"secondary": "#3b82f6",
"accent": "#10b981",
"neutral": "#1f2937",
"base-100": "#0f172a", // Çok koyu mavi/siyah arka plan
"base-200": "#1e293b",
"base-300": "#334155",
"base-content": "#f3f4f6",
"info": "#3abff8",
"success": "#36d399",
"warning": "#fbbd23",
"error": "#f87272",
"--rounded-box": "0.5rem", // ROUND_EIGHT
"--rounded-btn": "0.5rem",
"--glass-blur": "12px",
"--glass-opacity": "0.7",
},
},
"dark",
],
},
};