Surfaces
Card
Group related content and actions on a shared surface.
Import
import { NeuCardComponent } from '@neural-ui/native/card';Examples
Import ExampleComponent into its parent and place <app-example /> inside your application’s root neu-theme. The preview supplies the device frame and safe areas; use the root setup from Installation in your app.
Your next milestone
Compose a project card with an original cover, team and working checklist. Open the project and complete its two tasks: progress follows the completed tasks and stays saved locally when the details close.
View and copy the complete example
import { Component, signal, computed } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuCheckboxComponent } from '@neural-ui/native/checkbox';
import { NeuCardComponent } from '@neural-ui/native/card';
import { NeuBadgeComponent } from '@neural-ui/native/badge';
import { NeuAvatarGroupComponent } from '@neural-ui/native/avatar-group';
import { NeuProgressBarComponent } from '@neural-ui/native/progress-bar';
import { NeuCardHeaderDirective } from '@neural-ui/native/card';
import { NeuCardFooterDirective } from '@neural-ui/native/card';
import { View, Text, Image, ScrollView } from '@ng-native/components';
@Component({
selector: 'app-example',
imports: [NeuButtonComponent, NeuCheckboxComponent, NeuCardComponent, NeuBadgeComponent, NeuAvatarGroupComponent, NeuProgressBarComponent, NeuCardHeaderDirective, NeuCardFooterDirective, View, Text, Image, ScrollView],
template: `
<scroll-view class="product-scroll" keyboardShouldPersistTaps="handled" [showsVerticalScrollIndicator]="false"><view class="product-stack"><view class="product-section"><text class="product-title" accessibilityRole="header">Your next milestone</text><text class="product-caption">Neural Studio · Selected project</text></view>
<neu-card variant="outlined">
<view neuCardHeader class="project-cover-heading">
<view class="product-row"><view class="product-copy"><text class="studio-kicker">NEURAL STUDIO / 02</text></view><neu-badge label="In progress" tone="info" /></view>
<image class="project-cover" [source]="{ uri: cover }" resizeMode="cover" accessibilityLabel="An original illustration of a quiet blue coast" />
<text class="project-name" accessibilityRole="header">Mobile launch</text>
<text class="product-caption">Next milestone · Friday</text>
</view>
<view class="product-section">
<text>Prepare the onboarding flow and final release notes.</text>
<view class="product-row"><neu-avatar-group [items]="team" [max]="3" size="sm" /><view class="product-copy"><text class="product-caption">Product team</text></view></view>
<neu-progress-bar label="Release readiness" [value]="readyCount() * 50" />
@if (opened()) {
<view class="project-checklist"><text class="product-heading">Release checklist</text><neu-checkbox label="Review onboarding" [(checked)]="onboarding" /><neu-checkbox label="Prepare release notes" [(checked)]="notes" /><text class="product-caption" accessibilityLiveRegion="polite">{{ readyCount() }} / 2 ready</text></view>
}
</view>
<view neuCardFooter class="product-actions"><neu-button [label]="opened() ? 'Close project' : 'Open project'" size="sm" [variant]="opened() ? 'outline' : 'solid'" (pressed)="opened.set(!opened())" /></view>
</neu-card>
<view class="next-project"><view class="next-project-mark"><text class="next-project-letter">N</text></view><view class="product-copy"><text class="studio-kicker">UP NEXT</text><text class="product-heading">Design system</text></view><neu-badge label="Draft" tone="neutral" /></view></view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
:host { flex: 1; flex-shrink: 1; min-height: 0; }
.product-scroll { flex: 1; flex-shrink: 1; height: 0px; min-height: 0; }
.product-stack { gap: 24px; padding-bottom: 20px; }
.product-section { gap: 12px; }
.product-row { flex-direction: row; align-items: center; gap: 12px; }
.product-copy { flex: 1; min-width: 0; gap: 4px; }
.product-title { color: var(--neu-text, #172033); font-size: 24px; line-height: 30px; font-weight: 600; }
.product-heading { color: var(--neu-text, #172033); font-size: 17px; line-height: 23px; font-weight: 600; }
.product-caption { color: var(--neu-muted, #596477); font-size: 14px; line-height: 20px; }
.product-actions { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
.product-surface { gap: 16px; padding: 16px; border-radius: 16px; background-color: var(--neu-surface, #ffffff); border-width: 1px; border-color: var(--neu-border, #a5afbf); }
.project-cover-heading { gap: 12px; }
.studio-kicker { color: var(--neu-muted, #596477); font-size: 11px; line-height: 16px; font-weight: 600; letter-spacing: 1px; }
.project-cover { width: 100%; aspect-ratio: 2; border-radius: 12px; }
.project-name { color: var(--neu-text, #172033); font-size: 25px; line-height: 31px; font-weight: 600; }
.project-checklist { gap: 12px; padding-top: 8px; }
.next-project { flex-direction: row; align-items: center; gap: 12px; }
.next-project-mark { width: 44px; height: 44px; align-items: center; justify-content: center; border-radius: 14px; background-color: #e9e1f6; }
.next-project-letter { font-size: 20px; font-weight: 600; color: #5b387d; }
`,
})
export class ExampleComponent {
readonly cover = '/assets/media/v2/coast.png';
readonly team = [{ id: 'ada', label: 'Ada Lovelace' }, { id: 'grace', label: 'Grace Hopper' }, { id: 'alan', label: 'Alan Turing' }];
readonly opened = signal(false);
readonly onboarding = signal(true);
readonly notes = signal(false);
readonly readyCount = computed(() => Number(this.onboarding()) + Number(this.notes()));
}Surface and tonal treatments
Compare surface and tonal cards with projected content.
View and copy the complete example
import { Component } from '@angular/core';
import { NeuCardComponent } from '@neural-ui/native/card';
import { View, Text, ScrollView } from '@ng-native/components';
@Component({
selector: 'app-example',
imports: [NeuCardComponent, View, Text, ScrollView],
template: `
<scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
<neu-card title="Design review" description="Today · 14:30" variant="surface"><text>Review the final onboarding flow with the team.</text></neu-card>
<neu-card title="Next milestone" description="Release candidate" variant="tonal"><text>Everything you need for the next handoff.</text></neu-card>
</view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }
`,
})
export class ExampleComponent {
}Custom header and actions
Project a heading with an avatar and a separate footer. Your application owns the content and action.
View and copy the complete example
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuCardComponent } from '@neural-ui/native/card';
import { NeuBadgeComponent } from '@neural-ui/native/badge';
import { NeuAvatarComponent } from '@neural-ui/native/avatar';
import { View, Text, ScrollView } from '@ng-native/components';
import { NeuCardHeaderDirective, NeuCardFooterDirective } from '@neural-ui/native/card';
@Component({
selector: 'app-example',
imports: [NeuButtonComponent, NeuCardComponent, NeuBadgeComponent, NeuAvatarComponent, NeuCardHeaderDirective, NeuCardFooterDirective, View, Text, ScrollView],
template: `
<scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
<neu-card title="Design review" variant="outlined">
<view neuCardHeader class="project-header">
<neu-avatar label="Alex Morgan" size="md" />
<view class="project-copy"><text class="usage-heading" accessibilityRole="header">Design review</text><text class="usage-caption">Alex Morgan · Product team</text></view>
</view>
<text>Review the new onboarding screens before Friday.</text>
<view neuCardFooter class="project-actions"><neu-badge label="Ready for review" tone="success" /><neu-button label="Open review" size="sm" variant="text" (pressed)="opened.set(true)" /></view>
</neu-card>
<text class="usage-caption" accessibilityLiveRegion="polite">{{ opened() ? 'Review opened' : 'Choose a review' }}</text>
</view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }
.project-header { flex-direction: row; gap: 12px; align-items: center; } .project-copy { flex: 1; min-width: 0; gap: 4px; } .project-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: space-between; }
`,
})
export class ExampleComponent {
readonly opened = signal(false);
}Change the settings and try the result.
Device captures shown in English.


Personalization
Import these directives together with the component and add them to Component.imports. The examples above include the complete setup.
import { NeuCardHeaderDirective, NeuCardFooterDirective } from '@neural-ui/native/card';| Template or region | Context | Purpose |
|---|---|---|
[neuCardHeader] | — | Project a native view to replace the built-in title and description. |
ng-content | — | Unmarked content is the card body. |
[neuCardFooter] | — | Project actions or supporting content after the body. |
API reference
Inputs
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| title | string | '' | Input | Heading for the surface, section or presentation. |
| description | string | '' | Input | Supporting text. Individual components decide where this optional description is shown. |
| variant | "tonal" | "surface" | "outlined" | 'surface' | Input | Surface treatment: surface, tonal or outlined. Projected content keeps its own behavior. |
Models
This component declares no two-way models.
Outputs
This component declares no public outputs.