# Brainfish Components

Brainfish Components is a React component library that supports both bulk imports and individual component imports (similar to shadcn/ui) for optimal tree-shaking and bundle size optimization.

## Installation

```bash
npm install @brainfish-ai/components
# or
yarn add @brainfish-ai/components
```

## Usage

### Individual Component Imports (Recommended)

Import only the components you need for optimal bundle size:

```tsx
// Import individual UI components
import { Button } from '@brainfish-ai/components/ui/button';
import { Dialog } from '@brainfish-ai/components/ui/dialog';
import { Input } from '@brainfish-ai/components/ui/input';

// Import other components
import { ChatSearch } from '@brainfish-ai/components/chat-search';
import { DatePicker } from '@brainfish-ai/components/date-picker';
import { Filter } from '@brainfish-ai/components/filter';

function MyApp() {
  return (
    <div>
      <Button>Click me</Button>
      <Input placeholder="Enter text..." />
      <DatePicker />
    </div>
  );
}
```

### Bulk Import (Legacy)

Import all components at once (larger bundle size):

```tsx
import { Button, Dialog, Input, ChatSearch } from '@brainfish-ai/components';
```

### Available Individual Imports

#### UI Components
- `@brainfish-ai/components/ui/button`
- `@brainfish-ai/components/ui/card`
- `@brainfish-ai/components/ui/collapsible`
- `@brainfish-ai/components/ui/command`
- `@brainfish-ai/components/ui/dialog`
- `@brainfish-ai/components/ui/dropdown-menu`
- `@brainfish-ai/components/ui/input`
- `@brainfish-ai/components/ui/label`
- `@brainfish-ai/components/ui/popover`
- `@brainfish-ai/components/ui/scroll-area`
- `@brainfish-ai/components/ui/switch`
- `@brainfish-ai/components/ui/textarea`
- `@brainfish-ai/components/ui/tooltip`

#### Complex Components
- `@brainfish-ai/components/chat-search`
- `@brainfish-ai/components/combobox`
- `@brainfish-ai/components/date-picker`
- `@brainfish-ai/components/feedback`
- `@brainfish-ai/components/filter`
- `@brainfish-ai/components/generating-star`
- `@brainfish-ai/components/markdown`
- `@brainfish-ai/components/select`

### Styles

Don't forget to import the CSS:

```tsx
import '@brainfish-ai/components/styles.css';
```

## Development

### Getting started

```bash
yarn install
```

### Developing

To start developing run:

```bash
yarn start
```

