Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion component.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"preview/src/components/textarea",
"preview/src/components/skeleton",
"preview/src/components/card",
"preview/src/components/sheet"
"preview/src/components/sheet",
"preview/src/components/badge"
]
}
21 changes: 20 additions & 1 deletion preview/src/components/avatar/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ impl AvatarImageSize {
}
}

#[derive(Clone, Copy, PartialEq, Default)]
pub enum AvatarShape {
#[default]
Circle,
Rounded,
}

impl AvatarShape {
fn to_class(self) -> &'static str {
match self {
AvatarShape::Circle => "avatar-circle",
AvatarShape::Rounded => "avatar-rounded",
}
}
}

/// The props for the [`Avatar`] component.
#[derive(Props, Clone, PartialEq)]
pub struct AvatarProps {
Expand All @@ -37,6 +53,9 @@ pub struct AvatarProps {
#[props(default)]
pub size: AvatarImageSize,

#[props(default)]
pub shape: AvatarShape,

/// Additional attributes for the avatar element
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,
Expand All @@ -51,7 +70,7 @@ pub fn Avatar(props: AvatarProps) -> Element {
document::Link { rel: "stylesheet", href: asset!("./style.css") }

avatar::Avatar {
class: "avatar {props.size.to_class()}",
class: "avatar {props.size.to_class()} {props.shape.to_class()}",
on_load: props.on_load,
on_error: props.on_error,
on_state_change: props.on_state_change,
Expand Down
12 changes: 10 additions & 2 deletions preview/src/components/avatar/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
flex-shrink: 0;
align-items: center;
justify-content: center;
border-radius: 3.40282e+38px;
color: var(--secondary-color-4);
cursor: pointer;
font-weight: 500;
Expand Down Expand Up @@ -52,13 +51,22 @@
font-size: 1.75rem;
}

/* Avatar shape */
.avatar-circle {
border-radius: 50%;
}

.avatar-rounded {
border-radius: 8px;
}

/* State-specific styles */
.avatar[data-state="loading"] {
animation: pulse 1.5s infinite ease-in-out;
}

.avatar[data-state="empty"] {
background: var(--primary-color-2);
background: var(--primary-color-7);
}

@keyframes pulse {
Expand Down
13 changes: 13 additions & 0 deletions preview/src/components/badge/component.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "Badge",
"description": "Show notifications, counts or status information on its children",
"authors": ["Evan Almloff"],
"exclude": ["variants", "docs.md", "component.json"],
"cargoDependencies": [
{
"name": "dioxus-primitives",
"git": "https://github.com/DioxusLabs/components"
}
],
"globalAssets": ["../../../assets/dx-components-theme.css"]
}
163 changes: 163 additions & 0 deletions preview/src/components/badge/component.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use dioxus::prelude::*;

#[derive(Copy, Clone, PartialEq, Default)]
#[non_exhaustive]
pub enum BadgeVariant {
#[default]
Primary,
Secondary,
Destructive,
Outline,
}

impl BadgeVariant {
pub fn class(&self) -> &'static str {
match self {
BadgeVariant::Primary => "primary",
BadgeVariant::Secondary => "secondary",
BadgeVariant::Destructive => "destructive",
BadgeVariant::Outline => "outline",
}
}
}

/// The props for the [`Badge`] component.
#[derive(Props, Clone, PartialEq)]
pub struct BadgeProps {
#[props(default)]
pub variant: BadgeVariant,

/// Additional attributes to extend the badge element
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,

/// The children of the badge element
pub children: Element,
}

#[component]
pub fn Badge(props: BadgeProps) -> Element {
rsx! {
document::Link { rel: "stylesheet", href: asset!("./style.css") }

BadgeElement {
"padding": true,
variant: props.variant,
attributes: props.attributes,
{props.children}
}
}
}

/// The props for the [`NotifyBadge`] component.
#[derive(Props, Clone, PartialEq)]
pub struct BadgeNotifyProps {
/// Number to show in badge
pub count: u32,

/// Max count to show
#[props(default = u32::MAX)]
pub overflow_count: u32,

/// Whether to display a dot instead of count
#[props(default = false)]
pub dot: bool,

/// Whether to show badge when count is zero
#[props(default = false)]
pub show_zero: bool,

#[props(default = BadgeVariant::Destructive)]
pub variant: BadgeVariant,

/// Additional attributes to extend the badge element
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,

/// The children of the badge element
pub children: Element,
}

#[component]
pub fn NotifyBadge(props: BadgeNotifyProps) -> Element {
let text = if props.dot {
String::default()
} else if props.overflow_count < props.count {
format!("{}+", props.overflow_count)
} else {
format!("{}", props.count)
};

let add_padding = text.chars().count() > 1;

rsx! {
document::Link { rel: "stylesheet", href: asset!("./style.css") }

span {
{props.children}

if props.count > 0 || props.show_zero {
BadgeElement {
class: "badge",
"padding": if add_padding { true },
"dot": if props.dot { true },
"notify": true,
variant: props.variant,
attributes: props.attributes,
{text}
}
}
}
}
}

#[component]
fn BadgeElement(props: BadgeProps) -> Element {
rsx! {
span {
class: "badge",
"data-style": props.variant.class(),
..props.attributes,
{props.children}
}
}
}

#[component]
pub fn CardIcon() -> Element {
rsx! {
svg {
view_box: "0 0 24 24",
xmlns: "http://www.w3.org/2000/svg",
width: "24",
height: "24",
fill: "none",
stroke: "var(--secondary-color-4)",
stroke_linecap: "round",
stroke_linejoin: "round",
stroke_width: 2,
circle { cx: 8, cy: 21, r: 1 }
circle { cx: 19, cy: 21, r: 1 }
path { d: "M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12" }
}
}
}

#[component]
pub fn VerifiedIcon() -> Element {
rsx! {
svg {
view_box: "0 0 24 24",
xmlns: "http://www.w3.org/2000/svg",
width: "12",
height: "12",
fill: "none",
stroke: "var(--secondary-color-4)",
stroke_linecap: "round",
stroke_linejoin: "round",
stroke_width: 2,
path { d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" }
path { d: "m9 12 2 2 4-4" }
}
}
}
9 changes: 9 additions & 0 deletions preview/src/components/badge/docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
The Badge is a component designed to display small, distinct labels that help highlight important content or status indicators. Perfect for use cases like notifications, status labels, or categorization.

## Component Structure

```rust
Badge {
{children}
}
```
2 changes: 2 additions & 0 deletions preview/src/components/badge/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod component;
pub use component::*;
64 changes: 64 additions & 0 deletions preview/src/components/badge/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.badge-example {
display: flex;
align-items: center;
gap: 1rem;
}

.badge-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}

.badge-label {
color: var(--secondary-color-4);
font-size: 0.875rem;
}

.badge {
display: inline-flex;
min-width: 20px;
height: 20px;
align-items: center;
justify-content: center;
border-radius: 10px;
box-shadow: 0 0 0 1px var(--primary-color-2);
font-size: 12px;
gap: 4px
}

.badge[notify="true"] {
position: absolute;
transform: translate(-50%, -50%);
}

.badge[padding="true"] {
padding: 0 8px;
}

.badge[dot="true"] {
min-width: 8px;
height: 8px;
}

.badge[data-style="primary"] {
background-color: var(--secondary-color-2);
color: var(--primary-color);
}

.badge[data-style="secondary"] {
background-color: var(--primary-color-5);
color: var(--secondary-color-1);
}

.badge[data-style="outline"] {
border: 1px solid var(--primary-color-6);
background-color: var(--light, var(--primary-color)) var(--dark, var(--primary-color-3));
color: var(--secondary-color-4);
}

.badge[data-style="destructive"] {
background-color: var(--primary-error-color);
color: var(--contrast-error-color);
}
22 changes: 22 additions & 0 deletions preview/src/components/badge/variants/main/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use dioxus::prelude::*;

use super::super::component::*;

#[component]
pub fn Demo() -> Element {
rsx! {
div { class: "badge-example",

Badge { "Primary" }
Badge { variant: BadgeVariant::Secondary, "Secondary" }
Badge { variant: BadgeVariant::Destructive, "Destructive" }
Badge { variant: BadgeVariant::Outline, "Outline" }
Badge {
variant: BadgeVariant::Secondary,
style: "background-color: var(--focused-border-color)",
VerifiedIcon {}
"Verified"
}
}
}
}
Loading
Loading