Menu

Change language

GitHub repo

Section Card

section-cardui

Card variant tuned for settings pages — title, description, and content slots, with optional footer for save/cancel actions. The block-level building block for `.../settings/*` routes.

Installation

$npx uipkge-ng@latest add section-card
Manifest:https://uipkge.dev/r/angular/section-card.jsonInstalls to:src/app/components/ui/section-card/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
titlestring—optional
data-slot

A consumer's data-slot wins, as React spreads its props after data-slot="card".

stringcardoptional
descriptionstring—optional
contentClassNamestring—optional
classstring—optional

Includes

Used by

Files installed (2)

  • src/app/components/ui/section-card/section-card.component.ts2.1 kB
    import { Component, Input, ChangeDetectionStrategy } from '@angular/core'
    import { cn } from '@/lib/utils'
    import { cardVariants } from '@/ui/card/card.variants'
    import {
      UiCardContentComponent,
      UiCardDescriptionComponent,
      UiCardHeaderComponent,
      UiCardTitleComponent,
    } from '@/ui/card/card.component'
    
    /**
     * Angular port of UIPKGE SectionCard (React `SectionCard`): a Card with a title/description
     * header, a content well and an optional footer. The host is the Card itself (same classes and
     * data-slot as React's `<Card>`). React's `headerAction` / `footer` props are the
     * `[slot=header-action]` / `[slot=footer]` projections, rendered verbatim with no wrapper.
     */
    @Component({
      changeDetection: ChangeDetectionStrategy.Eager,
      selector: 'ui-section-card, [ui-section-card]',
      standalone: true,
      imports: [UiCardHeaderComponent, UiCardTitleComponent, UiCardDescriptionComponent, UiCardContentComponent],
      host: {
        '[attr.data-slot]': 'dataSlot',
        '[attr.data-uipkge]': '""',
        '[class]': 'hostClass',
      },
      template: `<div ui-card-header class="pb-4">
          <div class="flex flex-wrap items-center justify-between gap-2">
            <div class="min-w-0">
              <h3 ui-card-title class="text-base font-semibold">{{ title }}</h3>
              @if (description) {
                <p ui-card-description class="mt-0.5">{{ description }}</p>
              }
            </div>
            <ng-content select="[slot=header-action]" />
          </div>
        </div>
        <div ui-card-content [class]="contentClass"><ng-content /></div>
        <ng-content select="[slot=footer]" />`,
    })
    export class UiSectionCardComponent {
      @Input() title = ''
      /** A consumer's data-slot wins, as React spreads its props after data-slot="card". */
      @Input('data-slot') dataSlot = 'card'
      @Input() description?: string
      @Input() contentClassName?: string
      @Input('class') className?: string
    
      get hostClass(): string {
        return cn(cardVariants({ variant: 'default' }), 'overflow-hidden', 'flex flex-col', this.className)
      }
    
      get contentClass(): string {
        return cn('flex-1', this.contentClassName)
      }
    }
    
  • src/app/components/ui/section-card/index.ts0.1 kB

Raw manifest:https://uipkge.dev/r/angular/section-card.json