rc-list
Shared-column list layout with standard and segmented appearances, optional leading and trailing content, and native-backed selection.
- Package
@rcarls/rc-list- Element
<rc-list, rc-list-item>- Native dependency
- Author-owned radio or checkbox controls in selecting lists
- State model
- Native checked/disabled state mirrored to list items
- Main events
- None
Installation
- npm
- Yarn
npm install @rcarls/rc-list
yarn add @rcarls/rc-list
import '@rcarls/rc-list/define';
Live demo
Shared columns
rc-list owns leading, content, and trailing grid columns. Each direct
rc-list-item participates in them through CSS subgrid, so content stays
aligned even when leading visuals or trailing actions have different sizes.
If no visible row uses an optional slot, the corresponding column and gap
collapse across the whole list.
Mark an icon in the leading slot with data-rc-list-leading when the active
theme should apply its standard icon size and alignment. Other leading media
such as images, avatars, and selection controls retain their authored geometry.
<rc-list aria-label="Recent recipes">
<rc-list-item>
<span slot="leading" data-rc-list-leading aria-hidden="true">★</span>
Apple pie
<span slot="trailing">42 min</span>
</rc-list-item>
</rc-list>
Primary content truncates to one line with an ellipsis by default. Set
--rc-list-item-content-white-space: normal on a list or item for deliberate
multi-line rows.
Adapt region placement
The shared column sizes and each item's leading, content, and trailing placements are exposed as a coordinated CSS custom-property contract. Use those tokens when a container query should rearrange the same regions without changing source order, focus behavior, or semantics:
.list-region {
container-type: inline-size;
}
@container (max-width: 24rem) {
.list-region rc-list {
--rc-list-trailing-size: 0;
--rc-list-trailing-gap: 0;
--rc-list-item-grid-template-rows: auto auto;
--rc-list-item-row-gap: 0.25rem;
--rc-list-item-leading-grid-row: 1 / -1;
--rc-list-item-content-grid-row: 1;
--rc-list-item-trailing-grid-column: content-start / content-end;
--rc-list-item-trailing-grid-row: 2;
--rc-list-item-trailing-justify-self: start;
}
}
Keep the named leading-*, content-*, and trailing-* column lines in
placement values. They are the stable coordination points supplied by
rc-list's shared subgrid.
Variants
variant="standard" is the default continuous list. variant="segmented"
creates a grouped set of discrete rows; themes use the item position assigned
by the list to shape first, middle, last, and only rows.
Native selection
Use selection="single" with one direct radio per item, or
selection="multiple" with one direct checkbox per item. The native input is
the source of truth for checked, disabled, form, reset, and accessibility
behavior. The component mirrors native state to the row and makes the otherwise
non-interactive row surface activate its input. Independent links, buttons,
inputs, selects, and textareas keep their own behavior. Radios in a
single-selection list should share a name, exactly as they would without the
custom element enhancement.
<rc-list variant="segmented" selection="single" aria-label="Sort recipes">
<rc-list-item>
<input slot="leading" type="radio" name="sort" value="recent" checked />
Recently updated
</rc-list-item>
<rc-list-item>
<input slot="leading" type="radio" name="sort" value="title" />
Recipe title
</rc-list-item>
</rc-list>
Programmatic writes to selected, disabled, and interactive are silent.
In a selecting list, the next native change synchronizes those presentation
states from the input again.
Action targets
For a row whose primary action is an anchor or button rather than its selection
input, set interactive and point action-target at that same-root native
control. A plain primary click on otherwise non-interactive row content invokes
the target. Nested links, buttons, form controls, editable content, and
modifier-qualified or non-primary clicks retain their own behavior.
<rc-list aria-label="Theme settings">
<rc-list-item interactive action-target="open-theme">
<span slot="leading" aria-hidden="true">◐</span>
Theme
<button id="open-theme" type="button" slot="trailing">Choose</button>
</rc-list-item>
</rc-list>
The target remains its own keyboard tab stop. Delegation extends pointer reach without creating a second interactive role on the row.
Scope
The package intentionally does not implement drag-and-drop reordering, swipe-to-reveal actions, virtualization, infinite loading, or pull-to-refresh. Those behaviors have distinct data, focus, scrolling, and platform contracts and can compose with list rows when their APIs are defined.
API
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
variant | variant | RCListVariant | 'standard' | Appearance hint. |
selection | selection | RCListSelection | 'none' | Native selection coordination mode. |
role | JS property only | string | 'list' | No description provided. |
Methods
No public methods are documented in the custom elements manifest.
Events
No custom events are documented in the custom elements manifest.
Slots
| Name | Description |
|---|---|
(default) | Direct `rc-list-item` children. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-list-padding-inline | 0 | Shared inline content padding. |
--rc-list-padding-block | 0 | List block padding. |
--rc-list-leading-size | minmax(0, max-content) | Shared leading column size when any visible item has leading content. |
--rc-list-leading-gap | 1rem | Gap after the leading column. |
--rc-list-trailing-size | minmax(0, max-content) | Shared trailing column size when any visible item has trailing content. |
--rc-list-trailing-gap | 1rem | Gap before the trailing column. |
--rc-list-row-gap | 0 | Gap between rows. |
CSS Parts
| Part | Description |
|---|---|
list | Shared list grid. |
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
selected | selected | boolean | false | Presentational selected state. Host writes are silent. |
disabled | disabled | boolean | false | Presentational disabled state. Host writes are silent. |
interactive | interactive | boolean | false | Enables row interaction styling. |
actionTarget | action-target | string | '' | ID of a same-root anchor or button that receives forwarded surface clicks — the same contract as `rc-card`'s `action-target`. Checked before the native radio/checkbox fallback, so a row can combine a selection input with its own `action-target` if it ever needs to (uncommon, but not fought against). |
role | JS property only | string | 'listitem' | No description provided. |
Methods
No public methods are documented in the custom elements manifest.
Events
No custom events are documented in the custom elements manifest.
Slots
| Name | Description |
|---|---|
leading | Optional leading visual or native selection control. Add `data-rc-list-leading` when a theme should apply its standard leading-icon geometry. |
(default) | Primary row content. It truncates to one line by default. |
trailing | Optional trailing metadata or action. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-list-item-min-block-size | 3rem | Minimum rendered row height. |
--rc-list-item-padding-block | 0.5rem | Row block padding. |
--rc-list-item-color | CanvasText | Row foreground color. |
--rc-list-item-background | transparent | Row surface color. |
--rc-list-item-selected-color | Not specified | Selected foreground color. |
--rc-list-item-selected-background | transparent | Selected surface color. |
--rc-list-item-border | 0 | Row border shorthand. |
--rc-list-item-border-radius | 0 | Row corner radius. |
--rc-list-item-box-shadow | none | Row shadow. |
--rc-list-item-divider | 0 | Divider border shorthand. |
--rc-list-item-divider-inset-inline | 0 | Divider inline inset. |
--rc-list-item-grid-template-rows | auto | Internal row track definition. |
--rc-list-item-row-gap | 0 | Gap between internal row tracks. |
--rc-list-item-leading-grid-column | leading-start / leading-end | Leading region column placement. |
--rc-list-item-leading-grid-row | auto | Leading region row placement. |
--rc-list-item-content-grid-column | content-start / content-end | Content region column placement. |
--rc-list-item-content-grid-row | auto | Content region row placement. |
--rc-list-item-content-white-space | nowrap | Content wrapping behavior. |
--rc-list-item-content-text-overflow | ellipsis | Content overflow marker. |
--rc-list-item-trailing-grid-column | trailing-start / trailing-end | Trailing region column placement. |
--rc-list-item-trailing-grid-row | auto | Trailing region row placement. |
--rc-list-item-trailing-justify-self | end | Trailing region alignment within its grid area. |
--rc-list-item-state-layer-color | currentColor | Interaction state layer color. |
--rc-list-item-state-layer-opacity | 0 | Resting interaction state layer opacity. |
--rc-list-item-hover-state-layer-opacity | 0.08 | Hover state opacity. |
--rc-list-item-focus-state-layer-opacity | 0.1 | Focus state opacity. |
--rc-list-item-pressed-state-layer-opacity | 0.1 | Pressed state opacity. |
--rc-list-item-disabled-opacity | 0.38 | Disabled row opacity. |
--rc-list-item-transition-duration | 0ms | Row state transition duration. |
--rc-list-item-transition-easing | ease | Row state transition easing. |
CSS Parts
| Part | Description |
|---|---|
row | Row surface and subgrid. |
state-layer | Hover, focus, and pressed state layer. |
leading | Leading slot wrapper. |
content | Default content slot wrapper. |
trailing | Trailing slot wrapper. |
divider | Row divider. |