This will build a version of your library, run the watcher and also run Storybook.
To open Storybook manually open your Browser and navigate to [http://localhost:6006](http://localhost:6006).
Start developing your components in `src/components` folder and update the `src/index.js` file accordingly.
Always provide an `YourComponent.story.tsx` file, so your component will show up in Storybook.

### Building

Build the library with individual component exports:

```bash
yarn build:components
```

---

## Development Guide

This section explains the architecture and patterns used in this component library to help new developers get started quickly.

### Color System

Our color system is built on CSS custom properties (variables) defined in `src/global.css`. All variables use the `--bfc-` prefix (Brainfish Components).

#### Color Token Scale

Colors follow a 100-1000 scale where lower numbers are lighter and higher numbers are darker:

```css
--bfc-v2-color-blue-100: #e9f2fe;  /* lightest */
--bfc-v2-color-blue-500: #4688ec;  /* mid-tone */
--bfc-v2-color-blue-1000: #1c2b42; /* darkest */
```

#### Available Color Palettes

| Palette   | CSS Variable Pattern              |
|-----------|-----------------------------------|
| Mono      | `--bfc-v2-color-mono-{100-1000}`  |
| Red       | `--bfc-v2-color-red-{100-1000}`   |
| Orange    | `--bfc-v2-color-orange-{100-1000}`|
| Yellow    | `--bfc-v2-color-yellow-{100-1000}`|
| Lime      | `--bfc-v2-color-lime-{100-1000}`  |
| Green     | `--bfc-v2-color-green-{100-1000}` |
| Blue      | `--bfc-v2-color-blue-{100-1000}`  |
| Teal      | `--bfc-v2-color-teal-{100-1000}`  |
| Purple    | `--bfc-v2-color-purple-{100-1000}`|
| Magenta   | `--bfc-v2-color-magenta-{100-1000}`|

#### Semantic Color Tokens

Instead of using raw color values, use semantic tokens that adapt to themes:

| Token                    | Purpose                        |
|--------------------------|--------------------------------|
| `--bfc-primary`          | Primary brand color            |
| `--bfc-background`       | Page background                |
| `--bfc-foreground`       | Primary text color             |
| `--bfc-muted`            | Subdued backgrounds            |
| `--bfc-muted-foreground` | Subdued text                   |
| `--bfc-border`           | Border color                   |
| `--bfc-destructive-bg`   | Error/danger backgrounds       |
| `--bfc-success-bg`       | Success state backgrounds      |

#### Dark Mode

Dark mode is activated by adding the `.dark` class to the <html> element. The color scale is automatically inverted (100 becomes the darkest, 1000 becomes the lightest), ensuring consistent contrast in both themes.

```html
<!-- Light mode (default) -->
<html>...</html>

<!-- Dark mode -->
<html class="dark">...</html>
```

### Tailwind CSS Integration

We use Tailwind CSS with a custom preset that maps our color system to Tailwind utilities.

#### Using the Tailwind Preset

Consumers of this library can import our Tailwind preset to use the same design tokens:

```js
// tailwind.config.js
module.exports = {
  presets: [require('@brainfish-ai/components/tailwind')],
  // ... your config
};
```

#### Semantic Color Classes

Use semantic Tailwind classes instead of raw colors:

```tsx
// Good - uses semantic colors that adapt to themes
<div className="bg-primary text-foreground border-border" />
<div className="bg-destructive text-destructive" />
<div className="bg-muted text-muted-foreground" />

// Bad - hardcoded colors won't adapt to dark mode
<div className="bg-[#a3e635] text-[#171717]" />
```

#### Typography Utilities

Custom typography classes are available for consistent text styles:

| Class          | Font Size | Use Case           |
|----------------|-----------|---------------------|
| `.heading-xxl` | 2rem      | Page titles         |
| `.heading-xl`  | 1.75rem   | Section headers     |
| `.heading-lg`  | 1.5rem    | Card headers        |
| `.heading-m`   | 1.25rem   | Subsections         |
| `.heading-sm`  | 1rem      | Small headers       |
| `.paragraph-lg`| 1rem      | Body text           |
| `.paragraph-md`| 0.875rem  | Default text        |
| `.paragraph-sm`| 0.75rem   | Captions, labels    |

#### The `cn()` Utility

Use `cn()` from `@/lib/utils` to merge Tailwind classes safely:

```tsx
import { cn } from '@/lib/utils';

// Merges classes and handles conflicts properly
<div className={cn('bg-primary p-4', isActive && 'bg-accent', className)} />
```

### Component Patterns (shadcn/ui)

Our UI components follow [shadcn/ui](https://ui.shadcn.com/) patterns and conventions.

#### Component Location

- Base UI components: `src/components/ui/`
- Complex/composite components: `src/components/`

#### Component Structure

Components use `class-variance-authority` (CVA) for variant management:

```tsx
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';

// Define variants with CVA
const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-md text-sm font-medium',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground',
        destructive: 'bg-destructive text-destructive-foreground',
        outline: 'border border-input bg-background',
      },
      size: {
        default: 'h-9 px-4 py-2',
        sm: 'h-8 px-3 text-sm',
        lg: 'h-10 px-8',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
);

// Component with forwarded ref
export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, ...props }, ref) => (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      ref={ref}
      {...props}
    />
  )
);
Button.displayName = 'Button';

export { Button, buttonVariants };
```

#### Key Conventions

1. **Always use semantic colors** - Never use raw hex values in components
2. **Forward refs** - All components should forward refs for flexibility
3. **Use `cn()` for className** - Always merge with incoming className prop
4. **Export variants** - Export the CVA variants for reuse
5. **Set displayName** - Always set `displayName` for better debugging

### Storybook Requirements

**Every component MUST have an accompanying Storybook story file.**

#### Why Stories Matter

- Enable independent component testing and development
- Serve as living documentation for the component API
- Allow visual regression testing
- Help designers and developers collaborate

#### Story File Convention

For a component `Button.tsx`, create `Button.stories.tsx` in the same directory:

```
src/components/ui/
├── button.tsx
├── button.stories.tsx  <-- Required!
└── button.test.tsx     <-- Optional unit tests
```

#### Story Structure

```tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './button';

const meta: Meta<typeof Button> = {
  title: 'UI/Button',
  component: Button,
  tags: ['autodocs'],
};

export default meta;
type Story = StoryObj<typeof Button>;

// Show all variants
export const Default: Story = {
  args: { children: 'Click me' },
};

export const Destructive: Story = {
  args: { variant: 'destructive', children: 'Delete' },
};

export const AllSizes: Story = {
  render: () => (
    <div className="flex gap-4">
      <Button size="sm">Small</Button>
      <Button size="default">Default</Button>
      <Button size="lg">Large</Button>
    </div>
  ),
};
```

#### Running Storybook

```bash
yarn storybook
```

Then open [http://localhost:6006](http://localhost:6006) in your browser.

---

## Linting and Code formating for Typescript

Linting and code formating is done via [ESLint](https://eslint.org/) and [Prettier](https://prettier.io/) using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) and
[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier).
You can modify linting rules by overriding them in the `.eslintrc.cjs` file.

```
yarn lint
```

or (if automatic fixing is possible)

```
yarn lint:fix
```

## Testing

Testing is done with [Vitest](https://vitest.dev/) and [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/)
You can refer to `Button.test.js` as an example.

```
yarn test
```

## Publishing your library to NPM

To release your library to NPM or your private Registry, make sure you have an active account at [NPM](https://www.npmjs.com/), your `.npmrc` file is correctly setup and the registry url at publishConfig in `package.json` file is set to your repository url, then:

```
yarn release
```

## Storybook

For custom layouts, styling and more information about Storybook, please refer to [Storybook](https://storybook.js.org/basics/writing-stories/) documentation.

#### Deploy Storybook to GitHub Pages

Make sure the homepage url in `package.json` file is set to your githup pages url, then:

```
yarn deploy
```

## Scripts

- `yarn start` : Only serves Storybook.
- `yarn build` : Builds your library (build can be found in `dist` folder).
- `yarn storybook:build` : Builds the static Storybook in case you want to deploy it.
- `yarn test` : Runs the tests.
- `yarn test:coverage`: Runs the test and shows the coverage.
- `yarn lint` : Runs the linter, Typescript typecheck and stylelint.
- `yarn lint:fix` : Runs the linter, Typescript typecheck and stylelint and fixes automatic fixable issues.
- `yarn eslint`: Runs only the JavaScript linter.
- `yarn eslint:fix`: Runs only the JavaScript linter and fixes automatic fixable issues.
- `yarn stylelint`: Runs only the style linter.
- `yarn stylelint:fix`: Runs only the style linter and fixes automatic fixable issues.
- `yarn check-types`: Runs typescript type checker.
- `yarn ci`: Runs Linting, tests and type checker all together.
- `yarn release` : Publishes your Library on NPM or your private Registry (depending on your config in your `.npmrc` file).
- `yarn storybook`: Same as yarn start, to serve storybook.
- `yarn storybook:build`: Generates the build for storybook in `storybook-static` folder, that can be deployed wherever you need.
- `yarn storybook:deploy`: Builds and deploys Storybook to GitHub Pages.

## Resources

### Bundler

- [Rollup.js](https://rollupjs.org/guide/en)

### Code Formatter

- [Prettier](https://prettier.io/)

### Storybook

- [Storybook](https://storybook.js.org/)

### Testing

- [Vitest](https://vitest.dev/)
- [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/)
- [@testing-library/jest-dom](https://github.com/testing-library/jest-dom)

### Linting

- [ESLint](https://eslint.org/)
- [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react)
- [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)
- [stylelint-prettier](https://github.com/prettier/stylelint-prettier)
- [stylelint-scss](https://github.com/kristerkari/stylelint-scss)

### Compiler

- [Typescript](https://www.typescriptlang.org/)
