Gallery mode
Set the gallery prop and the grid renders its rows as cards instead of a
table: a cover image, a title and a few fields per row, in a wall that fills
the width. It is the same <SvGrid>, the same data and columns; the cards
are the rows the table would show, so the search box, column filters and the
sort carry over, and turning the prop off brings the table back in the same
order.
The gallery renderer ships in @svgrid/enterprise, so enableGalleryView()
(or installEnterprise(api)) is what lights it up. The gallery prop and the
GalleryConfig type are part of the free grid; without the renderer the grid
shows a short note where the cards would be.
<script lang="ts">
import { SvGrid, type GridColumns } from '@svgrid/grid'
import { enableGalleryView } from '@svgrid/enterprise'
enableGalleryView()
type Product = { id: number; name: string; image: string; category: string; price: number }
let { data }: { data: Product[] } = $props()
const columns: GridColumns<Product> = [
{ field: 'name', header: 'Product' },
{ field: 'category', header: 'Category' },
{ field: 'price', header: 'Price', format: { type: 'currency', currency: 'USD' } },
]
</script>
<SvGrid {data} {columns} getRowId={(r) => String(r.id)}
gallery={{ coverField: 'image', titleField: 'name', cardFields: ['category', 'price'] }} />
What a card shows
| Option | What it does |
|---|---|
coverField |
The field holding the cover: an image URL (https:, blob: or a data:image/... URL), or a list of files ({ url, type, name, thumbnailUrl }), whose first image is used. Omit it for cards without a cover. |
coverFit |
'cover' (default) crops the image to fill the cover's box; 'contain' shows all of it. |
titleField |
The card's title. Defaults to the first column's field. |
cardFields |
The fields under the title, in this order. Defaults to the next columns, up to six, leaving out the title and the cover. |
showLabels |
Each value under its field's name (default true). |
cardSize |
'small' (180px), 'medium' (240px, default), 'large' (320px) or a width in pixels. The wall fits as many columns as the width holds. |
emptyText |
What the wall says when no row is shown (default "No records"). |
searchable, searchPlaceholder |
The search box above the cards (on by default); it is the grid's quick filter. |
cellGrid |
(width) => grid: what a field type's cell on a card gets as its grid. A base's gallery view sets it to the grid itself at the card's width, with editing off; without it a cell gets an object with getColumnWidth only. |
A value is written the way the table cell writes it: through the column's
formatter, else its format config (currency, percent, dates), else as
text. A column declared by field type (@svgrid/enterprise/fields) draws on
the card with its own cell: a select as its colored pill, a rating as stars, a
person with an avatar, and the field's type icon sits beside its name.
Clicks
onCardClick(row) is called when a card is clicked, or when its title gets
Enter or Space from the keyboard (the title is the card's button). Without
it the cards are not clickable. Values on a card are read, not edited.
const gallery = { coverField: 'image', onCardClick: (row: Product) => (picked = row) }
Your own card
card is a snippet that receives each row; the grid lays the cards out and
you draw what is inside.
{#snippet profile(p: Person)}
<article class="profile">
<img src={p.photo} alt="" width="72" height="72" />
<strong>{p.name}</strong>
<span>{p.role}</span>
</article>
{/snippet}
<SvGrid {data} {columns} gallery={{ card: profile, cardSize: 220 }} />
Filters, sort and search
The cards are the grid's filtered and sorted rows, so everything that shapes
the table shapes the wall: api.setFilter, api.setSort, the quick filter,
an advanced filter. A new filter or search starts the wall from the top.
Many rows
The wall draws its cards in batches: the first 120, then the next 120 a
little before the end comes into view. A gallery over thousands of rows costs
about the same to open as a small one. A cover can come from a computed
column (fieldFn), so the image need not be stored in the rows.
In a table with views
The fields module's gallery view is this gallery, set up from the view: the cover field, the primary field as the title, the fields the grid shows as the card's fields, and a click that opens the record.
Live examples
- Product catalog (gallery) - One <SvGrid> as a storefront: the `gallery` prop shows the rows as product cards drawn by a card snippet (photo, brand, rating, sale price, a badge), and Table shows the same rows. The category filter, search and sort are the grid, so both views agree; a click opens the product in a panel with Add to cart.
- Cards from field types - With the fields module on, a gallery card draws each field as its cell does: select pills, stars, avatars, currency, with each field type icon by its name. The cover is the first image of an attachment field.
- Team directory (custom cards) - A gallery whose cards you draw yourself: `gallery.card` is a snippet that gets each row, so a person shows as a profile card with photo, role, team and a mail link. The search box and the Team filter buttons narrow the same rows the Table view shows.
- Real estate listings - Listings drawn by a card snippet: the photo with its status and a save button, the price, beds, baths and size, the address and the agent. The cards are the grid filtered and sorted rows: status buttons and a beds filter set column filters, the sort menu calls api.setSort, the search box is the quick filter.
- Gallery at scale (5,000 cards) - 5,000 rows as cards, drawn in batches as the wall scrolls, so the first paint costs the same as a small table. Search narrows all of them; the cover is a computed column (fieldFn), so no image is stored in the rows.