Choice & selection

AppChoiceCard

A selectable card — icon, title and description — for picking one option from a small, visible set.

<app-choice-card name="struct" value="flat" icon="building-2" title="Flat roof" description="Single-level rooftop" />

A choice card is a radio dressed as a card — an icon, a title, and a line of description — so the user compares a small set of options side by side and picks one. It is the rich cousin of a radio list, not a dropdown. <app-choice-card> is the one way to render a selectable card; never hand-roll a clickable .card.

Its look comes entirely from the shared @webority/theme, so the Razor <app-choice-card> and the React <AppChoiceCard> render identically — a card is a card on every Webority surface.

Playground

Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the card above it.

<app-choice-card name="struct" value="flat" icon="building-2" title="Flat roof" description="Single-level rooftop" />

AppIcon cards

The common layout — an icon, a title, and a short description per card. A shared name makes the group mutually exclusive.

A structure picker
Each card is a radio; selecting one clears the rest. Keep the group to a handful of options.
Show code
<app-choice-card name="struct" value="flat" checked="true" icon="building-2" title="Flat roof" description="Single-level rooftop" />
<app-choice-card name="struct" value="pitched" icon="house" title="Pitched roof" description="Sloped / gabled roof" />
<app-choice-card name="struct" value="tower" icon="factory" title="Tower" description="Tall vertical structure" />
Radio, not dropdownCards keep every option visible so the user weighs them at a glance — the reason to choose them over a select. That only works for a small set; past 5–6 options the visible-all advantage turns into scroll fatigue and a dropdown is kinder.

Image cards

Pass image instead of icon for an image-forward card — swatches, thumbnails, plan artwork. The image replaces the icon slot.

Image-forward cards
image renders a media band above the title and description.
Show code
<app-choice-card name="swatch" value="blue" checked="true" image="/media/plan-blue.png" title="Royal blue" description="Primary brand" />
<app-choice-card name="swatch" value="green" image="/media/plan-green.png" title="Green" description="Success tone" />
<app-choice-card name="swatch" value="amber" image="/media/plan-amber.png" title="Amber" description="Warning tone" />

Selected state

The selected card carries a check marker and the theme's selected treatment — driven entirely by the checked state.

One card selected
checked marks the active card; the shared name moves the selection.
Show code
<app-choice-card name="struct" value="pitched" checked="true" icon="house" title="Pitched roof" description="Sloped / gabled roof" />

When to use

Use it when

  • Picking one of a small set (2–5) of exclusive options, each worth an icon and a line of description.
  • A structure, plan, or type picker where seeing all options side by side helps the decision.
  • An onboarding or setup choice that benefits from richer visuals than a plain radio list.

Reach for something else when

  • There are many options (6+). → AppSelect
  • The options are plain and need no icon or description. → AppRadio
  • It is a compact filter or tag toggle. → AppChoiceChip
  • It just displays a chosen value. → AppChip

Best practices

Do
A short title and a one-line description. The card reads instantly.
Don't
A paragraph stuffed into a card. If it needs this much text, it needs a different control.
Do
One visual style across the group — all icon cards, or all image cards.
Don't
Mixing an icon card with an image card in one group makes the set feel broken.

Every option

The whole surface of the component, one cell per value — content modes, selected state, single- vs multi-select grouping, and the nearest equivalent to a disabled card.

content mode — icon, iconNode, image, custom children, none

icon="building-2"
(no icon-node attribute — Razor has no custom-node slot; use inner content below for arbitrary markup)
image="..." — overrides icon
(content) — overrides title/description
(none) — no icon or image wrapper rendered

selected state

checked="false"
checked="true"

single vs multi grouping

radio group — one selected at a time (default)
multiple="true" — checkbox group, several selected at once

disabled — real on Razor, visual-only on React (see callout)

disabled="true" — no bound Disabled property, so it passes through onto the <input>
class="opacity-50 pe-none" — visual-only styling, stacks with disabled
React ↔ Razor mismatch: disabledAppChoiceCard has no dedicated disabled prop/attribute on either surface, but the fallback path differs. In Razor, an unclaimed attribute like disabled="true" is harvested and placed on the underlying <input> — so it works as a real, functional disabled input. In React, AppChoiceCard's ...rest spreads onto the <label> instead of the <input>, so a bare disabled prop has no effect there — the nearest React equivalent is a visual-only utility className (opacity-50 pe-none). Reported as a genuine surface difference, not fixed here.

Attributes

AttributeTypeDefaultDescription
namestring—Groups the cards so selection is mutually exclusive (the radio group name).
valuestring—The value this card posts when selected.
checkedboolfalseWhether this card starts selected.
multipleboolfalseCheckbox (multi-select) instead of radio.
iconstring—Bootstrap Icons glyph name for the card icon.
icon-sizeintby sizeIcon glyph size in pixels. Unset, it follows size: 16 (sm), 18 (md), 22 (lg).
imagestring—Image URL — renders an image-forward card (overrides icon).
image-altstring""Alt text for the image.
titlestring—The card title.
descriptionstring—A one-line description under the title.
(content)markup—Inner markup for a fully custom body template — overrides title/description.
check-iconstringcheckGlyph for the selected-state check marker.
check-sizeint12Check-glyph size in px (React checkSize).
hide-checkboolfalseRender no selected tick (React hideCheck). Selection reads from the border and fill alone, and the card's top and bottom padding tightens.
sizesm | md | lgmdCard size. Padding, gap, icon disc, title and description type, and the tick position step together. An unknown value throws.
layoutinline | stackedinlineinline puts the icon beside the text. stacked puts the icon on its own line, with the title and description below it. An unknown value throws.