Tile components for grouping content and layout utilities for maintaining consistent aspect ratios in responsive interfaces.
Basic container component for grouping related content with optional decorative elements.
/**
* Base tile component for grouping content
*/
interface TileProps extends React.HTMLAttributes<HTMLDivElement> {
/** Tile content */
children?: React.ReactNode;
/** CSS class name */
className?: string;
/** Experimental: Provide a decorator component to be rendered inside the Tile */
decorator?: React.ReactNode;
/** Deprecated: Use Layer component instead */
light?: boolean;
/** Experimental: Specify if the Tile should be rendered with rounded corners. Only valid when an AILabel is present */
hasRoundedCorners?: boolean;
/** Deprecated: Use decorator instead. Experimental: Provide a Slug component */
slug?: React.ReactNode;
}
/**
* Clickable tile component that can function as a link or button
*/
interface ClickableTileProps extends React.HTMLAttributes<HTMLAnchorElement> {
/** Tile content */
children?: React.ReactNode;
/** CSS class name */
className?: string;
/** Experimental: Provide a decorator component or set to true for an AILabel icon */
decorator?: boolean | React.ReactNode;
/** Deprecated: Use Layer component instead */
light?: boolean;
/** Boolean for whether a tile has been clicked */
clicked?: boolean;
/** Specify whether the ClickableTile should be disabled */
disabled?: boolean;
/** Experimental: Specify if the ClickableTile should be rendered with rounded corners. Only valid when decorator is present */
hasRoundedCorners?: boolean;
/** The href for the link */
href?: string;
/** A component used to render an icon */
renderIcon?: React.ElementType;
/** Function to run when the ClickableTile is clicked */
onClick?: (event: React.MouseEvent) => void;
/** Function to run when the ClickableTile is interacted with via keyboard */
onKeyDown?: (event: React.KeyboardEvent) => void;
/** The rel property for the link */
rel?: string;
/** Deprecated: Use decorator instead. Experimental: Specify if a Slug icon should be rendered */
slug?: boolean;
}
/**
* Selectable tile component with checkbox-style interaction
*/
interface SelectableTileProps extends React.HTMLAttributes<HTMLDivElement> {
/** Tile content */
children?: React.ReactNode;
/** CSS class name */
className?: string;
/** Experimental: Provide a decorator component to be rendered inside the SelectableTile */
decorator?: React.ReactNode;
/** Deprecated: Use Layer component instead */
light?: boolean;
/** Specify whether the SelectableTile should be disabled */
disabled?: boolean;
/** Experimental: Specify if the SelectableTile should be rendered with rounded corners. Only valid when decorator is present */
hasRoundedCorners?: boolean;
/** The ID of the input */
id?: string;
/** Deprecated: The name of the input */
name?: string;
/** The handler for the input change event */
onChange?: (
event: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>,
selected?: boolean,
id?: string
) => void;
/** Function to run when the SelectableTile is clicked */
onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
/** Function to run when the SelectableTile is interacted with via keyboard */
onKeyDown?: (event: React.KeyboardEvent<HTMLDivElement>) => void;
/** True to select this tile */
selected?: boolean;
/** Deprecated: Use decorator instead. Experimental: Provide a Slug component */
slug?: React.ReactNode;
/** Specify the tab index of the wrapper element */
tabIndex?: number;
/** The title of the input */
title?: string;
/** Deprecated: The value of the input */
value?: string | number;
}
/**
* Expandable tile component with collapsible content sections
*/
interface ExpandableTileProps extends React.HTMLAttributes<HTMLDivElement> {
/** Tile content - expects two children for above and below fold content */
children?: React.ReactNode;
/** CSS class name */
className?: string;
/** Experimental: Provide a decorator component to be rendered inside the ExpandableTile */
decorator?: React.ReactNode;
/** Deprecated: Use Layer component instead */
light?: boolean;
/** True if the tile is expanded */
expanded?: boolean;
/** Experimental: Specify if the ExpandableTile should be rendered with rounded corners. Only valid when decorator is present */
hasRoundedCorners?: boolean;
/** An ID that can be provided to aria-labelledby */
id?: string;
/** Function to run when the ExpandableTile is clicked */
onClick?: (event: React.MouseEvent) => void;
/** Optional handler to trigger a function when a key is pressed */
onKeyUp?: (event: React.KeyboardEvent) => void;
/** Deprecated: Use decorator instead. Experimental: Provide a Slug component */
slug?: React.ReactNode;
/** The tabindex attribute */
tabIndex?: number;
/** The description of the "collapsed" icon that can be read by screen readers */
tileCollapsedIconText?: string;
/** When "collapsed", a label to appear next to the chevron (e.g., "View more") */
tileCollapsedLabel?: string;
/** The description of the "expanded" icon that can be read by screen readers */
tileExpandedIconText?: string;
/** When "expanded", a label to appear next to the chevron (e.g., "View less") */
tileExpandedLabel?: string;
/** Maximum height of the tile */
tileMaxHeight?: number;
/** Tile padding */
tilePadding?: number;
}
/**
* Content wrapper for the visible portion of an expandable tile
*/
interface TileAboveTheFoldContentProps {
/** The child nodes */
children?: React.ReactNode;
}
/**
* Content wrapper for the collapsible portion of an expandable tile
*/
interface TileBelowTheFoldContentProps {
/** The child nodes */
children?: React.ReactNode;
}
/**
* Group container for RadioTile components with form-like behavior
*/
interface TileGroupProps<T = string | number>
extends Omit<React.HTMLAttributes<HTMLFieldSetElement>, "onChange"> {
/** Collection of RadioTile components to render in the group */
children?: React.ReactNode;
/** Optional className to be applied to the container node */
className?: string;
/** The value of RadioTile to be selected by default */
defaultSelected?: T;
/** Specify whether the group is disabled */
disabled?: boolean;
/** Optional legend for this group */
legend?: string;
/** Specify the name of the underlying input nodes (required) */
name: string;
/** Optional onChange hook that is called whenever the value of the group changes */
onChange?: (selection: T, name: string, evt: unknown) => void;
/** Specify the value that is currently selected in the group */
valueSelected?: T;
/** True to specify if input selection in group is required */
required?: boolean;
}Usage Examples:
import {
Tile,
ClickableTile,
SelectableTile,
ExpandableTile,
TileAboveTheFoldContent,
TileBelowTheFoldContent,
TileGroup
} from "@carbon/react";
import { ArrowRight, Add } from "@carbon/react/icons";
// Basic tile for grouping content
<Tile>
<h3>Product Overview</h3>
<p>This product offers comprehensive features for your business needs.</p>
</Tile>
// Clickable tile as a link
<ClickableTile href="/product-details" renderIcon={ArrowRight}>
<h4>Learn More</h4>
<p>Discover all the features and benefits.</p>
</ClickableTile>
// Clickable tile as a button
<ClickableTile
onClick={() => console.log('Tile clicked')}
renderIcon={Add}
>
<h4>Add New Item</h4>
<p>Click to create a new item.</p>
</ClickableTile>
// Selectable tile with checkbox behavior
<SelectableTile
id="option-1"
selected={isSelected}
onChange={(event, selected, id) => {
setIsSelected(selected);
}}
>
<h4>Premium Plan</h4>
<p>Advanced features for enterprise customers.</p>
</SelectableTile>
// Expandable tile with collapsible content
<ExpandableTile
expanded={isExpanded}
tileCollapsedIconText="Expand to see more details"
tileExpandedIconText="Collapse details"
tileCollapsedLabel="Show more"
tileExpandedLabel="Show less"
>
<TileAboveTheFoldContent>
<h4>Service Details</h4>
<p>Basic information about our service offering.</p>
</TileAboveTheFoldContent>
<TileBelowTheFoldContent>
<p>Additional details about pricing, features, and implementation process.</p>
<ul>
<li>24/7 Support</li>
<li>Custom Integration</li>
<li>Advanced Analytics</li>
</ul>
</TileBelowTheFoldContent>
</ExpandableTile>
// Tile group for radio button-like selection (requires RadioTile components)
<TileGroup
name="plan-selection"
legend="Choose your plan"
valueSelected={selectedPlan}
onChange={(selection, name, event) => {
setSelectedPlan(selection);
}}
>
<RadioTile value="basic" id="basic-plan">
<h4>Basic Plan</h4>
<p>Essential features for small teams</p>
</RadioTile>
<RadioTile value="premium" id="premium-plan">
<h4>Premium Plan</h4>
<p>Advanced features for growing businesses</p>
</RadioTile>
</TileGroup>Aspect ratio container for maintaining consistent proportions across different screen sizes.
/**
* Aspect ratio container component for maintaining consistent content proportions
*/
interface AspectRatioProps {
/** Provide a custom component or string to be rendered as the outermost node */
as?: React.ElementType;
/** Specify a class name for the outermost node of the component */
className?: string;
/** Specify the ratio to be used by the aspect ratio container */
ratio?:
| "1x1"
| "2x3"
| "3x2"
| "3x4"
| "4x3"
| "1x2"
| "2x1"
| "9x16"
| "16x9";
/** Content to be displayed within the aspect ratio container */
children?: React.ReactNode;
}Usage Examples:
import { AspectRatio } from "@carbon/react";
// Square aspect ratio for profile images
<AspectRatio ratio="1x1">
<img src="profile.jpg" alt="User profile" />
</AspectRatio>
// Video aspect ratio
<AspectRatio ratio="16x9">
<video controls>
<source src="presentation.mp4" type="video/mp4" />
</video>
</AspectRatio>
// Portrait aspect ratio for mobile mockups
<AspectRatio ratio="9x16">
<div className="mobile-mockup">
<h3>Mobile App Preview</h3>
<p>App interface content</p>
</div>
</AspectRatio>
// Custom element type
<AspectRatio as="section" ratio="3x2" className="hero-banner">
<div className="hero-content">
<h1>Welcome to our platform</h1>
<p>Discover amazing features</p>
</div>
</AspectRatio>
// Grid layout with consistent aspect ratios
<Grid>
<Row>
<Column lg={4}>
<AspectRatio ratio="4x3">
<Tile>
<h3>Feature 1</h3>
<p>Description of feature 1</p>
</Tile>
</AspectRatio>
</Column>
<Column lg={4}>
<AspectRatio ratio="4x3">
<Tile>
<h3>Feature 2</h3>
<p>Description of feature 2</p>
</Tile>
</AspectRatio>
</Column>
</Row>
</Grid>Common patterns for combining tiles with other Carbon components.
// Tiles in a grid layout for dashboard cards
<Grid>
<Row>
<Column lg={4}>
<ClickableTile href="/analytics" renderIcon={ArrowRight}>
<h4>Analytics Dashboard</h4>
<p>View detailed analytics and reports</p>
<Tag type="green">Active</Tag>
</ClickableTile>
</Column>
<Column lg={4}>
<ClickableTile href="/settings" renderIcon={ArrowRight}>
<h4>Account Settings</h4>
<p>Manage your account preferences</p>
</ClickableTile>
</Column>
</Row>
</Grid>
// Selectable tiles for configuration options
<FormGroup legendText="Select deployment options">
<SelectableTile
id="auto-deploy"
selected={options.autoDeploy}
onChange={(event, selected) => setOptions({...options, autoDeploy: selected})}
>
<h4>Automatic Deployment</h4>
<p>Deploy changes automatically on push</p>
</SelectableTile>
<SelectableTile
id="manual-deploy"
selected={options.manualDeploy}
onChange={(event, selected) => setOptions({...options, manualDeploy: selected})}
>
<h4>Manual Deployment</h4>
<p>Require manual approval for deployments</p>
</SelectableTile>
</FormGroup>
// Expandable tiles for FAQ or help content
<Stack gap={4}>
<ExpandableTile
tileCollapsedLabel="Show answer"
tileExpandedLabel="Hide answer"
>
<TileAboveTheFoldContent>
<h4>How do I reset my password?</h4>
</TileAboveTheFoldContent>
<TileBelowTheFoldContent>
<p>You can reset your password by clicking the "Forgot Password" link on the login page...</p>
<Button kind="ghost" size="sm">Reset Password</Button>
</TileBelowTheFoldContent>
</ExpandableTile>
<ExpandableTile
tileCollapsedLabel="Show answer"
tileExpandedLabel="Hide answer"
>
<TileAboveTheFoldContent>
<h4>How do I contact support?</h4>
</TileAboveTheFoldContent>
<TileBelowTheFoldContent>
<p>Our support team is available 24/7 through multiple channels...</p>
<ButtonSet>
<Button kind="secondary" size="sm">Email Support</Button>
<Button kind="primary" size="sm">Live Chat</Button>
</ButtonSet>
</TileBelowTheFoldContent>
</ExpandableTile>
</Stack>