> ## Documentation Index
> Fetch the complete documentation index at: https://docs.taho.is/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing Ingredients

> How to define preview entries for your ratatui widgets using the Ingredient trait.

An **ingredient** is one preview: a specific widget configuration with mock data. You implement the `Ingredient` trait for a struct, and the Pantry renders it in the preview pane with navigation, description, and prop documentation.

## The Ingredient trait

Four methods are required:

| Method     | Purpose                                                                                  |
| ---------- | ---------------------------------------------------------------------------------------- |
| `group()`  | Widget name, shown as a collapsible heading in the sidebar. Shared values nest together. |
| `name()`   | Variant label, the leaf node under the group.                                            |
| `source()` | Module path shown as a breadcrumb in the preview pane.                                   |
| `render()` | Draw the widget into the preview area.                                                   |

Optional methods with defaults:

| Method           | Default     | Purpose                                                          |
| ---------------- | ----------- | ---------------------------------------------------------------- |
| `tab()`          | `"Widgets"` | Top-level tab: `"Widgets"`, `"Panes"`, `"Views"`, or `"Styles"`. |
| `description()`  | `""`        | One-line summary displayed in the preview pane.                  |
| `props()`        | `&[]`       | `PropInfo` slice documenting the widget's configurable surface.  |
| `interactive()`  | `false`     | Whether the preview captures keyboard and mouse input.           |
| `animated()`     | `false`     | Whether the ingredient needs periodic redraws (33ms tick).       |
| `handle_key()`   | `false`     | Process a key event while focused.                               |
| `handle_mouse()` | `false`     | Process a mouse event while focused.                             |

## Basic ingredient

A static ingredient is a unit struct with mock data:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tui_pantry::{Ingredient, PropInfo};

struct GaugeDefault;

impl Ingredient for GaugeDefault {
    fn group(&self) -> &str { "Resource Gauge" }
    fn name(&self) -> &str { "Default" }
    fn source(&self) -> &str { "my_crate::widgets::resource_gauge" }

    fn description(&self) -> &str {
        "Horizontal bar showing resource utilization with color thresholds"
    }

    fn props(&self) -> &[PropInfo] {
        &[
            PropInfo { name: "label", ty: "&str", description: "Resource name" },
            PropInfo { name: "ratio", ty: "f64", description: "Fill from 0.0 to 1.0" },
        ]
    }

    fn render(&self, area: Rect, buf: &mut Buffer) {
        ResourceGauge::new("CPU", 0.34).render(area, buf);
    }
}
```

Each ingredient module exports a factory function:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
pub fn ingredients() -> Vec<Box<dyn Ingredient>> {
    vec![Box::new(GaugeDefault), Box::new(GaugeHigh)]
}
```

## Interactive ingredient

Set `interactive()` to `true` to receive keyboard and mouse input when the preview pane has focus. Press `Enter` in the sidebar to focus an interactive ingredient. Press `Esc` to return.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
struct TableInteractive {
    selected: usize,
}

impl Ingredient for TableInteractive {
    fn group(&self) -> &str { "Node Table" }
    fn name(&self) -> &str { "Interactive" }
    fn source(&self) -> &str { "my_crate::widgets::node_table" }

    fn interactive(&self) -> bool { true }

    fn handle_key(&mut self, code: KeyCode) -> bool {
        match code {
            KeyCode::Up => { self.selected = self.selected.saturating_sub(1); true }
            KeyCode::Down => { self.selected += 1; true }
            _ => false,
        }
    }

    fn render(&self, area: Rect, buf: &mut Buffer) {
        NodeTable::new(Some(self.selected)).render(area, buf);
    }
}
```

Return `true` from `handle_key()` or `handle_mouse()` to consume the event, `false` to let the Pantry handle it.

## Tab assignment

Override `tab()` to place ingredients in a different tab:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
fn tab(&self) -> &str { "Panes" }   // composed sections
fn tab(&self) -> &str { "Views" }   // full-page layouts
```

## Feature gating

Gate ingredient modules behind `#[cfg(feature = "tui-pantry")]` so they don't compile into production:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
// widgets/gauge/mod.rs
#[cfg(feature = "tui-pantry")]
#[path = "gauge.ingredient.rs"]
pub mod ingredient;
```

For flat crates, gate at the crate root:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
// lib.rs
#[cfg(feature = "tui-pantry")]
pub mod ingredient;
```

## Registration

Declare your ingredient modules in `pantry.toml`:

```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
[ingredients]
source = "my_crate"
modules = [
    "widgets::gauge",
    "widgets::node_table",
]
```

Each entry expands at compile time to `my_crate::widgets::gauge::ingredient::ingredients()` via the `pantry_ingredients!()` proc macro. The entry point uses this automatically:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
// examples/widget_preview/main.rs
fn main() -> std::io::Result<()> {
    tui_pantry::run!()
}
```

For crates without an `[ingredients]` section in `pantry.toml`, pass the factory directly:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
fn main() -> std::io::Result<()> {
    tui_pantry::run!(my_crate::ingredient::ingredients())
}
```

For multi-crate workspaces, see the [array-of-tables syntax](/tui-pantry/configuration#ingredients) in the configuration reference.

## Example pantry

The TUI Pantry repository includes a complete [example pantry](https://github.com/taho-inc/tui-pantry/tree/main/examples/example-pantry) showcasing ratatui's stock widgets with a Catppuccin Mocha theme. It demonstrates all four tabs (Widgets, Panes, Views, and Styles) and serves as a reference for the full integration pattern.

Run it with:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
cargo run -p example-pantry
```
