Card Heading
The <smart-card-heading> component provides a small composable heading region for cards, with optional slots for avatar, title, description, meta, and actions. It can be used standalone or passed as the headerTpl value to <smart-card>. It follows the Base + Standard + Wrapper pattern with an InjectionToken-based extension mechanism. The abstract CardHeadingBaseComponent defines the shared API — optional ICardHeadingOptions and cssClass (alias class). CardHeadingStandardComponent is a barebones placeholder concrete implementation. CardHeadingComponent is the public wrapper that renders CardHeadingStandardComponent by default and accepts a custom replacement via CARD_HEADING_STANDARD_COMPONENT_TOKEN.
Usage
<smart-card-heading [options]="options()" />
<ng-template #actions>
<button type="button" (click)="onCreate()">Create new job</button>
</ng-template>
Components
CardHeadingComponent (<smart-card-heading>)
Main wrapper component. Renders CardHeadingStandardComponent by default. When CARD_HEADING_STANDARD_COMPONENT_TOKEN is provided, renders the injected component via NgComponentOutlet.
CardHeadingStandardComponent (<smart-card-heading-standard>)
Barebones placeholder concrete implementation. Renders a wrapper <div> with an optional avatar slot, a content area containing <h3> (title) + <p class="description"> (description) + optional meta slot, and an optional actions slot. Each section is rendered only when its corresponding template/string is provided. The external cssClass is applied to the wrapper. It does not include Tailwind UI styling — it exists solely as the default structural placeholder until a custom implementation is registered through the token.
CardHeadingBaseComponent (abstract)
Abstract base directive for extending custom card-heading implementations. Exposes options as an InputSignal<ICardHeadingOptions | undefined> and cssClass as an InputSignal<string> (with alias class).
API
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
options | InputSignal<ICardHeadingOptions | undefined> | - | Optional configuration (title, description, slot templates) |
class | InputSignal<string> | '' | External CSS classes (alias for cssClass) |
ICardHeadingOptions
All properties are optional. The default CardHeadingStandardComponent consumes every property; a section is rendered only when its template/string is provided.
CARD_HEADING_STANDARD_COMPONENT_TOKEN
InjectionToken that allows replacing the default CardHeadingStandardComponent with a custom implementation. Provide a Type<CardHeadingBaseComponent> to override.
Extending the base class
import { NgTemplateOutlet } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
computed,
input,
ViewEncapsulation,
} from '@angular/core';
import {
CardHeadingBaseComponent,
CardHeadingComponent,
CARD_HEADING_STANDARD_COMPONENT_TOKEN,
ICardHeadingOptions,
} from '@smartsoft001/angular';
/**
* A custom card heading built on `CardHeadingBaseComponent`.
*
* The base contributes the `options` and `class` inputs; the implementation
* owns the markup, including where the optional `TemplateRef` slots of
* `ICardHeadingOptions` are projected.
*/
@Component({
selector: 'docs-custom-card-heading',
template: `
<div [class]="containerClasses()">
<div class="docs-card-heading__content">
@if (options()?.title) {
<h3 class="docs-card-heading__title">{{ options()!.title }}</h3>
}
@if (options()?.description) {
<p class="docs-card-heading__description">
{{ options()!.description }}
</p>
}
</div>
@if (options()?.actionsTpl) {
<div class="docs-card-heading__actions">
<ng-container [ngTemplateOutlet]="options()!.actionsTpl!" />
</div>
}
</div>
`,
imports: [NgTemplateOutlet],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomCardHeadingComponent extends CardHeadingBaseComponent {
// The wrapper hands inputs to NgComponentOutlet by canonical name, so the
// consumer's class arrives as `cssClass` rather than through the alias.
override cssClass = input<string>('');
containerClasses = computed(() =>
['docs-card-heading', this.cssClass()].filter(Boolean).join(' '),
);
}
/**
* Registering the implementation against `CARD_HEADING_STANDARD_COMPONENT_TOKEN`
* makes every `<smart-card-heading>` in this injector render it instead of the
* standard variation.
*/
@Component({
selector: 'docs-card-heading-custom-example',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CardHeadingComponent],
providers: [
{
provide: CARD_HEADING_STANDARD_COMPONENT_TOKEN,
useValue: CustomCardHeadingComponent,
},
],
template: `
<smart-card-heading
[options]="options"
[class]="'docs-card-heading--demo'"
/>
`,
})
export class CardHeadingCustomExampleComponent {
options: ICardHeadingOptions = {
title: 'Applicant information',
description: 'Personal details and application.',
};
}
HyperUI preset
CardHeadingPresetComponent (<smart-card-heading-preset>) is a HyperUI-styled drop-in replacement for the standard component. It extends CardHeadingStandardComponent, is OnPush + ViewEncapsulation.None, and restyles the heading into one of four card looks selected by options.presentation.variant. All utilities are smart:-prefixed with explicit smart:dark:* variants. Content flows from the shared ICardHeadingOptions slots; the root element carries data-role="card" and per-variant zones expose data-role hooks (avatar, title, description, meta, actions, plus title-hover for the outline variant).
Because the wrapper forwards inputs canonically through NgComponentOutlet, the preset does override cssClass = input<string>('') (dropping the inherited class alias) and merges it into the root card classes.
| Variant | Look | Slots used |
|---|---|---|
author | Bordered, rounded card; avatar to the side, meta <dl> (default) | title, description, avatarTpl, metaTpl, actionsTpl |
stacked | Large top image, title + description stacked underneath | title, description, avatarTpl, metaTpl, actionsTpl |
overlay | Full-bleed image on a black backdrop, content revealed on hover | title, description, avatarTpl, metaTpl (eyebrow), actionsTpl |
outline | Dashed offset border, title flips to description/action on hover | title, description, avatarTpl, actionsTpl |
presentation.variant defaults to author (also the fallback for an unknown value).
Gaps (out of scope)
HyperUI card templates 5–9 are not implemented — they need domain fields absent from ICardHeadingOptions:
- Property card — price, address, list of numeric specs (beds/baths/area).
- Profile with social + project links — dedicated social-icon and project-link collections (dark profile card).
- Shaped image — a decorative clip-path/image-shape treatment with no content-driven data channel.
- Podcast post — episode number, duration, and audio/player metadata.
- Forum post — author, reply count, tag list, and activity timestamps.
Adding any of these would require extending ICardHeadingOptions (e.g. structured stats, links, or badges collections) before a faithful preset variant can be built.
Source
The component lives in packages/shared/angular/src/lib/components/card-heading and is documented for Claude Code by the angular-components-card-heading skill.