feat: shadcn -> rust-ui.com migration + TorrentDetail silme
All checks were successful
Build MIPS Binary / build (push) Successful in 5m15s

- Tüm leptos-shadcn-* paketleri kaldırıldı (19 dependency)
- leptos_ui, tw_merge, strum eklendi
- components/ui/ modülü oluşturuldu (Button, Card, Input)
- TorrentDetail bileşeni tamamen silindi
- sidebar.rs: saf HTML+Tailwind ile SidebarButton yardımcı bileşeni
- toolbar.rs, login.rs, setup.rs, add_torrent.rs: saf HTML+Tailwind
- table.rs: shadcn Card -> rust-ui Card
- app.rs: Skeleton -> animate-pulse div
This commit is contained in:
spinline
2026-02-11 21:01:51 +03:00
parent 907ae66a7f
commit 7539307e18
16 changed files with 415 additions and 765 deletions

View File

@@ -0,0 +1,29 @@
use leptos::prelude::*;
use leptos_ui::variants;
variants! {
Button {
base: "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive w-fit hover:cursor-pointer active:scale-[0.98] active:opacity-100 touch-manipulation [-webkit-tap-highlight-color:transparent] select-none [-webkit-touch-callout:none]",
variants: {
variant: {
Default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
Destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
Outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/5",
Secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
Ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
Link: "text-primary underline-offset-4 hover:underline",
},
size: {
Default: "h-9 px-4 py-2 has-[>svg]:px-3",
Sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
Lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
Icon: "size-9",
}
},
component: {
element: button,
support_href: true,
support_aria_current: true
}
}
}

View File

@@ -0,0 +1,15 @@
use leptos::prelude::*;
use leptos_ui::clx;
mod components {
use super::*;
clx! {Card, div, "bg-card text-card-foreground flex flex-col gap-4 rounded-xl border py-6 shadow-sm"}
clx! {CardHeader, div, "@container/card-header flex flex-col items-start gap-1.5 px-6 [.border-b]:pb-6"}
clx! {CardTitle, h2, "leading-none font-semibold"}
clx! {CardContent, div, "px-6"}
clx! {CardDescription, p, "text-muted-foreground text-sm"}
clx! {CardFooter, footer, "flex items-center px-6 [.border-t]:pt-6", "gap-2"}
}
pub use components::*;

View File

@@ -0,0 +1,98 @@
use leptos::html;
use leptos::prelude::*;
use strum::AsRefStr;
use tw_merge::tw_merge;
#[derive(Default, Clone, Copy, PartialEq, Eq, AsRefStr)]
#[strum(serialize_all = "lowercase")]
pub enum InputType {
#[default]
Text,
Email,
Password,
Number,
Tel,
Url,
Search,
Date,
Time,
#[strum(serialize = "datetime-local")]
DatetimeLocal,
Month,
Week,
Color,
File,
Hidden,
}
#[component]
pub fn Input(
#[prop(into, optional)] class: String,
#[prop(default = InputType::default())] r#type: InputType,
#[prop(into, optional)] placeholder: Option<String>,
#[prop(into, optional)] name: Option<String>,
#[prop(into, optional)] id: Option<String>,
#[prop(into, optional)] title: Option<String>,
#[prop(optional)] disabled: bool,
#[prop(optional)] readonly: bool,
#[prop(optional)] required: bool,
#[prop(optional)] autofocus: bool,
#[prop(into, optional)] min: Option<String>,
#[prop(into, optional)] max: Option<String>,
#[prop(into, optional)] step: Option<String>,
#[prop(into, optional)] bind_value: Option<RwSignal<String>>,
#[prop(optional)] node_ref: NodeRef<html::Input>,
) -> impl IntoView {
let merged_class = tw_merge!(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50",
"focus-visible:ring-2",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
"read-only:bg-muted",
class
);
let type_str = r#type.as_ref();
match bind_value {
Some(signal) => view! {
<input
data-name="Input"
type=type_str
class=merged_class
placeholder=placeholder
name=name
id=id
title=title
disabled=disabled
readonly=readonly
required=required
autofocus=autofocus
min=min
max=max
step=step
bind:value=signal
node_ref=node_ref
/>
}.into_any(),
None => view! {
<input
data-name="Input"
type=type_str
class=merged_class
placeholder=placeholder
name=name
id=id
title=title
disabled=disabled
readonly=readonly
required=required
autofocus=autofocus
min=min
max=max
step=step
node_ref=node_ref
/>
}.into_any(),
}
}

View File

@@ -0,0 +1,3 @@
pub mod button;
pub mod card;
pub mod input;