# Table Previews

Documentation sites for data-oriented packages often need to show what a dataset looks like. Screenshots go stale, raw HTML tables lack context, and notebook-style output is tightly coupled to a specific runtime. The [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview) function solves this by generating a self-contained HTML table preview from almost any data source. It works in Python code cells, Jupyter notebooks, and (via the `{{< tbl-preview >}}` shortcode) directly in Quarto `.qmd` pages without writing any Python at all.

Each preview includes a colored type badge (Polars, Pandas, CSV, Parquet, etc.), compact dtype labels beneath every column header, row-number gutters, head/tail splitting for large tables, and automatic highlighting of missing values. The output renders identically in light mode and dark mode, requires no JavaScript, and is safe to embed in RSS feeds, emails, or static HTML.

This guide walks through every feature, starting from the simplest Python call and building up to the Quarto shortcode, file format support, and advanced display options. For interactive tables with sorting, filtering, and pagination, see the companion [Table Explorer](table-explorer.md) guide.


# Quick Start

The fastest way to preview a table is to pass a Python dictionary to [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview). No configuration or file is needed.


``` python
from great_docs import tbl_preview

tbl_preview({
    "city": ["Tokyo", "Paris", "New York"],
    "country": ["Japan", "France", "USA"],
    "population": [13960000, 2161000, 8336000],
})
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="city" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

city

<em>str</em>

</div></th>
<th id="country" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

country

<em>str</em>

</div></th>
<th id="population" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

population

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 149px">Tokyo</td>
<td class="gt_row gt_left" style="max-width: 146px">Japan</td>
<td class="gt_row gt_right" style="max-width: 169px">13960000</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 149px">Paris</td>
<td class="gt_row gt_left" style="max-width: 146px">France</td>
<td class="gt_row gt_right" style="max-width: 169px">2161000</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 149px">New York</td>
<td class="gt_row gt_left" style="max-width: 146px">USA</td>
<td class="gt_row gt_right" style="max-width: 169px">8336000</td>
</tr>
</tbody>
</table>


The result is a styled HTML table with a header banner showing the row and column count, dtype labels beneath each column name, and row numbers on the left. This single function call is all it takes to go from raw data to a polished preview.

> **Tip: Hiding the Code Cell**
>
> Most of the time you'll want to show just the table itself, not the underlying generation code. Add `#| echo: false` at the top of the code cell to hide the source and display only the rendered preview:
>
> ```` markdown
> ```{python}
> #| echo: false
> tbl_preview({"city": ["Tokyo", "Paris"], "country": ["Japan", "France"]})
> ```
> ````


# Data Sources

[tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview) accepts many different input types, so you can pass whatever data structure your project already uses. Each source type gets a distinct colored badge in the header banner, making it easy to tell at a glance what kind of data is being displayed.


## Dictionaries and Lists

The simplest inputs are column-oriented dictionaries and row-oriented lists of dictionaries. Both produce a **Table** badge and infer dtypes from the cell values.

A column-oriented dictionary (keys are column names, values are lists):


``` python
tbl_preview({"name": ["Alice", "Bob"], "score": [95.5, 82.0]})
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows2Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

name

<em>str</em>

</div></th>
<th id="score" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

score

<em>f64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 231px">Alice</td>
<td class="gt_row gt_right" style="max-width: 234px">95.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 231px">Bob</td>
<td class="gt_row gt_right" style="max-width: 234px">82</td>
</tr>
</tbody>
</table>


A list of row dictionaries (each dict is one row):


``` python
tbl_preview([
    {"name": "Alice", "score": 95.5},
    {"name": "Bob", "score": 82.0},
])
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows2Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

name

<em>str</em>

</div></th>
<th id="score" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

score

<em>f64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 231px">Alice</td>
<td class="gt_row gt_right" style="max-width: 234px">95.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 231px">Bob</td>
<td class="gt_row gt_right" style="max-width: 234px">82</td>
</tr>
</tbody>
</table>


Both styles produce identical output. Use whichever matches the data you already have.


## Polars DataFrames

If Polars is installed, pass a `pl.DataFrame` directly. The badge shows **Polars** in blue, and dtype labels are derived from the Polars schema (e.g., `i64`, `f64`, `str`).


``` python
import polars as pl

df = pl.DataFrame({
    "product": ["Widget", "Gadget", "Gizmo"],
    "price": [29.99, 49.50, 12.00],
    "in_stock": [True, False, True],
})

tbl_preview(df)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #0075FF; color: #FFFFFF; border: 1px solid #0075FF; margin-right: 8px;">Polars</span>Rows3Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="product" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

product

<em>str</em>

</div></th>
<th id="price" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

price

<em>f64</em>

</div></th>
<th id="in_stock" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

in_stock

<em>bool</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 158px">Widget</td>
<td class="gt_row gt_right" style="max-width: 142px">29.99</td>
<td class="gt_row gt_left" style="max-width: 165px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 158px">Gadget</td>
<td class="gt_row gt_right" style="max-width: 142px">49.5</td>
<td class="gt_row gt_left" style="max-width: 165px">False</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 158px">Gizmo</td>
<td class="gt_row gt_right" style="max-width: 142px">12</td>
<td class="gt_row gt_left" style="max-width: 165px">True</td>
</tr>
</tbody>
</table>


Polars dtypes are mapped to compact short labels (like `i64` for `Int64`, `f64` for `Float64`, `str` for `String`) so the column headers stay clean.


## Pandas DataFrames

Pandas DataFrames work the same way. The badge shows **Pandas** in dark purple, and dtypes come from the Pandas `.dtypes` attribute.


``` python
import pandas as pd

df = pd.DataFrame({
    "city": ["London", "Sydney", "Toronto"],
    "temp_c": [15.2, 22.8, -3.1],
    "sunny": [False, True, False],
})

tbl_preview(df)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #150458; color: #FFFFFF; border: 1px solid #150458; margin-right: 8px;">Pandas</span>Rows3Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="city" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

