Overview
BaseCard is a flexible container component designed for displaying content in a card format. It supports images, type badges (beta/soon), and customizable footer content through Svelte snippets.
Import
import { BaseCard } from '@invopop/popui'
Basic Usage
<script>
import { BaseCard } from '@invopop/popui'
</script>
<BaseCard
imageUrl="/icons/integration.png"
imageAlt="Integration icon"
title="API Integration"
description="Connect your application with our REST API"
onclick={() => console.log('Card clicked')}
/>
With Type Badge
Display status badges to indicate beta features or upcoming functionality:
<BaseCard
imageUrl="/icons/feature.png"
imageAlt="Feature icon"
title="New Feature"
description="This feature is currently in beta testing"
type="beta"
onclick={() => console.log('Beta feature clicked')}
/>
<BaseCard
imageUrl="/icons/upcoming.png"
imageAlt="Upcoming icon"
title="Upcoming Feature"
description="This feature will be available soon"
type="soon"
/>
Cards with type="soon" are automatically disabled and non-interactive.
Use Svelte snippets to add custom footer content:
<script>
import { BaseCard, TagStatus } from '@invopop/popui'
</script>
<BaseCard
imageUrl="/icons/service.png"
imageAlt="Service icon"
title="Cloud Service"
description="Scalable cloud infrastructure for your applications"
>
{#snippet footer()}
<div class="flex gap-2">
<TagStatus label="Active" status="green" />
<TagStatus label="Europe" status="blue" />
</div>
{/snippet}
</BaseCard>
Image Support
The component displays images in a consistent bordered container:
<BaseCard
imageUrl="https://example.com/logo.png"
imageAlt="Company logo"
title="Company Name"
description="Enterprise-grade solutions for modern businesses"
/>
Props
URL of the image to display in the card header
Alternative text for the image (accessibility)
Main heading text for the card
Secondary descriptive text displayed below the title
type
'default' | 'soon' | 'beta'
default:"'default'"
Card type that determines badge display and disabled state:
default: Normal interactive card
beta: Shows “Beta” badge
soon: Shows “Soon” badge and disables interaction
Svelte snippet for custom footer content. Rendered at the bottom of the card with proper spacing.
onclick
(event: MouseEvent) => void
Click handler function called when the card is clicked (not called when type="soon")
TypeScript Interface
export interface BaseCardProps {
imageUrl?: string
imageAlt?: string
title?: string
description?: string
type?: 'default' | 'soon' | 'beta'
footer?: Snippet
[key: string]: any
onclick?: (event: MouseEvent) => void
}
Styling
BaseCard uses Tailwind CSS classes and supports:
- Hover state with border color change
- Disabled state for “soon” cards
- Automatic layout with flexbox
- Minimum width of 298px
- Rounded corners (xl)
- Consistent padding and spacing
Accessibility
- Rendered as a
<button> element for proper keyboard navigation
- Supports disabled state when appropriate
- Includes alt text for images
- Maintains focus states for keyboard users
Examples
Grid of Cards
<script>
import { BaseCard } from '@invopop/popui'
const integrations = [
{
id: 1,
title: 'Stripe',
description: 'Payment processing integration',
imageUrl: '/icons/stripe.png',
type: 'default'
},
{
id: 2,
title: 'Webhooks',
description: 'Real-time event notifications',
imageUrl: '/icons/webhooks.png',
type: 'beta'
},
{
id: 3,
title: 'Analytics',
description: 'Advanced analytics dashboard',
imageUrl: '/icons/analytics.png',
type: 'soon'
}
]
function handleCardClick(id: number) {
console.log('Selected integration:', id)
}
</script>
<div class="grid grid-cols-3 gap-4">
{#each integrations as integration}
<BaseCard
imageUrl={integration.imageUrl}
imageAlt={integration.title}
title={integration.title}
description={integration.description}
type={integration.type}
onclick={() => handleCardClick(integration.id)}
/>
{/each}
</div>
<script>
import { BaseCard, TagStatus, BaseButton } from '@invopop/popui'
</script>
<BaseCard
imageUrl="/icons/database.png"
imageAlt="Database icon"
title="PostgreSQL Database"
description="Managed database with automatic backups"
>
{#snippet footer()}
<div class="flex items-center justify-between">
<TagStatus label="Running" status="green" dot />
<BaseButton size="sm" variant="ghost">
Configure
</BaseButton>
</div>
{/snippet}
</BaseCard>