AI Card
Loading...
Overview
Resources
Install
yarn add @camp/ai-cardBasic 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; sethasHeadertotrueto 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 forheightto set the height of the chart container (for use withResponsiveContainer).
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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | ✅ | - | 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. |
title | string | ✅ | - | The main title text displayed on the card |
description | string | ✅ | - | The description text displayed below the title |
isLoadingData | boolean | ✅ | - | Whether the card is in a loading state for data content |
isLoadingImages | boolean | ✅ | - | Whether the card is in a loading state for images |
isOpen | boolean | ✅ | - | Whether the card is in an open/active state |
images | string[] | ✅ | - | Array of image URLs to display in the image preview stack |
maxImages | number | ✅ | - | Maximum number of images to display in the preview stack |
onClick | () => void | ✅ | - | Callback function called when the card is clicked |
isDisabled | boolean | ❌ | false | Whether 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
chipTextin 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 customchipText. (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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
type | 'optimization' | 'new_opportunity' | 'growth_milestone' | 'alert' | Conditional | - | Type determines default chip text, chip color, and CTA button text. Required unless using typeChip |
title | string | ✅ | - | The title of the insight |
timestamp | string | ✅ | - | The timestamp of the insight (e.g., “2 hours ago”) |
onCtaClick | () => void | ✅ | - | Callback function called when the CTA button is clicked |
description | string | ❌ | - | Optional description text displayed below the title |
expandedContent | React.ReactNode | ❌ | - | The content to display when the insight is expanded |
active | boolean | ❌ | false | Set to true to apply active styling and change CTA text to “Close Active Intelligence” |
status | string | ❌ | - | Status indicator. Value “new” (case-insensitive) shows with ‘success’ color, any other value shows with ‘supportive’ color |
chipText | string | Conditional | - | Override for default chip text. Required when type is “alert” |
ctaText | string | Conditional | - | Override for default CTA button text. Required when using typeChip. Overridden by active prop |
typeChip | React.ReactNode | ❌ | - | Custom React component to display instead of the default chip (mutually exclusive with type) |
themed | boolean | ❌ | true | Whether the component should adapt to light/dark theme modes |
AiInsightCardRow
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | ✅ | - | The insight card children to display in the row. Maximum of 3 cards |
zIndex | number | ❌ | - | 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