city

<em>str</em>

</div></th>
<th id="temp_c" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

temp_c

<em>f64</em>

</div></th>
<th id="sunny" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

sunny

<em>bool</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 159px">London</td>
<td class="gt_row gt_right" style="max-width: 156px">15.2</td>
<td class="gt_row gt_left" style="max-width: 148px">False</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 159px">Sydney</td>
<td class="gt_row gt_right" style="max-width: 156px">22.8</td>
<td class="gt_row gt_left" style="max-width: 148px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 159px">Toronto</td>
<td class="gt_row gt_right" style="max-width: 156px">-3.1</td>
<td class="gt_row gt_left" style="max-width: 148px">False</td>
</tr>
</tbody>
</table>


Both Polars and Pandas DataFrames are detected automatically (no format flag is needed).


## CSV Files

Pass a file path (as a string or `pathlib.Path`) to any supported format and [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview) reads it directly. CSV files get a warm yellow **CSV** badge:


``` python
tbl_preview("../assets/data/students.csv")
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="6" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #FFF8E1; color: #7A6200; border: 1px solid #FFF8E1; margin-right: 8px;">CSV</span>Rows10Columns5
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

name

<em>str</em>

</div></th>
<th id="subject" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

subject

<em>str</em>

</div></th>
<th id="score" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

score

<em>f64</em>

</div></th>
<th id="grade" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

grade

<em>str</em>

</div></th>
<th id="passed" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

passed

<em>bool</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 97px">Alice</td>
<td class="gt_row gt_left" style="max-width: 102px">Math</td>
<td class="gt_row gt_right" style="max-width: 86px">95.5</td>
<td class="gt_row gt_left" style="max-width: 86px">A</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 97px">Bob</td>
<td class="gt_row gt_left" style="max-width: 102px">Science</td>
<td class="gt_row gt_right" style="max-width: 86px">82</td>
<td class="gt_row gt_left" style="max-width: 86px">B</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 97px">Charlie</td>
<td class="gt_row gt_left" style="max-width: 102px">English</td>
<td class="gt_row gt_right" style="max-width: 86px">71.3</td>
<td class="gt_row gt_left" style="max-width: 86px">C</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 97px">Diana</td>
<td class="gt_row gt_left" style="max-width: 102px">History</td>
<td class="gt_row gt_right" style="max-width: 86px">60</td>
<td class="gt_row gt_left" style="max-width: 86px">D</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_left" style="max-width: 97px">Eve</td>
<td class="gt_row gt_left" style="max-width: 102px">Art</td>
<td class="gt_row gt_right" style="max-width: 86px">55.8</td>
<td class="gt_row gt_left" style="max-width: 86px">F</td>
<td class="gt_row gt_left" style="max-width: 94px">False</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">5</td>
<td class="gt_row gt_left" style="max-width: 97px">Frank</td>
<td class="gt_row gt_left" style="max-width: 102px">Math</td>
<td class="gt_row gt_right" style="max-width: 86px">88.2</td>
<td class="gt_row gt_left" style="max-width: 86px">B+</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">6</td>
<td class="gt_row gt_left" style="max-width: 97px">Grace</td>
<td class="gt_row gt_left" style="max-width: 102px">Science</td>
<td class="gt_row gt_right" style="max-width: 86px">79.9</td>
<td class="gt_row gt_left" style="max-width: 86px">C+</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">7</td>
<td class="gt_row gt_left" style="max-width: 97px">Hank</td>
<td class="gt_row gt_left" style="max-width: 102px">English</td>
<td class="gt_row gt_right" style="max-width: 86px">91</td>
<td class="gt_row gt_left" style="max-width: 86px">A-</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">8</td>
<td class="gt_row gt_left" style="max-width: 97px">Iris</td>
<td class="gt_row gt_left" style="max-width: 102px">History</td>
<td class="gt_row gt_right" style="max-width: 86px">66.4</td>
<td class="gt_row gt_left" style="max-width: 86px">D+</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">9</td>
<td class="gt_row gt_left" style="max-width: 97px">Jack</td>
<td class="gt_row gt_left" style="max-width: 102px">Art</td>
<td class="gt_row gt_right" style="max-width: 86px">73.7</td>
<td class="gt_row gt_left" style="max-width: 86px">C</td>
<td class="gt_row gt_left" style="max-width: 94px">True</td>
</tr>
</tbody>
</table>


The file is read using Polars if available, falling back to Pandas. Column dtypes are inferred from the file contents.


## TSV Files

Tab-separated files (`.tsv` or `.tab`) are auto-detected by extension. The badge shows **TSV** in green:


``` python
tbl_preview("../assets/data/products.tsv")
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="6" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #E8F5E9; color: #2E7D32; border: 1px solid #E8F5E9; margin-right: 8px;">TSV</span>Rows7Columns5
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="product" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

product

<em>str</em>

</div></th>
<th id="category" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

category

<em>str</em>

</div></th>
<th id="price" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

price

<em>f64</em>

</div></th>
<th id="stock" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

stock

<em>i64</em>

</div></th>
<th id="rating" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

rating

