Comparison
A two-column or multi-column comparison table for pricing tiers, feature breakdowns, or before/after comparisons. Each column is defined with an arc-comparison-column child element.
<arc-comparison> Overview
Comparison renders a structured grid of feature rows and value columns, ideal for pricing tables, plan comparisons, and feature matrices. The parent arc-comparison element accepts a JSON array of feature labels, while each slotted arc-comparison-column child provides a heading and a matching JSON array of values.
Boolean values are rendered automatically as check marks or crosses — pass "true" or "false" as string values and the component renders accessible SVG icons in success/ghost colors. Any other string value is displayed as-is, making it flexible for mixed comparison data (e.g. "5 GB", "Unlimited", "true").
The highlight attribute on a column adds a subtle accent background to both the header and all cells in that column, drawing the user's eye to the recommended or featured tier. The entire component uses CSS Grid for automatic column sizing and includes row hover states for scanability.
Guidelines
When to use
- Use for pricing tables, feature matrices, and plan comparisons
- Keep feature labels concise — long labels compress the value columns
- Highlight at most one column (the recommended tier) to guide user attention
- Use boolean values ("true"/"false") for feature presence to get automatic check/cross icons
- Ensure the features array and each column's values array have the same length
When not to use
- Do not use for arbitrary data tables — use data-table instead for sortable/filterable data
- Do not add more than 4-5 columns — the grid becomes too compressed on smaller screens
- Do not mix boolean and text values in the same row — pick one format per feature
- Do not forget to provide the features prop — without it, no rows will render
Features
- CSS Grid layout with automatic column count based on slotted children
- JSON-driven features and values — no complex DOM nesting required
- Boolean rendering: "true" becomes a green check, "false" becomes a ghost X
- Column highlighting with accent background for featured/recommended tiers
- Row hover states for easy horizontal scanning
- Accessible table roles (table, row, rowheader, columnheader, cell)
- CSS parts for deep customization: table, header, cell, feature
- Respects `prefers-reduced-motion` for transitions
Preview
Usage
Comparison is in the marketing domain group, so it is
deliberately absent from the default @arclux/arc-ui barrel. Import it from
@arclux/arc-ui/marketing, or from its own subpath
@arclux/arc-ui/comparison. Everything else — the element, the CSS, the
framework wrappers, the support it gets — is unchanged.
<arc-comparison features='["Storage","Bandwidth","Custom Domain","Priority Support"]'>
<arc-comparison-column
heading="Free"
values='["5 GB","10 GB","false","false"]'>
</arc-comparison-column>
<arc-comparison-column
heading="Pro"
highlight
values='["100 GB","Unlimited","true","true"]'>
</arc-comparison-column>
<arc-comparison-column
heading="Enterprise"
values='["Unlimited","Unlimited","true","true"]'>
</arc-comparison-column>
</arc-comparison> import { Comparison, ComparisonColumn } from '@arclux/arc-ui-react';
function PricingTable() {
const features = JSON.stringify(['Storage', 'Bandwidth', 'Custom Domain', 'Support']);
return (
<Comparison features={features}>
<ComparisonColumn heading="Free" values='["5 GB","10 GB","false","false"]' />
<ComparisonColumn heading="Pro" highlight values='["100 GB","Unlimited","true","true"]' />
<ComparisonColumn heading="Enterprise" values='["Unlimited","Unlimited","true","true"]' />
</Comparison>
);
} <script setup>
import { Comparison, ComparisonColumn } from '@arclux/arc-ui-vue';
const features = JSON.stringify(['Storage', 'Bandwidth', 'Custom Domain', 'Support']);
</script>
<template>
<Comparison :features="features">
<ComparisonColumn heading="Free" values='["5 GB","10 GB","false","false"]' />
<ComparisonColumn heading="Pro" highlight values='["100 GB","Unlimited","true","true"]' />
<ComparisonColumn heading="Enterprise" values='["Unlimited","Unlimited","true","true"]' />
</Comparison>
</template> <script>
import { Comparison, ComparisonColumn } from '@arclux/arc-ui-svelte';
const features = JSON.stringify(['Storage', 'Bandwidth', 'Custom Domain', 'Support']);
</script>
<Comparison {features}>
<ComparisonColumn heading="Free" values='["5 GB","10 GB","false","false"]' />
<ComparisonColumn heading="Pro" highlight values='["100 GB","Unlimited","true","true"]' />
<ComparisonColumn heading="Enterprise" values='["Unlimited","Unlimited","true","true"]' />
</Comparison> import { Component } from '@angular/core';
import { Comparison, ComparisonColumn } from '@arclux/arc-ui-angular';
@Component({
imports: [Comparison, ComparisonColumn],
template: `
<arc-comparison [features]="features">
<arc-comparison-column heading="Free" values='["5 GB","10 GB","false","false"]' />
<arc-comparison-column heading="Pro" highlight values='["100 GB","Unlimited","true","true"]' />
<arc-comparison-column heading="Enterprise" values='["Unlimited","Unlimited","true","true"]' />
</arc-comparison>
`,
})
export class PricingComponent {
features = JSON.stringify(['Storage', 'Bandwidth', 'Custom Domain', 'Support']);
} import { Comparison, ComparisonColumn } from '@arclux/arc-ui-solid';
const features = JSON.stringify(['Storage', 'Bandwidth', 'Custom Domain', 'Support']);
<Comparison features={features}>
<ComparisonColumn heading="Free" values='["5 GB","10 GB","false","false"]' />
<ComparisonColumn heading="Pro" highlight values='["100 GB","Unlimited","true","true"]' />
<ComparisonColumn heading="Enterprise" values='["Unlimited","Unlimited","true","true"]' />
</Comparison> import { Comparison, ComparisonColumn } from '@arclux/arc-ui-preact';
const features = JSON.stringify(['Storage', 'Bandwidth', 'Custom Domain', 'Support']);
<Comparison features={features}>
<ComparisonColumn heading="Free" values='["5 GB","10 GB","false","false"]' />
<ComparisonColumn heading="Pro" highlight values='["100 GB","Unlimited","true","true"]' />
<ComparisonColumn heading="Enterprise" values='["Unlimited","Unlimited","true","true"]' />
</Comparison> API
-
featuresstring[][] - Feature label strings, one row each. Settable as a property, or as a JSON array in markup:
features='["Storage","Bandwidth"]'. A malformed value falls back to an empty list rather than throwing.
ComparisonColumn
<arc-comparison-column> Data-holder child element that defines a single column in the comparison grid. Renders nothing visible — it provides heading, highlight, and values data to the parent.
-
headingstring'' - Column header text displayed at the top of this column (e.g., "Free", "Pro").
-
highlightbooleanfalse - When true, adds an accent background to the header and all cells in this column.
-
valuesstring[][] - Values matching the features order. Settable as a property, or as a JSON array in markup. Use "true"/"false" for check/cross icons, or any string for text values.
See Also
- Data Grid A spreadsheet-grade grid for working with tabular data: inline cell editing, multi-column sorting, pinned columns, row selection, and virtualized rendering. Columns are defined as a JavaScript array, and the grid implements the full WAI-ARIA grid keyboard pattern with a single tab stop.
- Card Content container with subtle border styling and hover effects. Links the entire card surface when an href is provided, creating a seamless clickable area with an animated gradient border.
- Feature Card Card with icon, heading, description, and animated hover effects.