diff --git a/src/__tests__/renderer/components/UsageDashboard/EmptyState.test.tsx b/src/__tests__/renderer/components/UsageDashboard/EmptyState.test.tsx
new file mode 100644
index 00000000..40868a77
--- /dev/null
+++ b/src/__tests__/renderer/components/UsageDashboard/EmptyState.test.tsx
@@ -0,0 +1,181 @@
+/**
+ * Tests for EmptyState component
+ *
+ * Verifies:
+ * - Renders empty state container with correct test ID
+ * - Displays chart icon illustration
+ * - Shows default title and message
+ * - Supports custom title and message
+ * - Applies theme colors properly
+ * - Theme-aware styling for all elements
+ */
+
+import { describe, it, expect } from 'vitest';
+import { render, screen } from '@testing-library/react';
+import React from 'react';
+import { EmptyState } from '../../../../renderer/components/UsageDashboard/EmptyState';
+import { THEMES } from '../../../../shared/themes';
+
+// Test themes
+const darkTheme = THEMES['dracula'];
+const lightTheme = THEMES['solarized-light'];
+
+describe('EmptyState', () => {
+ describe('Rendering', () => {
+ it('renders the empty state container with correct test ID', () => {
+ render();
+
+ expect(screen.getByTestId('usage-dashboard-empty')).toBeInTheDocument();
+ });
+
+ it('renders the chart icon illustration', () => {
+ render();
+
+ // The container should have the icon (BarChart3 renders as svg)
+ const container = screen.getByTestId('usage-dashboard-empty');
+ const svgs = container.querySelectorAll('svg');
+
+ // Should have at least 2 svgs: main icon and decorative bars
+ expect(svgs.length).toBeGreaterThanOrEqual(2);
+ });
+
+ it('displays the default title', () => {
+ render();
+
+ expect(screen.getByText('No usage data yet')).toBeInTheDocument();
+ });
+
+ it('displays the default message', () => {
+ render();
+
+ expect(screen.getByText('Start using Maestro to see your stats!')).toBeInTheDocument();
+ });
+ });
+
+ describe('Custom Content', () => {
+ it('supports custom title', () => {
+ render(
+
+ );
+
+ expect(screen.getByText('No data for this period')).toBeInTheDocument();
+ expect(screen.queryByText('No usage data yet')).not.toBeInTheDocument();
+ });
+
+ it('supports custom message', () => {
+ render(
+
+ );
+
+ expect(screen.getByText('Try selecting a different time range.')).toBeInTheDocument();
+ expect(screen.queryByText('Start using Maestro to see your stats!')).not.toBeInTheDocument();
+ });
+
+ it('supports both custom title and message', () => {
+ render(
+
+ );
+
+ expect(screen.getByText('Custom Title')).toBeInTheDocument();
+ expect(screen.getByText('Custom message for testing.')).toBeInTheDocument();
+ });
+ });
+
+ describe('Theme Styling', () => {
+ it('applies theme textDim color to container', () => {
+ render();
+
+ const container = screen.getByTestId('usage-dashboard-empty');
+ expect(container).toHaveStyle({ color: darkTheme.colors.textDim });
+ });
+
+ it('applies theme textMain color to title', () => {
+ render();
+
+ const title = screen.getByText('No usage data yet');
+ expect(title).toHaveStyle({ color: darkTheme.colors.textMain });
+ });
+
+ it('works with light theme', () => {
+ render();
+
+ const container = screen.getByTestId('usage-dashboard-empty');
+ expect(container).toHaveStyle({ color: lightTheme.colors.textDim });
+
+ const title = screen.getByText('No usage data yet');
+ expect(title).toHaveStyle({ color: lightTheme.colors.textMain });
+ });
+ });
+
+ describe('Layout', () => {
+ it('uses flexbox centering layout', () => {
+ render();
+
+ const container = screen.getByTestId('usage-dashboard-empty');
+ expect(container).toHaveClass('flex');
+ expect(container).toHaveClass('flex-col');
+ expect(container).toHaveClass('items-center');
+ expect(container).toHaveClass('justify-center');
+ });
+
+ it('has gap between icon and text', () => {
+ render();
+
+ const container = screen.getByTestId('usage-dashboard-empty');
+ expect(container).toHaveClass('gap-4');
+ });
+
+ it('has full height container', () => {
+ render();
+
+ const container = screen.getByTestId('usage-dashboard-empty');
+ expect(container).toHaveClass('h-full');
+ });
+ });
+
+ describe('Icon Styling', () => {
+ it('renders decorative svg with theme-aware fills', () => {
+ render();
+
+ const container = screen.getByTestId('usage-dashboard-empty');
+ const rects = container.querySelectorAll('rect');
+
+ // The decorative bars should have rect elements
+ expect(rects.length).toBeGreaterThan(0);
+
+ // Check that rects use the theme color
+ rects.forEach((rect) => {
+ expect(rect.getAttribute('fill')).toBe(darkTheme.colors.textDim);
+ });
+ });
+ });
+
+ describe('Accessibility', () => {
+ it('has a data-testid for testing', () => {
+ render();
+
+ expect(screen.getByTestId('usage-dashboard-empty')).toBeInTheDocument();
+ });
+
+ it('text is visible and readable', () => {
+ render();
+
+ const title = screen.getByText('No usage data yet');
+ const message = screen.getByText('Start using Maestro to see your stats!');
+
+ // Text should be in the document and visible
+ expect(title).toBeVisible();
+ expect(message).toBeVisible();
+ });
+ });
+});
diff --git a/src/renderer/components/UsageDashboard/EmptyState.tsx b/src/renderer/components/UsageDashboard/EmptyState.tsx
new file mode 100644
index 00000000..25dea65b
--- /dev/null
+++ b/src/renderer/components/UsageDashboard/EmptyState.tsx
@@ -0,0 +1,97 @@
+/**
+ * EmptyState
+ *
+ * Displays a friendly empty state message when no usage data exists.
+ * Used in the Usage Dashboard to indicate that the user should start
+ * using Maestro to generate stats.
+ *
+ * Features:
+ * - Theme-aware styling with inline styles
+ * - Subtle chart illustration/icon
+ * - Friendly, encouraging message
+ * - Reusable component with customizable message
+ */
+
+import React from 'react';
+import { BarChart3 } from 'lucide-react';
+import type { Theme } from '../../types';
+
+interface EmptyStateProps {
+ /** Current theme for styling */
+ theme: Theme;
+ /** Optional custom title (default: "No usage data yet") */
+ title?: string;
+ /** Optional custom message (default: "Start using Maestro to see your stats!") */
+ message?: string;
+}
+
+export function EmptyState({
+ theme,
+ title = 'No usage data yet',
+ message = 'Start using Maestro to see your stats!',
+}: EmptyStateProps) {
+ return (
+
+ {/* Subtle chart illustration */}
+
+ {/* Main chart icon */}
+
+
+ {/* Decorative subtle bars for visual interest */}
+
+
+
+ {/* Message text */}
+
+
+ {title}
+
+
+ {message}
+
+
+
+ );
+}
+
+export default EmptyState;
diff --git a/src/renderer/components/UsageDashboard/UsageDashboardModal.tsx b/src/renderer/components/UsageDashboard/UsageDashboardModal.tsx
index 0384313b..999ddd19 100644
--- a/src/renderer/components/UsageDashboard/UsageDashboardModal.tsx
+++ b/src/renderer/components/UsageDashboard/UsageDashboardModal.tsx
@@ -21,6 +21,7 @@ import { AgentComparisonChart } from './AgentComparisonChart';
import { SourceDistributionChart } from './SourceDistributionChart';
import { DurationTrendsChart } from './DurationTrendsChart';
import { AutoRunStats } from './AutoRunStats';
+import { EmptyState } from './EmptyState';
import type { Theme } from '../../types';
import { useLayerStack } from '../../contexts/LayerStackContext';
import { MODAL_PRIORITIES } from '../../constants/modalPriorities';
@@ -377,22 +378,8 @@ export function UsageDashboardModal({
) : !data || (data.totalQueries === 0 && data.bySource.user === 0 && data.bySource.auto === 0) ? (
- /* Empty State */
-
-
-
-
- No usage data yet
-
-
- Start using Maestro to see your stats!
-
-
-
+ /* Empty State Component */
+
) : (
{/* View-specific content based on viewMode */}