<em>f64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 114px">Widget</td>
<td class="gt_row gt_left" style="max-width: 114px">Electronics</td>
<td class="gt_row gt_right" style="max-width: 78px">29.99</td>
<td class="gt_row gt_right" style="max-width: 74px">150</td>
<td class="gt_row gt_right" style="max-width: 82px">4.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 114px">Gadget</td>
<td class="gt_row gt_left" style="max-width: 114px">Tools</td>
<td class="gt_row gt_right" style="max-width: 78px">49.5</td>
<td class="gt_row gt_right" style="max-width: 74px">80</td>
<td class="gt_row gt_right" style="max-width: 82px">3.8</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 114px">Gizmo</td>
<td class="gt_row gt_left" style="max-width: 114px">Kitchen</td>
<td class="gt_row gt_right" style="max-width: 78px">12</td>
<td class="gt_row gt_right" style="max-width: 74px">300</td>
<td class="gt_row gt_right" style="max-width: 82px">4.9</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 114px">Doohickey</td>
<td class="gt_row gt_left" style="max-width: 114px">Garden</td>
<td class="gt_row gt_right" style="max-width: 78px">8.75</td>
<td class="gt_row gt_right" style="max-width: 74px">0</td>
<td class="gt_row gt_right" style="max-width: 82px">4.2</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_left" style="max-width: 114px">Thingamajig</td>
<td class="gt_row gt_left" style="max-width: 114px">Office</td>
<td class="gt_row gt_right" style="max-width: 78px">199.99</td>
<td class="gt_row gt_right" style="max-width: 74px">25</td>
<td class="gt_row gt_right" style="max-width: 82px">2.1</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">5</td>
<td class="gt_row gt_left" style="max-width: 114px">Contraption</td>
<td class="gt_row gt_left" style="max-width: 114px">Electronics</td>
<td class="gt_row gt_right" style="max-width: 78px">65</td>
<td class="gt_row gt_right" style="max-width: 74px">44</td>
<td class="gt_row gt_right" style="max-width: 82px">3.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">6</td>
<td class="gt_row gt_left" style="max-width: 114px">Apparatus</td>
<td class="gt_row gt_left" style="max-width: 114px">Tools</td>
<td class="gt_row gt_right" style="max-width: 78px">120</td>
<td class="gt_row gt_right" style="max-width: 74px">12</td>
<td class="gt_row gt_right" style="max-width: 82px">4.7</td>
</tr>
</tbody>
</table>


TSV support uses the same reader as CSV with the delimiter set to tab, so all the same options (column subsets, head/tail, etc.) apply.


## JSONL Files

Newline-delimited JSON files (`.jsonl` or `.ndjson`) are read line by line. Each line must be a valid JSON object. The badge shows **JSONL** in light blue:


``` python
tbl_preview("../assets/data/server_logs.jsonl", show_all=True)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="5" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #E3F2FD; color: #1565C0; border: 1px solid #E3F2FD; margin-right: 8px;">JSONL</span>Rows6Columns4
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="timestamp" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

timestamp

<em>str</em>

</div></th>
<th id="level" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

level

<em>str</em>

</div></th>
<th id="module" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

module

<em>str</em>

</div></th>
<th id="message" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

message

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 153px">2025-01-15T08:30:00</td>
<td class="gt_row gt_left" style="max-width: 66px">INFO</td>
<td class="gt_row gt_left" style="max-width: 63px">auth</td>
<td class="gt_row gt_left" style="max-width: 246px">User login successful</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 153px">2025-01-15T08:31:12</td>
<td class="gt_row gt_left" style="max-width: 66px">WARNING</td>
<td class="gt_row gt_left" style="max-width: 63px">db</td>
<td class="gt_row gt_left" style="max-width: 246px">Slow query detected (3.2s)</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 153px">2025-01-15T08:32:45</td>
<td class="gt_row gt_left" style="max-width: 66px">ERROR</td>
<td class="gt_row gt_left" style="max-width: 63px">api</td>
<td class="gt_row gt_left" style="max-width: 246px">Request timeout on /v2/users</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 153px">2025-01-15T08:33:01</td>
<td class="gt_row gt_left" style="max-width: 66px">INFO</td>
<td class="gt_row gt_left" style="max-width: 63px">cache</td>
<td class="gt_row gt_left" style="max-width: 246px">Cache miss for key user:42</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_left" style="max-width: 153px">2025-01-15T08:34:20</td>
<td class="gt_row gt_left" style="max-width: 66px">DEBUG</td>
<td class="gt_row gt_left" style="max-width: 63px">auth</td>
<td class="gt_row gt_left" style="max-width: 246px">Token refresh for session abc123</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">5</td>
<td class="gt_row gt_left" style="max-width: 153px">2025-01-15T08:35:55</td>
<td class="gt_row gt_left" style="max-width: 66px">ERROR</td>
<td class="gt_row gt_left" style="max-width: 63px">db</td>
<td class="gt_row gt_left" style="max-width: 246px">Connection pool exhausted</td>
</tr>
</tbody>
</table>


JSONL is a common format for log data and streaming pipelines, making [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview) a convenient way to inspect log files in documentation.


## Parquet Files

Apache Parquet files (`.parquet` or `.pq`) are read via Polars or PyArrow. The badge shows **Parquet** in purple:


``` python
tbl_preview("../assets/data/products.parquet", show_all=True)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="6" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F3E5F5; color: #6A1B9A; border: 1px solid #F3E5F5; margin-right: 8px;">Parquet</span>Rows5Columns5
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="product" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

product

<em>str</em>

</div></th>
<th id="category" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

category

<em>str</em>

</div></th>
<th id="price" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

price

<em>f64</em>

</div></th>
<th id="in_stock" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

in_stock

<em>bool</em>

</div></th>
<th id="rating" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

rating

<em>f64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 110px">Widget</td>
<td class="gt_row gt_left" style="max-width: 110px">Electronics</td>
<td class="gt_row gt_right" style="max-width: 74px">29.99</td>
<td class="gt_row gt_left" style="max-width: 93px">True</td>
<td class="gt_row gt_right" style="max-width: 78px">4.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 110px">Gadget</td>
<td class="gt_row gt_left" style="max-width: 110px">Tools</td>
<td class="gt_row gt_right" style="max-width: 74px">49.5</td>
<td class="gt_row gt_left" style="max-width: 93px">False</td>
<td class="gt_row gt_right" style="max-width: 78px">3.8</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 110px">Gizmo</td>
<td class="gt_row gt_left" style="max-width: 110px">Kitchen</td>
<td class="gt_row gt_right" style="max-width: 74px">12</td>
<td class="gt_row gt_left" style="max-width: 93px">True</td>
<td class="gt_row gt_right" style="max-width: 78px">4.9</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 110px">Doohickey</td>
<td class="gt_row gt_left" style="max-width: 110px">Garden</td>
<td class="gt_row gt_right" style="max-width: 74px">8.75</td>
<td class="gt_row gt_left" style="max-width: 93px">True</td>
<td class="gt_row gt_right" style="max-width: 78px">4.2</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_left" style="max-width: 110px">Thingamajig</td>
<td class="gt_row gt_left" style="max-width: 110px">Office</td>
<td class="gt_row gt_right" style="max-width: 74px">199.99</td>
<td class="gt_row gt_left" style="max-width: 93px">False</td>
<td class="gt_row gt_right" style="max-width: 78px">2.1</td>
</tr>
</tbody>
</table>


