diff --git a/packages/cli/src/ui/components/shared/Card.test.tsx b/packages/cli/src/ui/components/shared/Card.test.tsx
new file mode 100644
index 0000000000..579a0f1e94
--- /dev/null
+++ b/packages/cli/src/ui/components/shared/Card.test.tsx
@@ -0,0 +1,74 @@
+/**
+ * @license
+ * Copyright 2026 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { render } from '../../../test-utils/render.js';
+import { Card } from './Card.js';
+import { Text } from 'ink';
+import { describe, it, expect } from 'vitest';
+
+describe('Card', () => {
+ it.each([
+ {
+ variant: 'warning',
+ title: 'Gemini CLI update available',
+ suffix: '0.26.0 → 0.27.0',
+ prefix: true,
+ body: 'Installed via Homebrew. Please update with "brew upgrade gemini-cli".',
+ },
+ {
+ variant: 'information',
+ title: 'Delegate to agent',
+ suffix: "Delegating to agent 'cli_help'",
+ prefix: true,
+ body: '🤖💭 Execution limit reached (ERROR_NO_COMPLETE_TASK_CALL). Attempting one final recovery turn with a grace period.',
+ },
+ {
+ variant: 'error',
+ title: 'Error',
+ suffix: '429 You exceeded your current quota',
+ prefix: true,
+ body: 'Go to https://aistudio.google.com/apikey to upgrade your quota tier, or submit a quota increase request in https://ai.google.dev/gemini-api/docs/rate-limits',
+ },
+ {
+ variant: 'confirmation',
+ title: 'Shell',
+ suffix: 'node -v && which gemini',
+ prefix: true,
+ body: "ls /usr/local/bin | grep 'xattr'",
+ },
+ {
+ variant: 'success',
+ title: 'ReadFolder',
+ suffix: '/usr/local/bin',
+ prefix: true,
+ body: 'Listed 39 item(s).',
+ },
+ ])(
+ 'renders a $variant card with prefix=$prefix',
+ ({ variant, title, suffix, prefix, body }) => {
+ const { lastFrame } = render(
+
+ {body}
+ ,
+ );
+
+ const output = lastFrame();
+
+ // eslint-disable-next-line no-console
+ console.log(output);
+
+ expect(output).toMatchSnapshot();
+ },
+ );
+});
+
+export type { CardProps };
diff --git a/packages/cli/src/ui/components/shared/Card.tsx b/packages/cli/src/ui/components/shared/Card.tsx
new file mode 100644
index 0000000000..6e21079351
--- /dev/null
+++ b/packages/cli/src/ui/components/shared/Card.tsx
@@ -0,0 +1,142 @@
+/**
+ * @license
+ * Copyright 2026 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import type React from 'react';
+import { Box, Text } from 'ink';
+import { theme } from '../../semantic-colors.js';
+import { TOOL_STATUS } from '../../constants.js';
+
+/**
+ * Props for the Card component.
+ */
+export interface CardProps {
+ /** The main title of the card. */
+ title: string;
+ /** Optional text to display after the title (e.g., version, status). */
+ suffix?: string;
+ /** Optional icon or text to display before the title. */
+ prefix?: boolean;
+ /** The content to be displayed inside the card. */
+ children?: React.ReactNode;
+ /** The styling and intent of the card. */
+ variant?: 'information' | 'success' | 'warning' | 'error' | 'confirmation';
+ width?: number | string;
+}
+
+const CardDisplay: React.FC = ({
+ variant = 'information',
+ title,
+ prefix = true,
+ suffix,
+ children,
+}) => {
+ const getColors = () => {
+ switch (variant) {
+ case 'error':
+ return { border: theme.status.error, text: theme.status.error };
+ case 'warning':
+ return { border: theme.status.warning, text: theme.status.warning };
+ case 'success':
+ return { border: theme.status.success, text: theme.status.success };
+ case 'confirmation':
+ return { border: theme.border.focused, text: theme.text.link };
+ default:
+ return { border: theme.border.default, text: theme.text.primary };
+ }
+ };
+
+ const getGlyph = () => {
+ switch (variant) {
+ case 'error':
+ return TOOL_STATUS.ERROR;
+ case 'success':
+ return TOOL_STATUS.SUCCESS;
+ case 'warning':
+ return TOOL_STATUS.WARNING;
+ case 'confirmation':
+ return TOOL_STATUS.CONFIRMING;
+ default:
+ return TOOL_STATUS.INFORMATION;
+ }
+ };
+
+ const colors = getColors();
+ const glyph = getGlyph();
+
+ return (
+
+
+ {/* Top border section */}
+
+ {/* Label */}
+
+
+ {prefix && {glyph}}
+
+ {title}
+
+ {suffix && (
+
+ {suffix}
+
+ )}
+
+ {/* Top border after text */}
+
+
+ {/* Right border */}
+
+
+ {/* Content area */}
+
+ {children}
+
+
+ );
+};
+
+export const Card: React.FC = ({
+ title,
+ prefix,
+ suffix,
+ children,
+ variant,
+}) => (
+
+ {children}
+
+);