Toggle Group
Single- or multiple-selection toggle group, wrapping Morphos's ToggleGroup primitive.
Installation
npx kosmesis add toggle-grouppnpm dlx kosmesis add toggle-groupyarn dlx kosmesis add toggle-groupbunx kosmesis add toggle-groupInstall the following dependencies:
npm install @morphos/inputs class-variance-authoritypnpm add @morphos/inputs class-variance-authorityyarn add @morphos/inputs class-variance-authoritybun add @morphos/inputs class-variance-authorityThis component builds on other Kosmesis components — install these first (via kosmesis add or this same manual process on their own pages): toggle.
Copy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import { ToggleGroup as MorphosToggleGroup, ToggleGroupItem as MorphosToggleGroupItem, type ToggleGroupItemProps as MorphosToggleGroupItemProps } from "@morphos/inputs";import { toggleVariants } from "./toggle";import type { VariantProps } from "class-variance-authority";import { cn } from "@/lib/utils";/** * Extends (not wraps) Morphos's `ToggleGroup` so `new ToggleGroup({ type: "single" })` still * yields a real instance with `.isPressed()`/`.toggle()` — what `ToggleGroupItem` needs via its * `group` prop. */@Component()export class ToggleGroup extends MorphosToggleGroup { render() { return ( <div id={this.id} role="group" class={cn("flex w-fit items-center gap-1 rounded-md", this.class)} aria-label={this["aria-label"]} aria-labelledby={this["aria-labelledby"]} aria-disabled={this.disabled ? ("true" as const) : undefined} data-type={this.type} data-orientation={this.orientation} data-disabled={this.disabled ? "" : undefined} > {this.children} </div> ); }}/** * Unlike shadcn/ui's React version, `variant`/`size` aren't inherited from the group via context * (Morphos/PraxisJS compound components pass explicit props instead) — pass the same `variant` * and `size` to `ToggleGroup` and every `ToggleGroupItem` to keep them visually consistent. */export interface ToggleGroupItemProps extends MorphosToggleGroupItemProps, VariantProps<typeof toggleVariants> {}@Component()export class ToggleGroupItem extends StatelessComponent<ToggleGroupItemProps> { render() { const { variant, size, class: cls, ...rest } = this.props; return <MorphosToggleGroupItem class={cn(toggleVariants({ variant, size }), cls)} {...rest} />; }}Install the following dependencies:
npm install @morphos/inputs @praxisjs/csspnpm add @morphos/inputs @praxisjs/cssyarn add @morphos/inputs @praxisjs/cssbun add @morphos/inputs @praxisjs/cssThis component builds on other Kosmesis components — install these first (via kosmesis add or this same manual process on their own pages): toggle.
Copy 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 { ToggleGroup as MorphosToggleGroup, ToggleGroupItem as MorphosToggleGroupItem, type ToggleGroupItemProps as MorphosToggleGroupItemProps } from "@morphos/inputs";import { ToggleStyles, type ToggleSize, type ToggleVariant } from "./toggle";class ToggleGroupRootStyles extends Stylesheet { $root = this.css({ display: "flex", width: "fit-content", alignItems: "center", gap: "0.25rem", borderRadius: "0.375rem" });}/** * Extends (not wraps) Morphos's `ToggleGroup` so `new ToggleGroup({ type: "single" })` still * yields a real instance with `.isPressed()`/`.toggle()` — what `ToggleGroupItem` needs via its * `group` prop. */@Component()export class ToggleGroup extends MorphosToggleGroup { @Styled(ToggleGroupRootStyles) $s!: ToggleGroupRootStyles; render() { return ( <div id={this.id} role="group" class={cx(this.$s.$root, this.class)} aria-label={this["aria-label"]} aria-labelledby={this["aria-labelledby"]} aria-disabled={this.disabled ? ("true" as const) : undefined} data-type={this.type} data-orientation={this.orientation} data-disabled={this.disabled ? "" : undefined} > {this.children} </div> ); }}/** * Unlike shadcn/ui's React version, `variant`/`size` aren't inherited from the group via context * (Morphos/PraxisJS compound components pass explicit props instead) — pass the same `variant` * and `size` to `ToggleGroup` and every `ToggleGroupItem` to keep them visually consistent. */export interface ToggleGroupItemProps extends MorphosToggleGroupItemProps { variant?: ToggleVariant; size?: ToggleSize;}@Component()export class ToggleGroupItem extends StatelessComponent<ToggleGroupItemProps> { @Styled(ToggleStyles) $s!: ToggleStyles; render() { const { variant = "default", size = "default", class: cls, ...rest } = this.props; const variants: Record<ToggleVariant, string> = { default: this.$s.$variantDefault, outline: this.$s.$variantOutline }; const sizes: Record<ToggleSize, string> = { default: this.$s.$sizeDefault, sm: this.$s.$sizeSm, lg: this.$s.$sizeLg }; return <MorphosToggleGroupItem class={cx(this.$s.$root, variants[variant], sizes[size], cls)} {...rest} />; }}Examples
Usage
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
@Component()
class TextAlignPicker extends StatefulComponent {
@State() group = new ToggleGroup({ type: "single", defaultValue: "left" });
render() {
return (
<ToggleGroup type="single" defaultValue="left" variant="outline">
<ToggleGroupItem group={this.group} value="left" variant="outline">Left</ToggleGroupItem>
<ToggleGroupItem group={this.group} value="center" variant="outline">Center</ToggleGroupItem>
<ToggleGroupItem group={this.group} value="right" variant="outline">Right</ToggleGroupItem>
</ToggleGroup>
);
}
}Unlike shadcn/ui's React version, variant/size aren't inherited from the group via context —
pass the same variant/size to ToggleGroup and every ToggleGroupItem to keep them visually
consistent.
Props
ToggleGroup
| Prop | Type | Default |
|---|---|---|
type | "single" | "multiple" | — required |
value | string | string[] | — |
defaultValue | string | string[] | — |
disabled | boolean | false |
orientation | "horizontal" | "vertical" | "horizontal" |
onValueChange | (value: string | string[]) => void | — |
aria-label | string | — |
aria-labelledby | string | — |
ToggleGroup itself does not accept variant/size — despite the Usage example above passing
variant="outline" to it, that prop has no effect on the group; only ToggleGroupItem renders
variant/size styling, so it must be set per-item.
ToggleGroupItem
| Prop | Type | Default |
|---|---|---|
group | ToggleGroup | — required |
value | string | — required |
disabled | boolean | — |
variant | "default" | "outline" | "default" |
size | "default" | "sm" | "lg" | "default" |