Parquet preserves the original column types from the file schema, so dtype labels are precise (e.g., `f64` rather than a generic `float`).


## Feather and Arrow IPC Files

Feather files (`.feather`) and Arrow IPC files (`.arrow`, `.ipc`) are both read as Arrow IPC format. Feather files get a **Feather** badge in orange, while `.arrow`/`.ipc` files get an **Arrow** badge in indigo:


``` python
tbl_preview("../assets/data/employees.feather", show_all=True)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="5" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #FFF3E0; color: #E65100; border: 1px solid #FFF3E0; margin-right: 8px;">Feather</span>Rows6Columns4
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

name

<em>str</em>

</div></th>
<th id="department" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

department

<em>str</em>

</div></th>
<th id="salary" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

salary

<em>i64</em>

</div></th>
<th id="years" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

years

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 112px">Alice</td>
<td class="gt_row gt_left" style="max-width: 141px">Engineering</td>
<td class="gt_row gt_right" style="max-width: 109px">95000</td>
<td class="gt_row gt_right" style="max-width: 101px">5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 112px">Bob</td>
<td class="gt_row gt_left" style="max-width: 141px">Marketing</td>
<td class="gt_row gt_right" style="max-width: 109px">72000</td>
<td class="gt_row gt_right" style="max-width: 101px">3</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 112px">Charlie</td>
<td class="gt_row gt_left" style="max-width: 141px">Engineering</td>
<td class="gt_row gt_right" style="max-width: 109px">105000</td>
<td class="gt_row gt_right" style="max-width: 101px">8</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 112px">Diana</td>
<td class="gt_row gt_left" style="max-width: 141px">Sales</td>
<td class="gt_row gt_right" style="max-width: 109px">68000</td>
<td class="gt_row gt_right" style="max-width: 101px">2</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_left" style="max-width: 112px">Eve</td>
<td class="gt_row gt_left" style="max-width: 141px">Marketing</td>
<td class="gt_row gt_right" style="max-width: 109px">88000</td>
<td class="gt_row gt_right" style="max-width: 101px">6</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">5</td>
<td class="gt_row gt_left" style="max-width: 112px">Frank</td>
<td class="gt_row gt_left" style="max-width: 141px">Sales</td>
<td class="gt_row gt_right" style="max-width: 109px">71000</td>
<td class="gt_row gt_right" style="max-width: 101px">4</td>
</tr>
</tbody>
</table>


Arrow IPC is the recommended format for fast local reads when you need to preserve exact column types.


## PyArrow Tables

If you're working with PyArrow directly, pass a `pyarrow.Table` without writing to disk. The badge shows **Arrow** in indigo:


``` python
import pyarrow as pa

table = pa.table({
    "sensor": ["A1", "A2", "B1"],
    "reading": [23.5, 19.8, 31.2],
    "active": [True, True, False],
})

tbl_preview(table)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #E8EAF6; color: #283593; border: 1px solid #E8EAF6; margin-right: 8px;">Arrow</span>Rows3Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="sensor" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

sensor

<em>str</em>

</div></th>
<th id="reading" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

reading

<em>f64</em>

</div></th>
<th id="active" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

active

<em>bool</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 152px">A1</td>
<td class="gt_row gt_right" style="max-width: 160px">23.5</td>
<td class="gt_row gt_left" style="max-width: 152px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 152px">A2</td>
<td class="gt_row gt_right" style="max-width: 160px">19.8</td>
<td class="gt_row gt_left" style="max-width: 152px">True</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 152px">B1</td>
<td class="gt_row gt_right" style="max-width: 160px">31.2</td>
<td class="gt_row gt_left" style="max-width: 152px">False</td>
</tr>
</tbody>
</table>


PyArrow's type system is fully supported, including nested types like `list<int64>` and `struct` which are displayed with their Arrow type names.


## Supported File Extensions

The full mapping of file extensions to format types is:

| Extension           | Format    | Badge   |
|---------------------|-----------|---------|
| `.csv`              | CSV       | CSV     |
| `.tsv`, `.tab`      | TSV       | TSV     |
| `.jsonl`, `.ndjson` | JSONL     | JSONL   |
| `.parquet`, `.pq`   | Parquet   | Parquet |
| `.feather`          | Feather   | Feather |
| `.arrow`, `.ipc`    | Arrow IPC | Arrow   |

Any unrecognized extension defaults to CSV parsing.


# Head and Tail Splitting

Large tables are automatically split into a head and tail section, connected by a visual divider row. This gives readers a sense of both the beginning and end of the data without rendering thousands of rows.


## Default Split

By default, the first 5 rows and last 5 rows are shown:


