import type { Meta, StoryObj } from 'storybook-solidjs-vite';
import { fn } from 'storybook/test';
import { FeedbackBar } from './feedback-bar';
import { componentDescription } from '../stories/docs/element-controls';
const meta = {
title: 'Solid (Advanced)/Elements/FeedbackBar',
component: FeedbackBar,
tags: ['autodocs'],
parameters: {
layout: 'padded',
docs: {
controls: { exclude: ['use:eventListener'] },
description: componentDescription([
'An inline bar that prompts the user to rate a response. It owns its own flow — it asks, optionally collects a category + comment on a not-helpful vote, then confirms with a thank-you, all in place (the way ChatGPT/Claude do it). It does **not** disappear on a vote; only the close (X) button dismisses it.',
'**When to use:** after an assistant message, to collect quick helpful / not-helpful feedback (optionally with a reason).',
'**How to use:** set a `title`; for the richer flow set `collect-detail` and pass `categories`. The vote fires `onFeedback` immediately; the optional detail fires `onSubmitDetail`; `onClose` dismisses the bar.',
'**Placement:** directly beneath a completed assistant message, or in a message action row.',
]),
},
},
argTypes: {
title: {
control: 'text',
description: 'Prompt text shown next to the rating buttons.',
},
icon: {
control: false,
description: 'Optional leading icon element shown before the title.',
},
collectDetail: {
control: 'boolean',
description: 'When on, a not-helpful vote opens an optional detail form (category chips + comment) before the thank-you.',
},
categories: {
control: 'object',
description: 'Category chips offered in the detail form.',
},
thanksMessage: {
control: 'text',
description: 'Confirmation copy shown after a vote/submit.',
},
class: {
control: 'text',
description: 'Additional CSS classes for the root element.',
},
onFeedback: {
action: 'feedback',
description: 'Fired with `value: "helpful" | "not-helpful"` immediately when a rating button is clicked (the vote is recorded even if the detail form is skipped).',
table: { category: 'Events' },
},
onSubmitDetail: {
action: 'submitDetail',
description: 'Fired with `{ value, category?, comment? }` when the optional detail form is submitted.',
table: { category: 'Events' },
},
onClose: {
action: 'close',
description: 'Fired when the close (X) button is clicked.',
table: { category: 'Events' },
},
},
args: {
title: 'Was this response helpful?',
onFeedback: fn(),
onSubmitDetail: fn(),
onClose: fn(),
},
render: (args) => ,
} satisfies Meta;
export default meta;
type Story = StoryObj;
const IMPORT = `import { FeedbackBar } from '@kitn.ai/chat';`;
const src = (code: string) => ({
parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } },
});
/** Interactive playground — tweak the controls to explore the feedback bar. */
export const Playground: Story = {
...src(` console.log('feedback:', value)}
onClose={() => {}}
/>`),
};
export const CustomTitle: Story = {
args: { title: 'Rate this answer' },
...src(` console.log('feedback:', value)} />`),
};
const SmileyIcon = () => (
);
export const WithIcon: Story = {
args: { title: 'How did I do?', icon: },
...src(`}
onFeedback={(value) => console.log('feedback:', value)}
/>`),
};
/** The full flow: a not-helpful vote opens an optional detail form (category
* chips + comment) before the thank-you. A helpful vote skips straight to thanks.
* Click 👎 to see the detail step. */
export const WithDetail: Story = {
args: {
title: 'Was this response helpful?',
collectDetail: true,
categories: ['Inaccurate', 'Not helpful', 'Unsafe', 'Other'],
},
...src(` console.log('vote:', value)}
onSubmitDetail={(d) => console.log('detail:', d)} // { value, category?, comment? }
/>`),
};
/** A custom confirmation message shown after the vote. */
export const CustomThanks: Story = {
args: { title: 'Rate this answer', thanksMessage: 'Got it — thanks for helping us improve!' },
...src(` console.log('feedback:', value)}
/>`),
};