[eric] dashboard: empty state shows the literal chat bubble glyph, icon extracted for reuse

This commit is contained in:
ciregenz
2026-06-04 11:31:06 -07:00
parent ad75228abe
commit aaed2c5716
3 changed files with 31 additions and 18 deletions
@@ -0,0 +1,19 @@
import React from 'react';
// Custom near-circular speech bubble with a teardrop tail at the
// bottom-left. The bubble body is a rounded square with corner radius
// ~half the body size, so it reads as a circle. Matches Image #57; MUI
// rounded chat glyphs either fill the bubble or omit the tail.
export default function ChatBubbleTeardrop(props: { sx?: { fontSize?: number } }) {
const size = props.sx?.fontSize ?? 18;
return (
<svg
width={size} height={size} viewBox="0 0 24 24"
fill="none" stroke="currentColor" strokeWidth={2}
strokeLinecap="round" strokeLinejoin="round"
style={{ display: 'block' }}
>
<path d="M 8 3 H 16 A 5 5 0 0 1 21 8 V 13 A 5 5 0 0 1 16 18 H 11 L 6 22 L 8 18 A 5 5 0 0 1 3 13 V 8 A 5 5 0 0 1 8 3 Z" />
</svg>
);
}
@@ -9,23 +9,8 @@ import { styled } from '@mui/material/styles';
import AddRounded from '@mui/icons-material/AddRounded';
import HistoryRounded from '@mui/icons-material/HistoryRounded';
// Custom near-circular speech bubble with a teardrop tail at the
// bottom-left. The bubble body is a rounded square with corner radius
// ~half the body size, so it reads as a circle. Matches Image #57; MUI
// rounded chat glyphs either fill the bubble or omit the tail.
function ChatBubbleTeardrop(props: { sx?: { fontSize?: number } }) {
const size = props.sx?.fontSize ?? 18;
return (
<svg
width={size} height={size} viewBox="0 0 24 24"
fill="none" stroke="currentColor" strokeWidth={2}
strokeLinecap="round" strokeLinejoin="round"
style={{ display: 'block' }}
>
<path d="M 8 3 H 16 A 5 5 0 0 1 21 8 V 13 A 5 5 0 0 1 16 18 H 11 L 6 22 L 8 18 A 5 5 0 0 1 3 13 V 8 A 5 5 0 0 1 8 3 Z" />
</svg>
);
}
import ChatBubbleTeardrop from './ChatBubbleTeardrop';
// Collapsed-row buttons hop up one after another when the toolbar appears.
const popIn = (i: number) => ({
animation: `toolbar-pop 0.4s cubic-bezier(0.2, 1.4, 0.4, 1) ${i * 55}ms both`,
@@ -2,6 +2,7 @@ import React from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import type { ClaudeTokens } from '@/shared/styles/claudeTokens';
import ChatBubbleTeardrop from '../ChatBubbleTeardrop';
const DashboardEmptyState: React.FC<{ c: ClaudeTokens }> = ({ c }) => (
<Box
@@ -22,6 +23,9 @@ const DashboardEmptyState: React.FC<{ c: ClaudeTokens }> = ({ c }) => (
<Typography
sx={{
fontSize: '0.9rem',
display: 'inline-flex',
alignItems: 'center',
gap: 0.7,
background: `linear-gradient(90deg, ${c.text.ghost} 0%, ${c.text.ghost} 40%, ${c.text.primary} 50%, ${c.text.ghost} 60%, ${c.text.ghost} 100%)`,
backgroundSize: '200% 100%',
WebkitBackgroundClip: 'text',
@@ -31,7 +35,12 @@ const DashboardEmptyState: React.FC<{ c: ClaudeTokens }> = ({ c }) => (
animation: 'empty-state-shimmer 6s linear infinite',
}}
>
Click the chat bubble below to launch your first agent
Click the
{/* Literal toolbar glyph; the shimmer's transparent color would hide it, so reset color here. */}
<Box component="span" sx={{ display: 'inline-flex', color: c.text.tertiary }}>
<ChatBubbleTeardrop sx={{ fontSize: 15 }} />
</Box>
below to launch your first agent
</Typography>
</Box>
);