``` python
import polars as pl

df = pl.DataFrame({
    "id": list(range(1, 21)),
    "value": [x * 1.1 for x in range(1, 21)],
    "label": [f"item-{i}" for i in range(1, 21)],
})

tbl_preview(df)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #0075FF; color: #FFFFFF; border: 1px solid #0075FF; margin-right: 8px;">Polars</span>Rows20Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="id" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

id

<em>i64</em>

</div></th>
<th id="value" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

value

<em>f64</em>

</div></th>
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

label

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_right" style="max-width: 148px">1</td>
<td class="gt_row gt_right" style="max-width: 153px">1.1</td>
<td class="gt_row gt_left" style="max-width: 164px">item-1</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_right" style="max-width: 148px">2</td>
<td class="gt_row gt_right" style="max-width: 153px">2.2</td>
<td class="gt_row gt_left" style="max-width: 164px">item-2</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_right" style="max-width: 148px">3</td>
<td class="gt_row gt_right" style="max-width: 153px">3.3</td>
<td class="gt_row gt_left" style="max-width: 164px">item-3</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_right" style="max-width: 148px">4</td>
<td class="gt_row gt_right" style="max-width: 153px">4.4</td>
<td class="gt_row gt_left" style="max-width: 164px">item-4</td>
</tr>
<tr class="gd-tbl-divider">
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_right" style="max-width: 148px">5</td>
<td class="gt_row gt_right" style="max-width: 153px">5.5</td>
<td class="gt_row gt_left" style="max-width: 164px">item-5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">15</td>
<td class="gt_row gt_right" style="max-width: 148px">16</td>
<td class="gt_row gt_right" style="max-width: 153px">17.6</td>
<td class="gt_row gt_left" style="max-width: 164px">item-16</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">16</td>
<td class="gt_row gt_right" style="max-width: 148px">17</td>
<td class="gt_row gt_right" style="max-width: 153px">18.7</td>
<td class="gt_row gt_left" style="max-width: 164px">item-17</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">17</td>
<td class="gt_row gt_right" style="max-width: 148px">18</td>
<td class="gt_row gt_right" style="max-width: 153px">19.8</td>
<td class="gt_row gt_left" style="max-width: 164px">item-18</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">18</td>
<td class="gt_row gt_right" style="max-width: 148px">19</td>
<td class="gt_row gt_right" style="max-width: 153px">20.9</td>
<td class="gt_row gt_left" style="max-width: 164px">item-19</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">19</td>
<td class="gt_row gt_right" style="max-width: 148px">20</td>
<td class="gt_row gt_right" style="max-width: 153px">22</td>
<td class="gt_row gt_left" style="max-width: 164px">item-20</td>
</tr>
</tbody>
</table>


The divider row between head and tail is a thin colored line that visually separates the two sections while keeping the table compact.


## Custom Split

Adjust the `n_head` and `n_tail` parameters to control how many rows appear in each section:


``` python
tbl_preview(df, n_head=3, n_tail=2)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #0075FF; color: #FFFFFF; border: 1px solid #0075FF; margin-right: 8px;">Polars</span>Rows20Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="id" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

id

<em>i64</em>

</div></th>
<th id="value" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

value

<em>f64</em>

</div></th>
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

label

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_right" style="max-width: 148px">1</td>
<td class="gt_row gt_right" style="max-width: 153px">1.1</td>
<td class="gt_row gt_left" style="max-width: 164px">item-1</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_right" style="max-width: 148px">2</td>
<td class="gt_row gt_right" style="max-width: 153px">2.2</td>
<td class="gt_row gt_left" style="max-width: 164px">item-2</td>
</tr>
<tr class="gd-tbl-divider">
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_right" style="max-width: 148px">3</td>
<td class="gt_row gt_right" style="max-width: 153px">3.3</td>
<td class="gt_row gt_left" style="max-width: 164px">item-3</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">18</td>
<td class="gt_row gt_right" style="max-width: 148px">19</td>
<td class="gt_row gt_right" style="max-width: 153px">20.9</td>
<td class="gt_row gt_left" style="max-width: 164px">item-19</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">19</td>
<td class="gt_row gt_right" style="max-width: 148px">20</td>
<td class="gt_row gt_right" style="max-width: 153px">22</td>
<td class="gt_row gt_left" style="max-width: 164px">item-20</td>
</tr>
</tbody>
</table>


Setting `n_tail=0` shows only the head, which is useful when the start of the data is most relevant:


