Location

Location Card

Card for a single store or location with two layouts. A row-style `list` card for store directories, and a square `mapPopup` card for map markers. Wires phone, navigation, and detail actions.

Loading playground

Overview

LocationCard is the card for a single physical location. It carries the store name, image, a single-line address, a pre-formatted distance string, an OpeningStatus summary, up to a handful of feature pills (drive-through, accessibility, parking), and up to three action buttons: Navigate, Call, and Details.

The variant prop picks the layout:

  • list is the row layout for store directories and list panels alongside a map. The card body wraps in an anchor pointing at detailsUrl (so tapping anywhere on the body opens the detail page), and the action buttons stay outside the wrapping anchor to keep the HTML valid. Set bodyAsLink={false} to keep the body clickable for selection only without making it a link.
  • mapPopup is the square popup that sits inside a map marker's info window. The image renders at a fixed 1/1 aspect ratio and the action buttons stretch to the popup's width.

Every interactive action emits the location's id so the parent map or list view can correlate the click without re-deriving identity from props.

Key Business & UX Benefits

  • Two variants from one component keep map popups and list rows visually consistent, so shoppers see the same store information whether they tap a marker or scan the list.
  • Tap-anywhere navigation on the list body (when detailsUrl is set) reduces the tap target precision a shopper needs on mobile, lifting click-through to the detail page.
  • Wiring Navigate, Call, and Details directly as anchors (with tel: for phone and target="_blank" for maps) means iOS and Android handle the actions natively instead of going through JavaScript handlers that can break on slow networks.
  • Stable id on every event lets the parent map view sync selection state without re-deriving identity from the address string.

Feature List

  • Two layouts (`list`, `mapPopup`) cover store directories and map popups from one component
  • Composes `OpeningStatus` so each card carries the current open/closed state and next state-change time
  • Up to three action buttons (Navigate, Call, Details) wired as anchors so iOS and Android handle them natively
  • `bodyAsLink` opts the `list` card out of body-wide linking when the parent only wants to handle selection
  • Up to three feature pills via `FeaturePillList` for callouts like drive-through, accessibility, or parking
  • Every action emits the location `id`, so the parent map or list view can correlate clicks without prop-derived identity
  • Image falls back to a flat placeholder when absent, so missing-image stores don't break the row alignment

API Reference

PropDefaultType
idrequiredstring

Stable identifier — emitted with all events; used by parent for selection.

variantrequired"list" | "mapPopup"

Layout variant.

namerequiredstring

Display name.

image

Location image. Falls back to Media's built-in placeholder when absent.

addressstring

Pre-formatted single-line address. Locale formatting is the consumer's concern.

distancestring

Pre-formatted distance string (e.g. '1,2 km').

openingHours

Schedule + IANA timezone — drives the OpeningStatus child.

features

Up to ~3 inline feature pills (e.g. drive-through, accessibility).

navigateUrlstring

When set, renders the Navigate button as an anchor pointing here.

phonestring

When set, renders the Call button as a tel: anchor.

detailsUrlstring

When set, renders the Details button as an anchor. For variant='list', the card body (image + content) becomes a tap-anywhere link. The action buttons stay outside the wrapping anchor to keep the DOM valid — nested anchors are forbidden by HTML5.

bodyAsLinkboolean

When false, the card body never renders as an anchor — even when detailsUrl is set — so clicking the body only triggers select. The Details action button still renders normally.

EventType
select(event: "select", id: string): void
details(event: "details", id: string): void
navigate(event: "navigate", id: string): void
call(event: "call", id: string): void
Copyright © 2026 Laioutr GmbH