Rust UI component that displays a button or a component that looks like a button.
button
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::Button; #[component] pub fn DemoButton() -> impl IntoView { view! { <Button>"Button"</Button> } }
Installation
You can run either of the following commands:
# cargo install ui-cli --forceui add demo_buttonui add button
Update the imports to match your project setup.
Copy and paste the following code into your project:
components/ui/button.rs
use leptos::prelude::*; use leptos_ui::variants; // TODO 💪 Loading state (demo_use_timeout_fn.rs and demo_button.rs) 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", // Using hover:cursor-pointer as workaround for href_support. 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", Accent: "bg-accent text-accent-foreground hover:bg-accent/80", Link: "text-primary underline-offset-4 hover:underline", // Warning: "bg-warning text-warning-foreground hover:bg-warning/90", Success: "bg-success text-success-foreground hover:bg-success/90", Bordered: "bg-transparent border border-zinc-200 text-muted-foreground", }, 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", // Mobile: "px-6 py-3 rounded-[24px]", Badge: "px-2.5 py-0.5 text-xs" } }, component: { element: button, href_support: true } } }
Update the imports to match your project setup.
Usage
use crate::components::ui::button::Button;
<Button>"Click me"</Button>
Examples
1. Reactive Button
The Button
component can be reactive.
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::Button; #[component] pub fn DemoButtonReactive() -> impl IntoView { let count = RwSignal::new(0); let increment = move |_| *count.write() += 1; view! { <Button on:click=increment>"Click Me: " {count}</Button> } }
2. Variants
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::{Button, ButtonVariant}; #[component] pub fn DemoButtonVariants() -> impl IntoView { view! { <div class="flex flex-col gap-4 items-center md:flex-row"> <Button>Default</Button> <Button variant=ButtonVariant::Secondary>Secondary</Button> <Button variant=ButtonVariant::Outline>Outline</Button> <Button variant=ButtonVariant::Ghost>Ghost</Button> <Button variant=ButtonVariant::Destructive>Destructive</Button> </div> } }
3. Sizes
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::{Button, ButtonSize}; #[component] pub fn DemoButtonSizes() -> impl IntoView { view! { <div class="flex gap-4"> <Button size=ButtonSize::Sm>Small</Button> <Button>Default</Button> <Button size=ButtonSize::Lg>Large</Button> </div> } }
4. Disabled
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::Button; #[component] pub fn DemoButtonDisabled() -> impl IntoView { view! { <div class="flex gap-4"> <Button>"Normal"</Button> <Button disabled=true>"Disabled"</Button> </div> } }
5. Overriding Button
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::Button; #[component] pub fn DemoButtonOverride() -> impl IntoView { view! { <Button class="hover:bg-pink-500 bg-sky-500">Fancy Button</Button> } }
6. Button with Clx
- Copy Demo
use leptos::prelude::*; use leptos_ui::clx; // * 💁 Define your reusable Component here: clx! {MyButton, button, "px-4 py-2 bg-neutral-900 text-white rounded-md"} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ✨ FUNCTIONS ✨ */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ #[component] pub fn DemoButtonWithClx() -> impl IntoView { let count = RwSignal::new(0); let on_click = move |_| *count.write() += 1; view! { <MyButton class="bg-sky-500" on:click=on_click> "Click Me: " {count} </MyButton> } }
7. Split Button
A split button combines a primary action with a dropdown menu for additional options.
- Copy Demo
Copy Options
- Advanced Options
- Copy with Formatting
- Copy Structure Only
- Copy with Metadata
use icons::{ChevronDown, Copy}; use leptos::prelude::*; use crate::components::_coming_soon::dropdown_menu::{ DropdownMenu, DropdownMenuAction, DropdownMenuAlign, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuLink, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubItem, DropdownMenuSubTrigger, DropdownMenuTrigger, }; use crate::components::ui::separator::Separator; use crate::components::ui::split_button::{SplitButton, SplitButtonAction}; #[component] pub fn DemoSplitButton() -> impl IntoView { view! { <SplitButton> <SplitButtonAction class="rounded-r-none rounded-l-md"> <Copy class="size-3" /> <span>"Copy Page"</span> </SplitButtonAction> <DropdownMenu align=DropdownMenuAlign::End> <DropdownMenuTrigger class="flex items-center px-1.5 h-8 rounded-l-none rounded-r-md border border-l transition-colors duration-150 outline-none bg-card text-card-foreground hover:bg-accent hover:text-accent-foreground active:bg-muted"> <ChevronDown class="size-3" /> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuLabel>"Copy Options"</DropdownMenuLabel> <DropdownMenuGroup> <DropdownMenuItem> <DropdownMenuLink href="#">"Copy as HTML"</DropdownMenuLink> </DropdownMenuItem> <DropdownMenuItem> <DropdownMenuLink href="#">"Copy as Markdown"</DropdownMenuLink> </DropdownMenuItem> <DropdownMenuItem> <DropdownMenuAction>"Copy as Plain Text"</DropdownMenuAction> </DropdownMenuItem> </DropdownMenuGroup> <Separator class="my-1" /> <DropdownMenuGroup> <DropdownMenuSub> <DropdownMenuSubTrigger>"Advanced Options"</DropdownMenuSubTrigger> <DropdownMenuSubContent> <DropdownMenuSubItem>"Copy with Formatting"</DropdownMenuSubItem> <DropdownMenuSubItem>"Copy Structure Only"</DropdownMenuSubItem> <DropdownMenuSubItem>"Copy with Metadata"</DropdownMenuSubItem> </DropdownMenuSubContent> </DropdownMenuSub> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </SplitButton> } }
8. With Href
Automatic conversion to a
tag with data-slot
attribute.
- Copy Demo
use leptos::prelude::*; use crate::components::ui::button::{Button, ButtonVariant}; #[component] pub fn DemoButtonHref() -> impl IntoView { view! { <div class="flex gap-10 p-4 rounded-lg border"> <Button href="/dashboard">"Go to Dashboard"</Button> <Button href="/dashboard" variant=ButtonVariant::Ghost class="border-2 border-dashed"> "Go to Dashboard (custom)" </Button> <Button href="https://ever-ui.com/" rel="noopener" target="_blank"> "External Link" </Button> </div> } }