# Types: ProductCard to ProductCardSpecsProps (/themes/sdk/reference/listing/types-2)

```ts
import { … } from '@poltura/theme-sdk/listing';
```

## `ProductCard` (type) [#productcard-type]

A product as a list, rail or search result shows it.

<TypeTable type={{"id":{"description":"The product's id.","type":"string","required":true},"handle":{"description":"The product's URL segment.","type":"string","required":true},"href":{"description":"The product page's path.","type":"string","required":true},"title":{"description":"The product's title.","type":"string","required":true},"shortTitle":{"description":"A shorter title for tight cards, or null to use `title`.","type":"string | null","required":true},"categoryLabel":{"description":"The name of the product's main category, or null.","type":"string | null","required":true},"categoryPath":{"description":"The URL segments of the product's deepest category, root first.","type":"readonly string[]","required":true},"collection":{"description":"The collection the product is in, or null.","type":"CollectionRef | null","required":true},"sku":{"description":"The stock keeping unit of the variant the card shows, or null.","type":"string | null","required":true},"image":{"description":"The card image, or null.","type":"MediaImageRef | null","required":true},"secondaryImage":{"description":"The image shown on hover, or null.","type":"MediaImageRef | null","required":true},"price":{"description":"The price of the variant the card shows.","type":"PriceView","required":true},"priceRange":{"description":"The lowest and highest variant prices, or null when every variant costs the same.","type":"PriceBounds | null","required":true},"availability":{"description":"Whether and how the shown variant can be bought.","type":"Availability","required":true},"defaultVariantId":{"description":"The variant a quick add puts in the cart, or null when the shopper must choose.","type":"string | null","required":true},"requiresVariantSelection":{"description":"Whether the shopper must pick options on the product page before buying.","type":"boolean","required":true},"badge":{"description":"The merchant's card badge, or null.","type":"string | null","required":true},"specs":{"description":"The attributes the store shows on cards, such as a game's platform; empty when none apply.","type":"readonly Spec[]","required":true},"badges":{"description":"The badges the product shows, in the merchant's order; empty when none apply.","type":"readonly ProductBadge[]","required":true},"rating":{"description":"The review score, or null.","type":"RatingStats | null","required":true},"fixedBundle":{"description":"The fixed bundle the card sells, or null.","type":"BundleRef | null","required":true}}} />

## `FilterOptionProps` [#filteroptionprops]

