Grid List
The <smart-grid-list> component renders a grid of card-like records with optional title, description, per-item icon/image, link, badge, action template, and bottom footer slot. It follows the Base + Standard + Wrapper pattern with an InjectionToken-based extension mechanism. The abstract GridListBaseComponent defines the shared API — optional IGridListOptions and cssClass (alias class). GridListStandardComponent is a barebones placeholder concrete implementation. GridListComponent is the public wrapper that renders GridListStandardComponent by default and accepts a custom replacement via GRID_LIST_STANDARD_COMPONENT_TOKEN.
Usage
<smart-grid-list [options]="options" />
Components
GridListComponent (<smart-grid-list>)
Main wrapper component. Renders GridListStandardComponent by default. When GRID_LIST_STANDARD_COMPONENT_TOKEN is provided, renders the injected component via NgComponentOutlet.
GridListStandardComponent (<smart-grid-list-standard>)
Barebones placeholder concrete implementation. Renders a wrapper <div> containing an optional <h3 class="title">, optional <p class="description">, and a <ul role="list"> with one <li class="item"> per item. Each item renders the icon/image (icon template wins over image URL), a body group with the title (rendered as <a class="title"> if href is provided, otherwise <span class="title">) and optional description, plus optional badge/action template slots. When the item list is empty, the optional emptyTpl is rendered inside <div class="empty">. A bottom footerTpl renders inside <div class="footer">. The external cssClass is applied to the root wrapper. It does not include any visual styling — it exists solely as the default structural placeholder until a custom implementation is registered through the token.
GridListBaseComponent (abstract)
Abstract base directive for extending custom grid-list implementations. Exposes options as an InputSignal<IGridListOptions | undefined> and cssClass as an InputSignal<string> (with alias class).
API
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
options | InputSignal<IGridListOptions | undefined> | - | Optional configuration (title, description, items, columns, gap, layout, slots) |
class | InputSignal<string> | '' | External CSS classes (alias for cssClass) |
IGridListOptions
All properties are optional except IGridListItem.title. The default GridListStandardComponent consumes every property; a section is rendered only when its template/string is provided. Within an item, iconTpl takes precedence over imageUrl when both are set. columns, gap and layout are hints for custom implementations registered via the token.
GRID_LIST_STANDARD_COMPONENT_TOKEN
InjectionToken that allows replacing the default GridListStandardComponent with a custom implementation. Provide a Type<GridListBaseComponent> to override.
Extending the base class
import {
ChangeDetectionStrategy,
Component,
computed,
input,
ViewEncapsulation,
} from '@angular/core';
import {
GRID_LIST_STANDARD_COMPONENT_TOKEN,
GridListBaseComponent,
GridListComponent,
IGridListOptions,
} from '@smartsoft001/angular';
@Component({
selector: 'docs-custom-grid-list',
template: `
<div [class]="containerClasses()">
@if (options()?.title) {
<h3 class="docs-grid-list__title">{{ options()?.title }}</h3>
}
<ul
class="docs-grid-list__items"
[attr.data-columns]="options()?.columns ?? null"
>
@for (item of options()?.items ?? []; track item.id ?? $index) {
<li class="docs-grid-list__item">
@if (item.imageUrl) {
<img
class="docs-grid-list__image"
[src]="item.imageUrl"
[attr.alt]="item.imageAlt ?? ''"
/>
}
@if (item.href) {
<a class="docs-grid-list__link" [attr.href]="item.href">
{{ item.title }}
</a>
} @else {
<span class="docs-grid-list__label">{{ item.title }}</span>
}
@if (item.description) {
<p class="docs-grid-list__description">{{ item.description }}</p>
}
</li>
}
</ul>
</div>
`,
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomGridListComponent extends GridListBaseComponent {
// NgComponentOutlet passes 'cssClass' by canonical name, not the 'class'
// alias, so a grid list registered through the token declares it explicitly.
override cssClass = input<string>('');
containerClasses = computed(() => {
const classes = ['docs-grid-list'];
const extra = this.cssClass();
if (extra) classes.push(extra);
return classes.join(' ');
});
}
@Component({
selector: 'docs-grid-list-custom-example',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [GridListComponent],
// The token swaps the standard grid list for the custom one everywhere
// below this component, so consumers keep writing `<smart-grid-list>`.
providers: [
{
provide: GRID_LIST_STANDARD_COMPONENT_TOKEN,
useValue: CustomGridListComponent,
},
],
template: `<smart-grid-list [options]="options" />`,
})
export class GridListCustomExampleComponent {
options: IGridListOptions = {
title: 'Team',
columns: 3,
layout: 'cards',
items: [
{
id: 'lindsay',
title: 'Lindsay Walton',
description: 'Front-end Developer',
href: '/team/lindsay-walton',
},
{ id: 'courtney', title: 'Courtney Henry', description: 'Designer' },
{ id: 'tom', title: 'Tom Cook', description: 'Director of Product' },
],
};
}
Preset
GridListPresetComponent (<smart-grid-list-preset>) is a styled drop-in replacement for the barebones standard component, built entirely with vanilla Tailwind utilities (every class carries the smart: prefix) and explicit smart:dark:* twins in the same template. It extends GridListStandardComponent and reads the same IGridListOptions — no new options fields are introduced.
Layout:
- Optional
title/descriptionrender as a header block above the grid. - The grid is
smart:grid smart:grid-cols-1, widened responsively fromcolumns(smart:sm:grid-cols-2fromsm, thensmart:lg:grid-cols-<n>fromlg;1/unset stays single-column) and spaced fromgap(sm→smart:gap-3,md/default→smart:gap-4,lg→smart:gap-6). - Each item is a bordered rounded card.
layoutdrives the interior arrangement:cards(default) stacks media on top of the body,horizontalplaces media inline to the left of the body,logoscenters a contained logo above a centered caption. - Per item:
iconTpl(wins overimageUrl) orimageUrlrender as the media slot; the title renders as a link with asmart:hover:text-blue-600accent whenhrefis set, otherwise plain text;badgeTplsits beside the title;descriptionrenders under it;actionTplrenders in a bordered tile footer. - Empty items render
emptyTplor a centered default message;footerTplrenders below the grid.
Every zone is addressable via data-role hooks: header, grid, item, media, title, description, badge, action, empty, footer.
Register it through the token to restyle every <smart-grid-list>:
Because GridListComponent forwards inputs canonically through NgComponentOutlet, the preset overrides cssClass to drop the inherited class alias (override cssClass = input<string>('')); the value is merged onto the root wrapper.
Class recipes live in preset/preset-classes.util.ts (getGridListColumnsClasses, getGridListGapClasses, getGridListGridClasses, getGridListTileClasses, getGridListMediaClasses) and are intentionally not re-exported from the barrel to avoid export * collisions.
Documented gaps: layout only affects the tile interior arrangement (not per-item overrides); there is no built-in pagination or selection state.
- Preset:
packages/shared/angular/src/lib/components/grid-list/preset/preset.component.ts
Source
The component lives in packages/shared/angular/src/lib/components/grid-list and is documented for Claude Code by the angular-components-grid-list skill.