Compare commits

...

2 Commits

Author SHA1 Message Date
spinline
999cef34a7 fix(frontend): remove fake ScrollBar and use native styled webkit scrollbar in ScrollArea
All checks were successful
Build MIPS Binary / build (push) Successful in 2m1s
2026-02-21 20:51:27 +03:00
spinline
93a43d1b38 feat(frontend): implement rust-ui ScrollArea for details tab scrolling
All checks were successful
Build MIPS Binary / build (push) Successful in 2m1s
2026-02-21 20:44:20 +03:00
3 changed files with 105 additions and 2 deletions

View File

@@ -68,7 +68,7 @@ pub fn TorrentDetailsSheet() -> impl IntoView {
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
<div class="flex-1 overflow-y-auto min-h-0 mt-4 pb-12 pr-2"> <crate::components::ui::scroll_area::ScrollArea class="flex-1 min-h-0 mt-4 pb-12 pr-4">
<TabsContent value="general" class="space-y-6 animate-in fade-in slide-in-from-bottom-2 duration-300"> <TabsContent value="general" class="space-y-6 animate-in fade-in slide-in-from-bottom-2 duration-300">
<crate::components::ui::shimmer::Shimmer <crate::components::ui::shimmer::Shimmer
loading=Signal::derive(move || selected_torrent.get().is_none()) loading=Signal::derive(move || selected_torrent.get().is_none())
@@ -186,7 +186,7 @@ pub fn TorrentDetailsSheet() -> impl IntoView {
<p class="text-sm font-medium">"Eş listesi yakında eklenecek"</p> <p class="text-sm font-medium">"Eş listesi yakında eklenecek"</p>
</div> </div>
</TabsContent> </TabsContent>
</div> </crate::components::ui::scroll_area::ScrollArea>
</Tabs> </Tabs>
</div> </div>
</SheetContent> </SheetContent>

View File

@@ -14,6 +14,7 @@ pub mod input;
pub mod multi_select; pub mod multi_select;
pub mod select; pub mod select;
pub mod separator; pub mod separator;
pub mod scroll_area;
pub mod sheet; pub mod sheet;
pub mod sidenav; pub mod sidenav;
pub mod skeleton; pub mod skeleton;

View File

@@ -0,0 +1,102 @@
use leptos::prelude::*;
use leptos_ui::void;
use tw_merge::*;
// Removed unused fake components
/* ========================================================== */
/* ✨ COMPONENTS ✨ */
/* ========================================================== */
#[component]
pub fn ScrollArea(children: Children, #[prop(into, optional)] class: String) -> impl IntoView {
let merged_class = tw_merge!("relative overflow-hidden", class);
view! {
<div data-name="ScrollArea" class=merged_class>
<ScrollAreaViewport class="pr-3 pb-3 [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-border/60 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-border/80">{children()}</ScrollAreaViewport>
</div>
}
}
#[component]
pub fn ScrollAreaViewport(children: Children, #[prop(into, optional)] class: String) -> impl IntoView {
let merged_class = tw_merge!(
"focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1 overflow-auto",
class
);
view! {
<div data-name="ScrollAreaViewport" class=merged_class>
{children()}
</div>
}
}
/* ========================================================== */
/* 🧬 ENUMS 🧬 */
/* ========================================================== */
// Real scrollbars are now utilized in the viewport directly.
/* ========================================================== */
/* 🧬 STRUCT 🧬 */
/* ========================================================== */
#[component]
pub fn SnapScrollArea(
#[prop(into, default = SnapAreaVariant::default())] variant: SnapAreaVariant,
#[prop(into, optional)] class: String,
children: Children,
) -> impl IntoView {
let snap_item = SnapAreaClass { variant };
let merged_class = snap_item.with_class(class);
view! {
<div data-name="SnapScrollArea" class=merged_class>
{children()}
</div>
}
}
#[derive(TwClass, Default)]
#[tw(class = "")]
pub struct SnapAreaClass {
variant: SnapAreaVariant,
}
#[derive(TwVariant)]
pub enum SnapAreaVariant {
// * snap-x by default
#[tw(default, class = "overflow-x-auto snap-x")]
Center,
}
/* ========================================================== */
/* 🧬 STRUCT 🧬 */
/* ========================================================== */
#[component]
pub fn SnapItem(
#[prop(into, default = SnapVariant::default())] variant: SnapVariant,
#[prop(into, optional)] class: String,
children: Children,
) -> impl IntoView {
let snap_item = SnapItemClass { variant };
let merged_class = snap_item.with_class(class);
view! {
<div data-name="SnapItem" class=merged_class>
{children()}
</div>
}
}
#[derive(TwClass, Default)]
#[tw(class = "shrink-0")]
pub struct SnapItemClass {
variant: SnapVariant,
}
#[derive(TwVariant)]
pub enum SnapVariant {
// * snap-center by default
#[tw(default, class = "snap-center")]
Center,
}