Skip to Content

AI Card

Loading...

Overview

Resources

Loading...

Loading...

Loading...

Loading...

Install

yarn add @camp/ai-card

Basic Card Usage

The AI Card is exported with several helper components that can be used to style the card content.

  • Card - The main card wrapper.
  • StyledCardHeader - The header content of the card.
  • StyledCardBody - The body content of the card; set hasHeader to true to remove the top padding on the body content.
  • HeaderText - The text for the header; includes ellipsis truncation styling for long titles.
  • ChartWrapper - The wrapper for a chart component; set a string value for height to set the height of the chart container (for use with ResponsiveContainer).

Example

This card includes a header and body content.

import { Card, HeaderText, StyledCardHeader, StyledCardBody } from '@camp/ai-card'; <Card> <StyledCardHeader> <HeaderText> Card Header with a long title that should not wrap but should be truncated </HeaderText> </StyledCardHeader> <StyledCardBody> {' '} // You can optionally set `hasHeader` to `true` to remove the top padding on this body content. This is a basic card with a header and body content. The card component is flexible and can be used for various content types. </StyledCardBody> </Card>;

Chart Wrapper

AI Cards can include a chart component using ChartWrapper. Set a string value for height to set the height of the chart container (for use with ResponsiveContainer).

import { Card, StyledCardHeader, StyledCardBody, HeaderText, ChartWrapper } from '@camp/ai-card'; <Card> <StyledCardHeader> <HeaderText>Chart Container</HeaderText> </StyledCardHeader> <StyledCardBody> <ChartWrapper height="200px"> {' '} // Set a string value for `height` to set the height of the chart container (for use with `ResponsiveContainer`) <div>Chart content would go here</div> </ChartWrapper> </StyledCardBody> </Card>;

Block Card Usage

Block Cards are an interactive variation of the AI Card component. They have a responsive layout based on the width of the card container.

Example

import { BlockCard } from '@camp/ai-card'; // Example stock images const sampleImages = [ 'https://picsum.photos/id/15/200/300', 'https://picsum.photos/id/19/200/300', 'https://picsum.photos/id/17/200/300', ]; function Example() { return ( <div style={{ width: '600px' }}> <BlockCard type="automation" // Current available types are "automation" and "campaign_id" title="7-Day Welcome Drip Campaign" description="A 7-day email sequence to nurture new leads and increase engagement with your hardware store." isLoadingData={false} isLoadingImages={false} isOpen={false} images={sampleImages} maxImages={3} onClick={() => undefined} /> </div> ); }

Props

PropTypeRequiredDefaultDescription
typestring-The type of block card. Available values: "automation" (displays “Automate” label) or "campaign_id" (displays “Email Campaign” label)
Note: this is soon going to be phased out in favor of a render prop that can be used to render a chip in place of the type label text.
titlestring-The main title text displayed on the card
descriptionstring-The description text displayed below the title
isLoadingDataboolean-Whether the card is in a loading state for data content
isLoadingImagesboolean-Whether the card is in a loading state for images
isOpenboolean-Whether the card is in an open/active state
imagesstring[]-Array of image URLs to display in the image preview stack
maxImagesnumber-Maximum number of images to display in the preview stack
onClick() => void-Callback function called when the card is clicked
isDisabledbooleanfalseWhether the card is disabled and non-interactive

Loading states

The Block Card supports loading states for both data and images.

isLoadingData

When prop isLoadingData is set to true, the card will display this loading state for the data content.

isLoadingImages

When prop isLoadingImages is set to true, the card will display this loading state for the images.

isLoadingData & isLoadingImages

When props isLoadingData and isLoadingImages are both set to true, the card will display this loading state for both the data and images.

Open state

When prop isOpen is set to true, the card will display this open state. This matches the active pseudo state styles and is meant to be used when the card is active, such as when a user clicks on the card from the ActiveIntelligence sidebar and the relevant content is actively being displayed.

Truncation behavior

When the title or the description text is too long, it will be truncated with an ellipsis.

Disabled state

When prop isDisabled is set to true, the card will display this disabled state.

Insight Card Usage

The AI Insight Card is designed to display AI-generated insights to users in a consistent and actionable format. These cards present important information like optimizations, new opportunities, growth milestones, or alerts that require user attention.

Basic usage

An Insight Card requires a title, timestamp, and a callback function for the CTA button. The component supports multiple insight types with predefined styling and text.