``` python
tbl_preview(df, n_head=8, n_tail=0)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #0075FF; color: #FFFFFF; border: 1px solid #0075FF; margin-right: 8px;">Polars</span>Rows20Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="id" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

id

<em>i64</em>

</div></th>
<th id="value" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

value

<em>f64</em>

</div></th>
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

label

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_right" style="max-width: 150px">1</td>
<td class="gt_row gt_right" style="max-width: 155px">1.1</td>
<td class="gt_row gt_left" style="max-width: 159px">item-1</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_right" style="max-width: 150px">2</td>
<td class="gt_row gt_right" style="max-width: 155px">2.2</td>
<td class="gt_row gt_left" style="max-width: 159px">item-2</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_right" style="max-width: 150px">3</td>
<td class="gt_row gt_right" style="max-width: 155px">3.3</td>
<td class="gt_row gt_left" style="max-width: 159px">item-3</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_right" style="max-width: 150px">4</td>
<td class="gt_row gt_right" style="max-width: 155px">4.4</td>
<td class="gt_row gt_left" style="max-width: 159px">item-4</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_right" style="max-width: 150px">5</td>
<td class="gt_row gt_right" style="max-width: 155px">5.5</td>
<td class="gt_row gt_left" style="max-width: 159px">item-5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">5</td>
<td class="gt_row gt_right" style="max-width: 150px">6</td>
<td class="gt_row gt_right" style="max-width: 155px">6.6</td>
<td class="gt_row gt_left" style="max-width: 159px">item-6</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">6</td>
<td class="gt_row gt_right" style="max-width: 150px">7</td>
<td class="gt_row gt_right" style="max-width: 155px">7.7</td>
<td class="gt_row gt_left" style="max-width: 159px">item-7</td>
</tr>
<tr class="gd-tbl-divider">
<td class="gt_row gt_right gd-tbl-rownum">7</td>
<td class="gt_row gt_right" style="max-width: 150px">8</td>
<td class="gt_row gt_right" style="max-width: 155px">8.8</td>
<td class="gt_row gt_left" style="max-width: 159px">item-8</td>
</tr>
</tbody>
</table>


The `limit` parameter (default 50) caps the maximum sum of `n_head + n_tail`. If you need a larger split, increase the limit explicitly.


## Show All Rows

For small tables where every row matters, set `show_all=True` to disable the head/tail split entirely:


``` python
tbl_preview(
    {"name": ["Alice", "Bob", "Charlie"], "score": [95, 82, 71]},
    show_all=True,
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

name

<em>str</em>

</div></th>
<th id="score" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

score

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 238px">Alice</td>
<td class="gt_row gt_right" style="max-width: 227px">95</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 238px">Bob</td>
<td class="gt_row gt_right" style="max-width: 227px">82</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 238px">Charlie</td>
<td class="gt_row gt_right" style="max-width: 227px">71</td>
</tr>
</tbody>
</table>


When `show_all=True` is set, the divider row is omitted and all rows are displayed in sequence. Use this for tables with fewer than ~50 rows where the full picture is important.


# Column Selection

By default, all columns are shown. The `columns` parameter lets you pick a subset, which is useful for wide tables where only a few columns are relevant to the discussion.


``` python
tbl_preview(
    "../assets/data/students.csv",
    columns=["name", "score", "grade"],
    show_all=True,
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #FFF8E1; color: #7A6200; border: 1px solid #FFF8E1; margin-right: 8px;">CSV</span>Rows10Columns5
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

name

<em>str</em>

</div></th>
<th id="score" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

score

<em>f64</em>

</div></th>
<th id="grade" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

grade

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 162px">Alice</td>
<td class="gt_row gt_right" style="max-width: 151px">95.5</td>
<td class="gt_row gt_left" style="max-width: 151px">A</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 162px">Bob</td>
<td class="gt_row gt_right" style="max-width: 151px">82</td>
<td class="gt_row gt_left" style="max-width: 151px">B</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 162px">Charlie</td>
<td class="gt_row gt_right" style="max-width: 151px">71.3</td>
<td class="gt_row gt_left" style="max-width: 151px">C</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 162px">Diana</td>
<td class="gt_row gt_right" style="max-width: 151px">60</td>
<td class="gt_row gt_left" style="max-width: 151px">D</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_left" style="max-width: 162px">Eve</td>
<td class="gt_row gt_right" style="max-width: 151px">55.8</td>
<td class="gt_row gt_left" style="max-width: 151px">F</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">5</td>
<td class="gt_row gt_left" style="max-width: 162px">Frank</td>
<td class="gt_row gt_right" style="max-width: 151px">88.2</td>
<td class="gt_row gt_left" style="max-width: 151px">B+</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">6</td>
<td class="gt_row gt_left" style="max-width: 162px">Grace</td>
<td class="gt_row gt_right" style="max-width: 151px">79.9</td>
<td class="gt_row gt_left" style="max-width: 151px">C+</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">7</td>
<td class="gt_row gt_left" style="max-width: 162px">Hank</td>
<td class="gt_row gt_right" style="max-width: 151px">91</td>
<td class="gt_row gt_left" style="max-width: 151px">A-</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">8</td>
<td class="gt_row gt_left" style="max-width: 162px">Iris</td>
<td class="gt_row gt_right" style="max-width: 151px">66.4</td>
<td class="gt_row gt_left" style="max-width: 151px">D+</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">9</td>
<td class="gt_row gt_left" style="max-width: 162px">Jack</td>
<td class="gt_row gt_right" style="max-width: 151px">73.7</td>
<td class="gt_row gt_left" style="max-width: 151px">C</td>
</tr>
</tbody>
</table>


Columns appear in the order you specify, so you can also use this to reorder columns. If a column name doesn't exist in the data, a `ValueError` is raised with a helpful message listing the available columns.


# Missing Values

Missing values (`None`, `NaN`, `NA`, `Inf`, `-Inf`) are highlighted with a red background and text by default. This makes it easy to spot gaps in the data at a glance.


``` python
import math

tbl_preview({
    "sensor": ["A1", "A2", "A3", "B1"],
    "reading": [23.5, None, math.nan, 31.2],
    "status": ["ok", "offline", None, "ok"],
}, show_all=True)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows4Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="sensor" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

sensor

<em>str</em>

</div></th>
<th id="reading" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

reading

<em>f64</em>

</div></th>
<th id="status" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

status

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 151px">A1</td>
<td class="gt_row gt_right" style="max-width: 159px">23.5</td>
<td class="gt_row gt_left" style="max-width: 154px">ok</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 151px">A2</td>
<td class="gt_row gt_right gd-tbl-missing" style="max-width: 159px">None</td>
<td class="gt_row gt_left" style="max-width: 154px">offline</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 151px">A3</td>
<td class="gt_row gt_right gd-tbl-missing" style="max-width: 159px">NaN</td>
<td class="gt_row gt_left gd-tbl-missing" style="max-width: 154px">None</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_left" style="max-width: 151px">B1</td>
<td class="gt_row gt_right" style="max-width: 159px">31.2</td>
<td class="gt_row gt_left" style="max-width: 154px">ok</td>
</tr>
</tbody>
</table>


The cell text shows a representation of the missing value (`None`, `NaN`, `NA`, `Inf`), and the cell background turns light red to draw attention.

To disable missing-value highlighting (for example, if your data intentionally contains `None` as a meaningful value), set `highlight_missing=False`:


``` python
tbl_preview({
    "sensor": ["A1", "A2", "A3"],
    "reading": [23.5, None, 31.2],
}, show_all=True, highlight_missing=False)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="sensor" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

sensor

<em>str</em>

</div></th>
<th id="reading" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

reading

<em>f64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 228px">A1</td>
<td class="gt_row gt_right" style="max-width: 236px">23.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 228px">A2</td>
<td class="gt_row gt_right" style="max-width: 236px">None</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 228px">A3</td>
<td class="gt_row gt_right" style="max-width: 236px">31.2</td>
</tr>
</tbody>
</table>


With highlighting off, missing values still display their text representation but use the normal cell styling.


# Display Options

Every visual element of the preview table can be toggled on or off independently. This lets you create anything from a fully-featured data preview to a minimal, stripped-down table.


## Captions

Add a descriptive caption that appears below the header banner and above the column labels:


``` python
tbl_preview(
    {"city": ["Tokyo", "Paris", "New York"], "population": [13960000, 2161000, 8336000]},
    show_all=True,
    caption="World cities by population (2024 estimates)",
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns2
</div></th>
</tr>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_subtitle gt_font_normal">World cities by population (2024 estimates)</th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="city" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

city

<em>str</em>

</div></th>
<th id="population" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

population

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 222px">Tokyo</td>
<td class="gt_row gt_right" style="max-width: 242px">13960000</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 222px">Paris</td>
<td class="gt_row gt_right" style="max-width: 242px">2161000</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 222px">New York</td>
<td class="gt_row gt_right" style="max-width: 242px">8336000</td>
</tr>
</tbody>
</table>


Captions are useful when multiple previews appear on the same page, giving each table a distinct label.


## Row Numbers

Row numbers appear in a left-hand gutter by default, starting from 0 to match Python, Polars, and Pandas 0-based indexing. They reflect the original row positions, even when head/tail splitting is active. To hide them:


``` python
tbl_preview(
    {"x": [1, 2, 3], "y": [4, 5, 6]},
    show_all=True,
    show_row_numbers=False,
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="2" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th id="x" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

x

<em>i64</em>

</div></th>
<th id="y" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

y

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right" style="max-width: 250px">1</td>
<td class="gt_row gt_right" style="max-width: 250px">4</td>
</tr>
<tr>
<td class="gt_row gt_right" style="max-width: 250px">2</td>
<td class="gt_row gt_right" style="max-width: 250px">5</td>
</tr>
<tr>
<td class="gt_row gt_right" style="max-width: 250px">3</td>
<td class="gt_row gt_right" style="max-width: 250px">6</td>
</tr>
</tbody>
</table>


Hiding row numbers is useful for small reference tables where the row position isn't meaningful.


## Row Index Offset

If you prefer 1-based numbering (or any other starting value), set `row_index_offset`:


``` python
tbl_preview(
    {"x": [1, 2, 3], "y": [4, 5, 6]},
    show_all=True,
    row_index_offset=1,
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="x" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

x

<em>i64</em>

</div></th>
<th id="y" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

y

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_right" style="max-width: 232px">1</td>
<td class="gt_row gt_right" style="max-width: 232px">4</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_right" style="max-width: 232px">2</td>
<td class="gt_row gt_right" style="max-width: 232px">5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_right" style="max-width: 232px">3</td>
<td class="gt_row gt_right" style="max-width: 232px">6</td>
</tr>
</tbody>
</table>


The offset applies to all rows, including tail rows in head/tail splits. The default of `0` keeps row numbers consistent with what you see when inspecting a DataFrame in Python.


## Dtype Labels

Compact dtype labels appear beneath each column name (e.g., `str`, `i64`, `f64`). To hide them:


``` python
tbl_preview(
    {"name": ["Alice", "Bob"], "score": [95.5, 82.0]},
    show_all=True,
    show_dtypes=False,
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows2Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="name" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col">name</th>
<th id="score" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col">score</th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 231px">Alice</td>
<td class="gt_row gt_right" style="max-width: 234px">95.5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 231px">Bob</td>
<td class="gt_row gt_right" style="max-width: 234px">82</td>
</tr>
</tbody>
</table>


Hiding dtype labels produces a cleaner look when the column types are obvious from context or not relevant to the reader.


## Dimensions Banner

The header banner shows the table type badge, row count, and column count. To hide it:


``` python
tbl_preview(
    {"x": [1, 2, 3], "y": [4, 5, 6]},
    show_all=True,
    show_dimensions=False,
)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="x" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

x

<em>i64</em>

</div></th>
<th id="y" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

y

<em>i64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_right" style="max-width: 232px">1</td>
<td class="gt_row gt_right" style="max-width: 232px">4</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_right" style="max-width: 232px">2</td>
<td class="gt_row gt_right" style="max-width: 232px">5</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_right" style="max-width: 232px">3</td>
<td class="gt_row gt_right" style="max-width: 232px">6</td>
</tr>
</tbody>
</table>


Hiding the dimensions banner is useful when the surrounding text already describes the data size.


## Minimal Chrome

Combine the toggle options to create a stripped-down table with no row numbers, no dtypes, and no dimensions (just the data):


``` python
tbl_preview(
    {"name": ["Alice", "Bob", "Charlie"], "score": [95, 82, 71]},
    show_all=True,
    show_row_numbers=False,
    show_dtypes=False,
    show_dimensions=False,
)
```


| name    | score |
|---------|-------|
| Alice   | 95    |
| Bob     | 82    |
| Charlie | 71    |


This minimal style works well for small inline reference tables where the chrome would be distracting.


## Column Width Control

The `max_col_width` parameter caps the pixel width of any single column. Long cell values are truncated with an ellipsis. The default is 250px.


``` python
tbl_preview({
    "description": [
        "This is a very long description that would normally extend the column width quite far",
        "Another lengthy entry with lots of detail about the item in question",
        "Short one",
    ],
    "code": ["ABC-001", "DEF-002", "GHI-003"],
}, show_all=True, max_col_width=150)
```


<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="3" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #F0F0F0; color: #333333; border: 1px solid #F0F0F0; margin-right: 8px;">Table</span>Rows3Columns2
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="description" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

description

<em>str</em>

</div></th>
<th id="code" class="gt_col_heading gt_columns_bottom_border gt_left" scope="col"><div>

code

<em>str</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_left" style="max-width: 274px">This is a very long description that would normally extend the column width quite far</td>
<td class="gt_row gt_left" style="max-width: 190px">ABC-001</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_left" style="max-width: 274px">Another lengthy entry with lots of detail about the item in question</td>
<td class="gt_row gt_left" style="max-width: 190px">DEF-002</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_left" style="max-width: 274px">Short one</td>
<td class="gt_row gt_left" style="max-width: 190px">GHI-003</td>
</tr>
</tbody>
</table>


The `min_tbl_width` parameter sets a floor for the total table width (default 500px), ensuring that narrow tables don't collapse to an unreadably small size.

Both width parameters accept integer values in pixels.


# Quarto Shortcode

The `{{< tbl-preview >}}` shortcode renders a table preview directly in a `.qmd` page without writing any Python code. Point it at a data file and the shortcode handles everything.


## Basic Usage

The simplest invocation needs only the `file` parameter:

``` markdown
{{< tbl-preview file="assets/data.csv" >}}
```

The shortcode resolves the file path relative to the Quarto project root, reads the data, and inserts the preview HTML at render time. No code cell or Python import is needed.


## Adding Options

All the display options available to the Python function are also available as shortcode parameters:

``` markdown
{{< tbl-preview file="assets/data.csv" show_all="true" caption="My Dataset" >}}
```

``` markdown
{{< tbl-preview file="data.tsv" n_head="3" n_tail="2" show_row_numbers="false" >}}
```

``` markdown
{{< tbl-preview file="logs.jsonl" show_all="true" max_col_width="120" >}}
```

Note that shortcode parameters are always strings, so boolean values must be quoted (`"true"` / `"false"`) and numeric values must be quoted (`"10"`, `"150"`).


## Column Subsets

To show only specific columns, pass a comma-separated list to the `columns` parameter:

``` markdown
{{< tbl-preview file="assets/students.csv" columns="name,score,grade" show_all="true" >}}
```

Columns appear in the order listed.


## Supported Parameters

The full set of shortcode parameters mirrors the Python function:

| Parameter | Type | Default | Description |
|----|----|----|----|
| `file` | string | -- | Path to data file (required, relative to project root) |
| `columns` | string | all | Comma-separated column names to display |
| `n_head` | string | `"5"` | Number of rows from the start |
| `n_tail` | string | `"5"` | Number of rows from the end |
| `show_all` | string | `"false"` | Show all rows (ignores head/tail) |
| `show_row_numbers` | string | `"true"` | Show row-number gutter |
| `show_dtypes` | string | `"true"` | Show dtype labels under column names |
| `show_dimensions` | string | `"true"` | Show header banner with row/column counts |
| `max_col_width` | string | `"250"` | Maximum column width in pixels |
| `min_tbl_width` | string | `"500"` | Minimum total table width in pixels |
| `caption` | string | -- | Caption text below the header banner |
| `row_index_offset` | string | `"0"` | Starting row number (use `"1"` for 1-based) |

The shortcode supports every file format listed in the [Supported File Extensions](#supported-file-extensions) table.


# Notebook Integration

In Jupyter notebooks and Quarto `.qmd` documents with Python code cells, you can enable automatic [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview) rendering for all DataFrames using the display hook.


## Enable Auto-Preview

Call [enable_tbl_preview()](../reference/enable_tbl_preview.md#great_docs.enable_tbl_preview) once at the top of a notebook, and every Polars or Pandas DataFrame displayed afterward will render as a preview table instead of the library's default HTML:

``` python
import great_docs as gd

gd.enable_tbl_preview(n_head=8, n_tail=3)

# Now any DataFrame as the last expression in a cell
# renders as a tbl_preview() table automatically:
import pandas as pd
pd.read_csv("data.csv")  # → preview table
```

Keyword arguments passed to [enable_tbl_preview()](../reference/enable_tbl_preview.md#great_docs.enable_tbl_preview) are forwarded to [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview), so you can set defaults for the entire notebook in one call.


## Disable Auto-Preview

To restore the default DataFrame display, call [disable_tbl_preview()](../reference/disable_tbl_preview.md#great_docs.disable_tbl_preview):

``` python
gd.disable_tbl_preview()
```

This removes the formatter and returns to the library's built-in HTML rendering.


# Parameters Reference

The table below lists every parameter available on the [tbl_preview()](../reference/tbl_preview.md#great_docs.tbl_preview) function. All parameters except `data` are optional.

| Parameter | Type | Default | Description |
|----|----|----|----|
| `data` | various | -- | Data source: DataFrame, file path, dict, or list of dicts |
| `columns` | `list[str]` | `None` | Column names to display (all if `None`) |
| `n_head` | `int` | `5` | Rows from the start |
| `n_tail` | `int` | `5` | Rows from the end |
| `limit` | `int` | `50` | Maximum allowed `n_head + n_tail` |
| `show_all` | `bool` | `False` | Show all rows |
| `show_row_numbers` | `bool` | `True` | Show row-number gutter |
| `show_dtypes` | `bool` | `True` | Show dtype labels |
| `show_dimensions` | `bool` | `True` | Show header banner |
| `max_col_width` | `int` | `250` | Maximum column width (px) |
| `min_tbl_width` | `int` | `500` | Minimum table width (px) |
| `caption` | `str` | `None` | Caption text |
| `highlight_missing` | `bool` | `True` | Highlight missing values |
| `row_index_offset` | `int` | `0` | Starting row number (0-based by default) |
| `id` | `str` | auto | Custom HTML `id` for the container |

The return value is a `TblPreview` object with `_repr_html_()` (for notebook display), `as_html()` (returns the HTML string), and `save(path)` (writes HTML to a file) methods.


# Next Steps

Table previews give readers a quick look at a dataset's structure and content without loading the full table. Use them in docstring examples, user guides, or anywhere you want to show data at a glance.

- [Table Explorer](table-explorer.md) adds interactive filtering, sorting, and pagination for larger datasets
- [Scale-to-Fit](scale-to-fit.md) keeps wide tables readable on narrow screens
- [Writing Docstrings](writing-docstrings.md) covers embedding table previews in executable docstring examples
