Skip to content
Navigation

Card

Added 14 October 2026

React

Codecomponents/react/card-demo.tsx
import {Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardIcon, CardTitle} from '@stroeer-labs/design-library/react';
import {Calendar} from 'lucide-react';

export function CardDemo() {
    return (
        <div className="space-y-6">
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Leading icon — CardIcon slot</p>
                <Card className="w-full max-w-sm">
                    <CardHeader>
                        <CardIcon>
                            <Calendar />
                        </CardIcon>
                        <CardTitle>Schedule</CardTitle>
                        <CardDescription>When should your campaign run?</CardDescription>
                    </CardHeader>
                    <CardContent>
                        <p className="text-sm text-muted-foreground">The optional icon sits in a leading column; title and description keep their layout.</p>
                    </CardContent>
                </Card>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Leading icon — size="sm"</p>
                <Card size="sm" className="w-full max-w-sm">
                    <CardHeader>
                        <CardIcon>
                            <Calendar />
                        </CardIcon>
                        <CardTitle>Schedule</CardTitle>
                        <CardDescription>Box and icon scale down with the sm card.</CardDescription>
                    </CardHeader>
                </Card>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Card</p>
                <Card className="w-full max-w-sm">
                    <CardHeader>
                        <CardTitle>Login to your account</CardTitle>
                        <CardDescription>Enter your email below to login to your account</CardDescription>
                        <CardAction>
                            <Button variant="link">Sign Up</Button>
                        </CardAction>
                    </CardHeader>
                    <CardContent>
                        <p className="text-sm text-muted-foreground">
                            The header lays out title, description and an action; this content region sits below it.
                        </p>
                    </CardContent>
                    <CardFooter className="flex-col gap-2">
                        <Button className="w-full">Login</Button>
                        <Button variant="outline" className="w-full">
                            Login with Google
                        </Button>
                    </CardFooter>
                </Card>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Card — size="sm"</p>
                <Card size="sm" className="w-full max-w-sm">
                    <CardHeader>
                        <CardTitle>Compact card</CardTitle>
                        <CardDescription>Tighter padding and spacing via the sm size.</CardDescription>
                    </CardHeader>
                    <CardContent>
                        <p className="text-sm text-muted-foreground">Same parts, denser layout.</p>
                    </CardContent>
                </Card>
            </div>
            <div className="space-y-3">
                <p className="text-xs font-medium text-muted-foreground">Elevation</p>
                <div className="grid grid-cols-1 gap-5 sm:grid-cols-3">
                    {(
                        [
                            {elevation: 'resting', use: 'Standalone content/section card. The default.'},
                            {elevation: 'interactive', use: 'Clickable list item — raises on hover.'},
                            {elevation: 'floating', use: 'Floats above another surface (e.g. over the map).'},
                        ] as const
                    ).map(({elevation, use}) => (
                        <div key={elevation} className="space-y-1.5">
                            <Card elevation={elevation} size="sm">
                                <CardHeader>
                                    <CardTitle>{elevation}</CardTitle>
                                    <CardDescription>elevation="{elevation}"</CardDescription>
                                </CardHeader>
                            </Card>
                            <p className="text-xs text-muted-foreground">{use}</p>
                        </div>
                    ))}
                </div>
            </div>
        </div>
    );
}

Angular

Codecomponents/angular/card-demo.ts
import '@angular/compiler';
import {Component} from '@angular/core';
import {NgIcon, provideIcons} from '@ng-icons/core';
import {lucideCalendar} from '@ng-icons/lucide';
import {HlmButtonImports, HlmCardImports} from '@stroeer-labs/design-library/angular';

@Component({
    selector: 'dl-card-demo',
    standalone: true,
    imports: [HlmCardImports, HlmButtonImports, NgIcon],
    viewProviders: [provideIcons({lucideCalendar})],
    template: `
    <div class="space-y-6">
      <div class="space-y-2">
        <p class="text-xs font-medium text-muted-foreground">Leading icon — hlmCardIcon slot</p>
        <hlm-card class="w-full max-w-sm">
          <hlm-card-header>
            <div hlmCardIcon><ng-icon name="lucideCalendar" /></div>
            <h3 hlmCardTitle>Schedule</h3>
            <p hlmCardDescription>When should your campaign run?</p>
          </hlm-card-header>
          <div hlmCardContent>
            <p class="text-sm text-muted-foreground">The optional icon sits in a leading column; title and description keep their layout.</p>
          </div>
        </hlm-card>
      </div>
      <div class="space-y-2">
        <p class="text-xs font-medium text-muted-foreground">Leading icon — size="sm"</p>
        <hlm-card size="sm" class="w-full max-w-sm">
          <hlm-card-header>
            <div hlmCardIcon><ng-icon name="lucideCalendar" /></div>
            <h3 hlmCardTitle>Schedule</h3>
            <p hlmCardDescription>Box and icon scale down with the sm card.</p>
          </hlm-card-header>
        </hlm-card>
      </div>
      <div class="space-y-2">
        <p class="text-xs font-medium text-muted-foreground">Card</p>
        <hlm-card class="w-full max-w-sm">
          <hlm-card-header>
            <h3 hlmCardTitle>Login to your account</h3>
            <p hlmCardDescription>Enter your email below to login to your account</p>
            <div hlmCardAction>
              <button hlmBtn variant="link">Sign Up</button>
            </div>
          </hlm-card-header>
          <div hlmCardContent>
            <p class="text-sm text-muted-foreground">
              The header lays out title, description and an action; this content region sits below it.
            </p>
          </div>
          <hlm-card-footer class="flex-col gap-2">
            <button hlmBtn class="w-full">Login</button>
            <button hlmBtn variant="outline" class="w-full">Login with Google</button>
          </hlm-card-footer>
        </hlm-card>
      </div>
      <div class="space-y-2">
        <p class="text-xs font-medium text-muted-foreground">Card — size="sm"</p>
        <hlm-card size="sm" class="w-full max-w-sm">
          <hlm-card-header>
            <h3 hlmCardTitle>Compact card</h3>
            <p hlmCardDescription>Tighter padding and spacing via the sm size.</p>
          </hlm-card-header>
          <div hlmCardContent>
            <p class="text-sm text-muted-foreground">Same parts, denser layout.</p>
          </div>
        </hlm-card>
      </div>
      <div class="space-y-3">
        <p class="text-xs font-medium text-muted-foreground">Elevation</p>
        <div class="grid grid-cols-1 gap-5 sm:grid-cols-3">
          @for (item of elevations; track item.elevation) {
            <div class="space-y-1.5">
              <hlm-card [elevation]="item.elevation" size="sm">
                <hlm-card-header>
                  <h3 hlmCardTitle>{{ item.elevation }}</h3>
                  <p hlmCardDescription>elevation="{{ item.elevation }}"</p>
                </hlm-card-header>
              </hlm-card>
              <p class="text-xs text-muted-foreground">{{ item.use }}</p>
            </div>
          }
        </div>
      </div>
    </div>
  `,
})
export class CardDemoComponent {
    protected readonly elevations = [
        {elevation: 'resting', use: 'Standalone content/section card. The default.'},
        {elevation: 'interactive', use: 'Clickable list item — raises on hover.'},
        {elevation: 'floating', use: 'Floats above another surface (e.g. over the map).'},
    ] as const;
}