Label source

Inspect and copy the reviewed source included with this Free component.

Free source · 2 files

mod.rs

// SPDX-FileCopyrightText: 2026 Proa Labs, Inc.
// SPDX-License-Identifier: (MIT OR Apache-2.0) AND MIT

//! Label component - accessible form label
//!
//! A simple styled label component that renders as a native HTML `<label>` element.
//! Based on shadcn/ui's Label component.
mod md;
use crate::tw_join;
use proa_core::{ClassList, WebContext, WebRenderSync, WriteBuf};
use proa_macros::html_sync;
/// Base styles for the label - matches shadcn/ui exactly
/// "flex items-center gap-2 text-sm leading-none font-medium select-none
///  group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50
///  peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
const LABEL_BASE: &str = tw_join!(
    "flex",
    "items-center",
    "gap-2",
    "text-sm",
    "leading-none",
    "font-medium",
    "text-foreground",
    "select-none",
    "group-data-[disabled=true]:pointer-events-none",
    "group-data-[disabled=true]:opacity-50",
    "peer-disabled:cursor-not-allowed",
    "peer-disabled:opacity-50"
);
/// Type-safe Label component.
///
/// Renders an accessible label associated with form controls.
/// Uses the native HTML `<label>` element for proper accessibility.
///
/// # Example
///
/// ```ignore
/// use proa_ui::Label;
/// use proa_macros::html_sync;
///
/// // Basic usage with for attribute
/// html_sync! {
///     <div class="flex items-center gap-2">
///         <input type="checkbox" id="terms" />
///         {Label {
///             for_id: Some("terms"),
///             text: "Accept terms and conditions",
///             ..Label::new()
///         }}
///     </div>
/// }.render(cx);
///
/// // With custom class
/// html_sync! {
///     {Label {
///         for_id: Some("email"),
///         text: "Email address",
///         class: Some("text-red-500"),
///         ..Label::new()
///     }}
/// }.render(cx);
/// ```
pub struct Label {
    /// The id of the form element this label is for
    pub for_id: Option<&'static str>,
    /// The text content of the label
    pub text: &'static str,
    /// Additional CSS classes
    pub class: Option<&'static str>,
    /// Custom id for the label element
    pub id: Option<&'static str>,
}
impl Label {
    /// Create a new label with default settings
    pub const fn new() -> Self {
        Self {
            for_id: None,
            text: "",
            class: None,
            id: None,
        }
    }
    /// Create a new label with text
    pub const fn with_text(text: &'static str) -> Self {
        Self {
            for_id: None,
            text,
            class: None,
            id: None,
        }
    }
}
impl Default for Label {
    fn default() -> Self {
        Self::new()
    }
}
/// Get the label classes
#[inline(always)]
pub fn label_classes() -> ClassList<2> {
    ClassList::new().add(LABEL_BASE)
}
impl<B: WriteBuf, L: ::proa_core::DataLoader> WebRenderSync<L, B> for Label {
    #[inline(always)]
    fn render(
        self,
        cx: &mut WebContext<L, B>,
    ) -> Result<(), proa_core::shared::write_buf::WriteError> {
        let classes = label_classes().add_opt(self.class);
        html_sync! {
            <label data-label class={classes} for={self.for_id} id={self.id} data-slot="label">
                {self.text}
            </label>
        }
        .render(cx)
    }
}
pub use Label as LabelComponent;
#[cfg(test)]
mod tests {
    use super::*;
    use proa_core::ctx::Ctx;
    #[test]
    fn label_renders_with_defaults() {
        let mut out = Vec::new();
        let mut cx = Ctx::with_buffer(&mut out);
        Label {
            text: "Email",
            ..Label::new()
        }
        .render(&mut cx)
        .unwrap();
        let html = String::from_utf8(out).unwrap();
        assert!(html.contains("<label"));
        assert!(html.contains("Email"));
        assert!(html.contains("data-slot=\"label\""));
        assert!(html.contains("text-sm"));
        assert!(html.contains("font-medium"));
    }
    #[test]
    fn label_renders_with_for_attribute() {
        let mut out = Vec::new();
        let mut cx = Ctx::with_buffer(&mut out);
        Label {
            for_id: Some("my-input"),
            text: "Username",
            ..Label::new()
        }
        .render(&mut cx)
        .unwrap();
        let html = String::from_utf8(out).unwrap();
        assert!(html.contains("for=\"my-input\""));
        assert!(html.contains("Username"));
    }
    #[test]
    fn label_renders_with_custom_class() {
        let mut out = Vec::new();
        let mut cx = Ctx::with_buffer(&mut out);
        Label {
            text: "Custom",
            class: Some("text-red-500"),
            ..Label::new()
        }
        .render(&mut cx)
        .unwrap();
        let html = String::from_utf8(out).unwrap();
        assert!(html.contains("text-red-500"));
    }
    #[test]
    fn label_renders_with_id() {
        let mut out = Vec::new();
        let mut cx = Ctx::with_buffer(&mut out);
        Label {
            id: Some("my-label"),
            text: "Test",
            ..Label::new()
        }
        .render(&mut cx)
        .unwrap();
        let html = String::from_utf8(out).unwrap();
        assert!(html.contains("id=\"my-label\""));
    }
    #[test]
    fn label_with_text_constructor() {
        let mut out = Vec::new();
        let mut cx = Ctx::with_buffer(&mut out);
        Label::with_text("Quick label").render(&mut cx).unwrap();
        let html = String::from_utf8(out).unwrap();
        assert!(html.contains("Quick label"));
    }
    #[test]
    fn label_size_is_reasonable() {
        assert!(std::mem::size_of::<Label>() < 128);
        const _LABEL: Label = Label::new();
    }
}

Copy this source with the Free Proa UI components it imports; those component files remain available from their own source pages.

Licensed under MIT OR Apache-2.0. Third-party notices remain attached to the installed payload.

Open Markdown
FreeLabel

Accessible form labels.

Install with the Proa CLI
proa ui add label

Installs the reviewed component source, dependencies, shared support files, and required legal notices.

CLI and registry setup
mod.rs
// SPDX-FileCopyrightText: 2026 Proa Labs, Inc.
// SPDX-License-Identifier: (MIT OR Apache-2.0) AND MIT

//! Label component - accessible form label
//!
//! A simple styled label component that renders as a native HTML `<label>` element.
//! Based on shadcn/ui's Label component.
mod md;
use crate::tw_join;
use proa_core::{ClassList, WebContext, WebRenderSync, WriteBuf};
use proa_macros::html_sync;
/// Base styles for the label - matches shadcn/ui exactly
/// "flex items-center gap-2 text-sm leading-none font-medium select-none
///  group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50
///  peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
const LABEL_BASE: &str = tw_join!(
    "flex",
    "items-center",
    "gap-2",
    "text-sm",
    "leading-none",
    "font-medium",

Search

Type at least 2 characters

Customize

Make it yours

Palette

Radius

Overview
Components
Settings

Build your own

Themed Proa UI surface

Preview
Components52
RecipesTyped
customer-portal