Data & display

AppCompareTable

A feature-comparison table — one row per capability, one column per option.

<app-compare-table><app-compare-column … /><app-compare-row … /></app-compare-table>

<app-compare-table> lays capabilities against options so a reader can settle a choice by scanning — the plan matrix under a pricing page, an “us vs them” table on a marketing site, a two-approach comparison in a doc.

It is an editorial table, not a data grid: the rows are authored, there is no sorting or paging, and the point is the comparison rather than the records.

Playground

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

Plan comparison
FreeProEnterprise
Reports per month3UnlimitedUnlimited
Storage1 GB50 GBCustom
Single sign-on--
<app-compare-table caption="Plan comparison">
    <app-compare-column label="" />
    <app-compare-column label="Free" />
    <app-compare-column label="Pro" highlight="true" />
    <app-compare-column label="Enterprise" />
    <app-compare-row label="Reports per month" values="3,Unlimited,Unlimited" />
    <app-compare-row label="Storage" values="1 GB,50 GB,Custom" />
    <app-compare-row label="Single sign-on" values="false,false,true" />
</app-compare-table>
highlight tints only the matching columnSetting highlighted column to a column beyond the current column count is simply out of range — the table renders normally with no highlight, the same as picking "none".

Basic

The first column is the capability-name column and normally has an empty label. Each row's values line up with the columns after it.

A plan matrix
A value of true renders a tick, false a dash. Anything else renders as text.
Plan comparison
FreePro
Reports per month3Unlimited
Sites125
Report revisions-
Single sign-on--
Priority support-
Show code
<app-compare-table caption="Plan comparison">
    <app-compare-column label="" />
    <app-compare-column label="Free" />
    <app-compare-column label="Pro" />
    <app-compare-row label="Reports per month" values="3,Unlimited" />
    <app-compare-row label="Sites" values="1,25" />
    <app-compare-row label="Report revisions" values="false,true" />
    <app-compare-row label="Single sign-on" values="false,false" />
    <app-compare-row label="Priority support" values="false,true" />
</app-compare-table>
caption is not decorationIt is rendered visually hidden and read by a screen reader before the table, which is how a non-sighted reader knows what is being compared. Without it the table announces as an unlabelled grid of ticks.

Highlighting a column

Mark the recommended option and its column is tinted throughout — header and cells. The reader's eye lands on it with no legend to read.

Recommending a tier
Highlight exactly one column. Two highlighted columns highlight nothing.
Plan comparison
FreeProEnterprise
Reports per month3UnlimitedUnlimited
Sites125Unlimited
Report revisions-
Single sign-on--
Priority support-
Show code
<app-compare-column label="Pro" highlight="true" />

Mixed values

A column can mix booleans with text, so “3 reports” and “not included” sit in the same table without a second layout.

Numbers, text and booleans
The tick and the dash differ in shape as well as colour, so the two states read for someone who cannot distinguish green from grey.
Mixed value types
FreeProEnterprise
Reports per month3UnlimitedUnlimited
Storage1 GB50 GBCustom
Single sign-on--
Show code
<app-compare-row label="Storage" values="1 GB,50 GB,Custom" />
<app-compare-row label="Single sign-on" values="false,false,true" />
values is comma-separatedA Razor attribute cannot carry a collection, so the values are split on commas — a value that itself contains a comma needs the React component or a wider column label instead.

When to use

Use it when

  • A reader is choosing between two to four options on the same criteria.
  • The rows are authored capabilities, not records from a query.
  • Seeing the options side by side is what makes the choice obvious.

Reach for something else when

  • The rows are records to sort, filter or page. → app-data-table
  • You are showing the tiers themselves with prices and CTAs. → app-pricing-card
  • It is a list of facts about one thing. → app-info-list

Best practices

Do
Good example
FreePro
Single sign-on-
Every row appears for every column, so the reader can read across. The row label names the capability in the customer's words.
Don't
Bad example
FreePro
SSO / SAML2 IdP federation—Y
Two highlighted columns highlight neither; internal jargon in the row label; and hand-typed “—”/“Y” instead of booleans loses the tick's shape cue.

Every option

The whole surface of the component, one cell per value — every cell-value type, every highlight combination, and the shapes a normal example doesn't cover.

cell value — what a row's values can hold

true → tick
true value
Plan
Feature
false → dash
false value
Plan
Feature-
"text" → renders as-is
text value
Plan
Storage50 GB
"" → empty cell
empty string value
Plan
Feature
a node value — React-only; Razor reaches the same outcome with plain text
text in place of a node
Plan
Uptime SLA99.9%

column highlight

(default) no column highlighted
no highlight
FreePro
Single sign-on-
app-compare-column highlight="true" — one tinted column
single highlight
FreePro
Single sign-on-
two columns highlighted — neither reads as recommended
double highlight
FreePro
Single sign-on-

caption

caption set — visually hidden, read by screen readers
Plan comparison
Plan
Feature
caption omitted — no <caption> element
Plan
Feature

content length

long row label wraps within the row-header column
long row label
FreePro
Single sign-on with SAML2 and SCIM-based automatic user provisioning-
long cell value wraps within its column
long cell value
FreePro
SupportCommunity forum only best-effortDedicated 24×7 phone and email support

row grouping — not supported

No section/group rows in either surfacerows is a flat list — there is no group/section field on either the React prop or the <app-compare-row> tag helper. The nearest equivalent is a label-only row with blank values as a visual divider, shown below; for a genuinely sectioned comparison, render two adjacent <app-compare-table>s instead.
blank-value row as a section divider — values=","
section divider workaround
FreePro
Core
Reports per month3Unlimited
Collaboration
Single sign-on-

class

class="pricing-table" — appended to the base compare-table class
class
Plan
Feature

Attributes

AttributeTypeDefaultDescription
captionstring—Visually hidden description of what is being compared.

<app-compare-column> takes label and highlight. <app-compare-row> takes label and comma-separated values.