Components
Label
An accessible label, typically paired with Morphos's Field. Purely presentational.
Installation
npx kosmesis add labelpnpm dlx kosmesis add labelyarn dlx kosmesis add labelbunx kosmesis add labelCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { cn } from "@/lib/utils";export interface LabelProps { htmlFor?: string; class?: string; id?: string; children?: Children;}// Pairs with Morphos's `Field` (`field.fieldId` as `htmlFor`) but works standalone too.@Component()export class Label extends StatelessComponent<LabelProps> { render() { const { htmlFor, class: cls, id, children } = this.props; return ( <label id={id} htmlFor={htmlFor} class={cn( "flex select-none items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-disabled:pointer-events-none group-data-disabled:opacity-50", cls, )} > {children} </label> ); }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";class LabelStyles extends Stylesheet { $root = this.css({ display: "flex", userSelect: "none", alignItems: "center", gap: "0.5rem", fontSize: "0.875rem", fontWeight: 500, lineHeight: 1, }) // `&` can appear anywhere in the compound selector, not just as a prefix. .on("[data-kosmesis-peer]:disabled ~ &", { cursor: "not-allowed", opacity: 0.5 }) .on("[data-disabled] &", { pointerEvents: "none", opacity: 0.5 });}export interface LabelProps { htmlFor?: string; class?: string; id?: string; children?: Children;}// Pairs with Morphos's `Field` (`field.fieldId` as `htmlFor`) but works standalone too.@Component()export class Label extends StatelessComponent<LabelProps> { @Styled(LabelStyles) $s!: LabelStyles; render() { const { htmlFor, class: cls, id, children } = this.props; return ( <label id={id} htmlFor={htmlFor} class={cx(this.$s.$root, cls)}> {children} </label> ); }}Examples
Usage
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
<div class="flex flex-col gap-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="[email protected]" />
</div>Pairing with Field
import { Field, FieldControl, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
@Component()
class MyForm extends StatefulComponent {
// A second, separately-tracked instance — the same "instantiate once, pass to every part"
// pattern every Morphos compound component uses. The JSX-mounted <Field> below produces the
// actual container element; `this.field` is what FieldLabel/Control/Description read from.
@State() field = new Field();
render() {
return (
<Field>
<FieldLabel field={this.field}>Email</FieldLabel>
<FieldControl field={this.field}>
<Input id={this.field.fieldId} />
</FieldControl>
<FieldDescription field={this.field}>We'll never share your email.</FieldDescription>
</Field>
);
}
}Label itself doesn't require a Field — pass htmlFor pointing at any input's id for a
plain standalone label.
Props
| Prop | Type | Default |
|---|---|---|
htmlFor | string | — |