import type { Meta, StoryObj } from 'storybook-solidjs-vite'; import { createSignal } from 'solid-js'; import { Message, MessageAvatar, MessageContent, MessageActions, FeedbackBar, Button, } from '../index'; import { Tooltip } from '../ui/tooltip'; import { Copy, ThumbsUp, ThumbsDown, RefreshCw, Share, Bookmark, Check } from 'lucide-solid'; const meta: Meta = { title: 'Examples/Message Actions', parameters: { layout: 'padded' }, }; export default meta; type Story = StoryObj; export const HoverActions: Story = { name: 'Actions on Hover', render: () => (

Hover over the assistant message to see action buttons appear.

How do I handle errors in async Rust functions?
{`In Rust, async functions return \`Result\` types just like sync functions. The \`?\` operator works seamlessly: \`\`\`rust async fn fetch_user(id: u64) -> Result { let response = client.get(&format!("/users/{}", id)) .send() .await?; // propagates reqwest::Error let user = response .json::() .await?; // propagates deserialization error Ok(user) } \`\`\` Use \`anyhow::Result\` for applications and \`thiserror\` for libraries to define custom error types.`}
), }; export const AlwaysVisible: Story = { name: 'Always Visible Actions', render: () => (
{`To install Tailwind CSS v4 in a Vite project: \`\`\`bash pnpm add tailwindcss @tailwindcss/vite \`\`\` Then add the plugin to your \`vite.config.ts\`: \`\`\`typescript import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ plugins: [tailwindcss()], }); \`\`\` Import Tailwind in your main CSS file: \`\`\`css @import "tailwindcss"; \`\`\``}
), }; export const WithCopyConfirmation: Story = { name: 'Copy with Confirmation', render: () => { const [copied, setCopied] = createSignal(false); const handleCopy = () => { setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (
The current LTS version of Node.js is 22.x, which includes built-in support for the fetch API, test runner, and watch mode.
); }, }; export const WithFeedbackBar: Story = { name: 'Feedback Bar', render: () => { const [showFeedback, setShowFeedback] = createSignal(true); return (
{`Here are 3 ways to debounce in JavaScript: 1. **setTimeout approach** -- simple but manual cleanup 2. **lodash.debounce** -- battle-tested, configurable leading/trailing 3. **AbortController** -- modern, cancellable, works with fetch`} {showFeedback() && ( setShowFeedback(false)} /> )}
); }, }; export const FullExample: Story = { name: 'Full Example', render: () => { const [copied, setCopied] = createSignal(false); const [showFeedback, setShowFeedback] = createSignal(true); const handleCopy = () => { setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (

Everything combined — avatar, markdown, built-in copy/regenerate plus custom Share & Bookmark (with copy→check confirmation), and a Feedback Bar below.

{`Use \`anyhow::Result\` for application code and \`thiserror\` for libraries: \`\`\`rust async fn fetch_user(id: u64) -> anyhow::Result { let user = client.get(&format!("/users/{}", id)).send().await?.json().await?; Ok(user) } \`\`\` The \`?\` operator propagates errors from any \`Result\`-returning call.`} {showFeedback() && ( setShowFeedback(false)} /> )}
); }, };