Props of [`FilterOption`](/themes/sdk/reference/listing/parts-1#filteroption).

<TypeTable type={{"groupId":{"description":"The group the option belongs to; it keeps the checkbox ids unique.","type":"string","required":true},"option":{"description":"The option to draw, with its nested choices.","type":"FilterOptionView","required":true},"onToggle":{"description":"Called when the shopper ticks or unticks the option or one of its nested choices.","type":"(optionId: string) => void","required":true},"level":{"description":"How deep the option is nested; 0 at the top.","type":"number","required":false},"className":{"description":"Classes added to the option's row.","type":"string","required":false}}} />

## `SwatchFilterProps` [#swatchfilterprops]

Props of [`SwatchFilter`](/themes/sdk/reference/listing/parts-1#swatchfilter).

<TypeTable type={{"group":{"description":"A swatch group.","type":"FilterGroupView","required":true},"onToggle":{"description":"Called when the shopper picks or unpicks a swatch.","type":"(optionId: string) => void","required":true},"className":{"description":"Classes added to the swatch list.","type":"string","required":false}}} />

## `PriceRangeFilterProps` [#pricerangefilterprops]

Props of [`PriceRangeFilter`](/themes/sdk/reference/listing/parts-1#pricerangefilter).

<TypeTable type={{"group":{"description":"A price group; other kinds draw nothing.","type":"FilterGroupView","required":true},"onChange":{"description":"Called a moment after the shopper stops moving the range; both bounds are null when it covers every price.","type":"(range: PriceRangeSelection) => void","required":true},"className":{"description":"Classes added to the range control.","type":"string","required":false}}} />

## `FilterGroupProps` [#filtergroupprops]

Props of [`FilterGroup`](/themes/sdk/reference/listing/parts-1#filtergroup).

<TypeTable type={{"group":{"description":"The group to draw.","type":"FilterGroupView","required":true},"onToggle":{"description":"Called when the shopper picks or unpicks a choice of a list, swatch or toggle group.","type":"(optionId: string) => void","required":true},"onPriceChange":{"description":"Called when the shopper changes a price group's range.","type":"(range: PriceRangeSelection) => void","required":true},"className":{"description":"Classes added to the group.","type":"string","required":false}}} />

## `AppliedFiltersClassKey` [#appliedfiltersclasskey]

The parts of [`AppliedFilters`](/themes/sdk/reference/listing/parts-1#appliedfilters) its `classes` prop styles.

```ts
type AppliedFiltersClassKey = 'chip' | 'remove' | 'clear'
```

## `AppliedFiltersProps` [#appliedfiltersprops]

Props of [`AppliedFilters`](/themes/sdk/reference/listing/parts-1#appliedfilters).

<TypeTable type={{"filters":{"description":"The applied filters, as {@link useListingFilters} lists them.","type":"readonly AppliedFilter[]","required":true},"onClear":{"description":"Called by the \"clear all\" link; without it the link is not shown.","type":"() => void","required":false},"className":{"description":"Classes added to the chip row.","type":"string","required":false},"classes":{"description":"Classes added to the chips, their remove buttons and the \"clear all\" link.","type":"Partial<Record<AppliedFiltersClassKey, string>>","required":false}}} />

## `FilterPanelProps` [#filterpanelprops]

Props of [`FilterPanel`](/themes/sdk/reference/listing/defaults-1#filterpanel).

<TypeTable type={{"variant":{"description":"A card with a title, a scrolling group list and a selection note, or the bare group list for a sheet.","type":"'card' | 'plain'","required":false},"className":{"description":"Classes added to the panel.","type":"string","required":false}}} />

## `FilterSheetProps` [#filtersheetprops]

Props of [`FilterSheet`](/themes/sdk/reference/listing/parts-1#filtersheet).

<TypeTable type={{"resultCount":{"description":"How many products match, for the sheet's \"show results\" button.","type":"number","required":true},"label":{"description":"The button and sheet title; defaults to the store's \"Filters\" wording.","type":"string","required":false},"clearLabel":{"description":"The \"clear all\" button's text; defaults to the store's wording.","type":"string","required":false},"className":{"description":"Classes added to the button that opens the sheet.","type":"string","required":false}}} />

## `SortSelectProps` [#sortselectprops]

Props of [`SortSelect`](/themes/sdk/reference/listing/parts-1#sortselect).

<TypeTable type={{"options":{"description":"The orders on offer.","type":"readonly SortOption[]","required":true},"selected":{"description":"The current order.","type":"ProductSort","required":true},"onChange":{"description":"Called with the order the shopper picked.","type":"(sort: ProductSort) => void","required":true},"className":{"description":"Classes added to the menu button's wrapper.","type":"string","required":false}}} />

## `ListingPaginationProps` [#listingpaginationprops]

Props of [`ListingPagination`](/themes/sdk/reference/listing/parts-1#listingpagination).

<TypeTable type={{"pagination":{"description":"Where the list is.","type":"Pagination","required":true},"onPageChange":{"description":"Called with the page the shopper opened.","type":"(page: number) => void","required":true},"siblings":{"description":"How many pages show on each side of the current one before the rest collapse; defaults to 1.","type":"number","required":false},"busy":{"description":"Dims and disables the buttons while a page loads.","type":"boolean","required":false},"className":{"description":"Classes added to the navigation.","type":"string","required":false}}} />

## `ProductCardLayout` [#productcardlayout]

Whether a card is a tile in a grid or a wide row in a list.

```ts
type ProductCardLayout = 'grid' | 'list'
```

## `ProductCardVisibility` [#productcardvisibility]

Which parts of a product card are shown; every part is on unless switched off.

<TypeTable type={{"price":{"description":"The price.","type":"boolean","required":true},"compareAt":{"description":"The struck-through price before a markdown.","type":"boolean","required":true},"badge":{"description":"The merchant's card badge.","type":"boolean","required":true},"addToCart":{"description":"The add-to-cart button.","type":"boolean","required":true}}} />

## `ProductCardLabels` [#productcardlabels]

The button texts of a product card; each falls back to the store's own wording.

<TypeTable type={{"addToCart":{"description":"The add-to-cart button.","type":"string","required":false},"adding":{"description":"The button while the product is being added.","type":"string","required":false},"selectOptions":{"description":"The button of a product whose options are chosen on its page.","type":"string","required":false},"soldOut":{"description":"The button of a product that cannot be bought.","type":"string","required":false}}} />

## `ProductCardProps` [#productcardprops]

Props of [`ProductCard`](/themes/sdk/reference/listing/defaults-2#productcard).

<TypeTable type={{"card":{"description":"The product to show.","type":"ProductCardView","required":true},"layout":{"description":"A grid tile or a list row; defaults to `grid`.","type":"ProductCardLayout","required":false},"show":{"description":"Parts to switch off.","type":"Partial<ProductCardVisibility>","required":false},"imageAspectRatio":{"description":"The image's CSS aspect ratio in a grid, such as `3 / 4`; defaults to `3 / 4`.","type":"string","required":false},"labels":{"description":"Button texts.","type":"ProductCardLabels","required":false},"onAddToCart":{"description":"Replaces the built-in quick add.","type":"(card: ProductCardView) => void","required":false},"busy":{"description":"Shows the button as adding; only read with `onAddToCart`.","type":"boolean","required":false},"error":{"description":"An error under the button; only read with `onAddToCart`.","type":"string | null","required":false},"className":{"description":"Classes added to the card.","type":"string","required":false}}} />

## `ProductCardSkeletonProps` [#productcardskeletonprops]

Props of [`ProductCardSkeleton`](/themes/sdk/reference/listing/parts-1#productcardskeleton).

<TypeTable type={{"className":{"description":"Classes added to the placeholder.","type":"string","required":false}}} />

## `ProductCardBadgeProps` [#productcardbadgeprops]

Props of [`ProductCardBadge`](/themes/sdk/reference/listing/parts-2#productcardbadge).

<TypeTable type={{"card":{"description":"The card whose badge to show.","type":"ProductCardView","required":true},"className":{"description":"Classes added to the badge.","type":"string","required":false}}} />

## `ProductCardSpecsProps` [#productcardspecsprops]

Props of [`ProductCardSpecs`](/themes/sdk/reference/listing/parts-2#productcardspecs).

<TypeTable type={{"card":{"description":"The card whose attribute values to show.","type":"ProductCardView","required":true},"max":{"description":"How many values show before a \"+N\" chip; 2 when omitted.","type":"number","required":false},"className":{"description":"Classes added to the row of chips.","type":"string","required":false}}} />