import { AiInsightCard } from '@camp/ai-card'; function Example() { const handleCtaClick = () => { console.log('CTA clicked'); }; return ( <AiInsightCard type="optimization" title="Improve email engagement" description="Your recent campaigns show lower-than-average open rates. Consider adjusting send times." timestamp="2 hours ago" onCtaClick={handleCtaClick} /> ); }

Insight types

The Insight Card supports four predefined types, each with its own default chip styling and CTA text:

  • optimization: Optimizations are insights that include a drafted update to an object, such as an automation, email, SMS, etc that already exists. It includes data to back the insight, recommended next steps, and a draft of the update for the user to review. (default chip text: “Optimization”, default CTA: “Preview updates”)
  • new_opportunity: New opportunities are data-driven insights, where the next best action is a drafted newly created object, such as an automation, email, SMS, etc. (default chip text: “New opportunity”, default CTA: “Preview draft”)
  • growth_milestone: Account growth milestones are celebratory moments for the account, including number of contacts, number of email sends or automations activated, open/click rate, etc. records, and more. (default chip text: “Growth milestone”, default CTA: “View report”)
  • alert: Urgent, high-priority notifications from agents monitoring for problems. Alert cards should ALWAYS show first in the row, regardless of timestamp. The chipText in Alert cards should be set to be as clear as possible about the issue at hand (e.g., “Delivery Issue Detected”, “Integration Connection Issue”). This type requires custom chipText. (default CTA: “Review and fix”)
import { AiInsightCard } from '@camp/ai-card'; // Optimization type <AiInsightCard type="optimization" title="Improve email engagement" timestamp="2 hours ago" onCtaClick={handleToggleAiSidebar} // Default CTA text is "Preview updates" /> // New opportunity type <AiInsightCard type="new_opportunity" title="Expand to new audience segment" timestamp="1 day ago" onCtaClick={handleToggleAiSidebar} // Default CTA text is "Preview draft" /> // Growth milestone type <AiInsightCard type="growth_milestone" title="Reached 10,000 subscribers" timestamp="3 days ago" onCtaClick={handleToggleAiSidebar} // Default CTA text is "View report" /> // Alert type (requires custom chipText) <AiInsightCard type="alert" chipText="Delivery issue detected" title="Campaign delivery delays" timestamp="30 minutes ago" onCtaClick={handleToggleAiSidebar} // Default CTA text is "Review and fix" />

Expanded content

Insight Cards can include additional expandable content that appears when the user clicks “See more”. Clicking “See less” collapses it. Expanded cards expand over top of page content. Their height is not considered within the insight card row.

Expanded state is controlled within the component, so no external state management is needed. When content is provided to the expandedContent prop, “See more” will be displayed indicating that expanded content is available.

Active state

When an insight is currently being viewed or acted upon (opened in Active Intelligence via the card CTA), set the active prop to true. This applies a border-color change to indicate the card is active and changes the CTA text to “Close Active Intelligence”. Clicking the CTA then acts as an additional way to close the AI Sidebar.

import { AiInsightCard } from '@camp/ai-card'; <AiInsightCard type="optimization" title="Improve email engagement" timestamp="2 hours ago" active={true} onCtaClick={handleToggleAiSidebar} />;

Insight status

Insight cards have two primary status states that affect their visual appearance and behavior:

New

When a user has not yet opened a card in Active Intelligence via the CTA, it is considered to have “New” status. Set the status prop to “new” to display this status with success color.

All other statuses

Status is not required, but if another status is needed, set the status prop to the desired status. Any status value other than “new” (case-insensitive) displays with a supportive color.

import { AiInsightCard } from '@camp/ai-card'; // New status (success color) <AiInsightCard type="optimization" title="Improve email engagement" timestamp="2 hours ago" status="new" onCtaClick={handleToggleAiSidebar} /> // Other status (supportive color) <AiInsightCard type="optimization" title="Previous recommendation" timestamp="1 week ago" status="viewed" onCtaClick={handleToggleAiSidebar} />

Custom chip and CTA text

You can override the default chip text (chipText) and CTA button text (ctaText) for any type, or provide a completely custom chip component (typeChip).

import { AiInsightCard } from '@camp/ai-card'; import { Chip } from '@camp/chip'; // Override default text <AiInsightCard type="optimization" chipText="Custom optimization chip text" ctaText="Custom optimization CTA text" title="Urgent optimization needed" timestamp="5 minutes ago" onCtaClick={handleToggleAiSidebar} /> // Custom chip component <AiInsightCard typeChip={<Chip color="violet">Custom Chip</Chip>} ctaText="View details" title="Custom insight type" timestamp="1 hour ago" onCtaClick={handleToggleAiSidebar} />

Layout with AiInsightCardRow

Insight Cards should always be placed within an AiInsightCardRow component for proper layout. The row supports up to three cards and handles responsive sizing automatically.

import { AiInsightCard, AiInsightCardRow } from '@camp/ai-card'; function Example() { return ( <AiInsightCardRow> <AiInsightCard type="optimization" title="Improve email engagement" timestamp="2 hours ago" onCtaClick={() => handleToggleAiSidebar(someData)} /> <AiInsightCard type="new_opportunity" title="Expand to new audience" timestamp="1 day ago" onCtaClick={() => handleToggleAiSidebar(someData)} /> <AiInsightCard type="growth_milestone" title="Reached 10,000 subscribers" timestamp="3 days ago" onCtaClick={() => handleToggleAiSidebar(someData)} /> </AiInsightCardRow> ); }

Layout guidelines

  • Maximum 3 cards per row: Never place more than three Insight Cards in a single row. There should never be more than three cards per page.
  • Alert priority: Alert cards should ALWAYS show first in the row, regardless of timestamp.

Layout concerns handled automatically:

  • Responsive width: Single card 50% of row width; 2 cards: Stretch to fill equal width; 3 cards: Stretch to fill equal width.
  • Height matching: All cards in a row automatically match the height of the tallest card. Insight cards within a row grow in height to match the tallest card in a row.
  • Action alignment: Actions (CTA buttons) are aligned to the bottom of the card.

Z-index for expanded content

For greater control over stacking context, use the zIndex prop on AiInsightCardRow. This is helpful within pages that have multiple stacking contexts and the expanded content needs to be lifted up to appear above other page elements.

import { AiInsightCard, AiInsightCardRow } from '@camp/ai-card'; // Use zIndex when expanded content needs to appear above other elements <AiInsightCardRow zIndex={10}> <AiInsightCard type="optimization" title="Insight with expanded content" timestamp="1 hour ago" expandedContent={<div>{/* Expanded content */}</div>} onCtaClick={handleToggleAiSidebar} /> </AiInsightCardRow>;

Props

AiInsightCard

PropTypeRequiredDefaultDescription
type'optimization' | 'new_opportunity' | 'growth_milestone' | 'alert'Conditional-Type determines default chip text, chip color, and CTA button text. Required unless using typeChip
titlestring-The title of the insight
timestampstring-The timestamp of the insight (e.g., “2 hours ago”)
onCtaClick() => void-Callback function called when the CTA button is clicked
descriptionstring-Optional description text displayed below the title
expandedContentReact.ReactNode-The content to display when the insight is expanded
activebooleanfalseSet to true to apply active styling and change CTA text to “Close Active Intelligence”
statusstring-Status indicator. Value “new” (case-insensitive) shows with ‘success’ color, any other value shows with ‘supportive’ color
chipTextstringConditional-Override for default chip text. Required when type is “alert”
ctaTextstringConditional-Override for default CTA button text. Required when using typeChip. Overridden by active prop
typeChipReact.ReactNode-Custom React component to display instead of the default chip (mutually exclusive with type)
themedbooleantrueWhether the component should adapt to light/dark theme modes

AiInsightCardRow

PropTypeRequiredDefaultDescription
childrenReact.ReactNode-The insight card children to display in the row. Maximum of 3 cards
zIndexnumber-Optional z-index value to control stacking context. Use when expanded cards need to appear above other page content

Best practices

  • Use Block Cards for interactive content that users can click to expand or navigate
  • Set appropriate loading states to provide feedback during data fetching

Content guidelines

✅ DO

  • Use clear, descriptive titles that communicate the content purpose * Provide helpful descriptions that explain what the content does * Use appropriate block types that match the content category * Include relevant images that help users identify the content

🚫 DON’T

  • Use vague or generic titles that don’t describe the content * Leave descriptions empty or use placeholder text * Mix different content types in the same block card * Use too many images that clutter the interface

Accessibility

Keyboard support

  • Tab: Navigate through interactive elements within the AI Card
  • Enter/Space: Activate buttons and interactive elements
Last updated on