Places Details Component
The Place Details component of the Places UI Kit lets you add an individual UI component that displays place details in your app.

The PlaceDetailsCompactView
renders details for a selected place using minimal space. This may be useful in an info window highlighting a place on a map, in a social media experience like sharing a location in a chat, as a suggestion for selecting your current location, or within a media article to reference the place on Google Maps. The PlaceDetailsCompactView
can display name, address, rating, type, price, accessibility icon, open status, and a single photo.
The Place Details component can be used independently or in conjunction with other Google Maps Platform APIs and services. The component takes either a Place ID or latitude/longitude coordinates and returns rendered Place Details information.
The Place Details component offers a compact view, which can be displayed horizontally or vertically.
The content and visual style of the Place Details component can be configured to match your use case and visual brand guidelines. You can customize the appearance of the place details by providing custom PlacesMaterialTheme
values. You can also customize which place details fields are included by specifying a list of PlaceDetailsCompactView
entries, each of which corresponds to a piece of information shown about the place.
Billing
When using the Place Details UI Kit, you are billed for each time the PlaceDetailsQuery
method is called. If you load the same place multiple times, you are billed for each request.
Add place details to your app
The Place Details component is a Swift UI View. You can customize the look and feel of the place details information to suit your needs and match your app's appearance.
You can specify orientation (horizontal or vertical), theme overrides, and content. The content options are media, address, rating, price, type, accessible entrance, maps link, and directions link. Learn more about customization.
The default position is vertical. If you would like a horizontal layout, specify orientation: .horizontal
in PlaceDetailsCompactView
.
This sample creates a compact view with a vertical layout.
Swift
// Callback for the place details widget. let placeDetailsCallback: (PlaceDetailsResult) -> Void = { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } @Environment(\.colorScheme) var colorScheme var customTheme = false var theme: PlacesMaterialTheme { if customTheme { var theme = PlacesMaterialTheme() var color = PlacesMaterialColor() color.surface = (colorScheme == .dark ? .blue : .gray) color.outlineDecorative = (colorScheme == .dark ? .white : .black) color.onSurface = (colorScheme == .dark ? .yellow : .red) color.onSurfaceVariant = (colorScheme == .dark ? .white : .blue) color.onSecondaryContainer = (colorScheme == .dark ? .white : .red) color.secondaryContainer = (colorScheme == .dark ? .green : .purple) color.positive = (colorScheme == .dark ? .yellow : .red) color.primary = (colorScheme == .dark ? .yellow : .purple) color.info = (colorScheme == .dark ? .yellow : .purple) var shape = PlacesMaterialShape() shape.cornerRadius = 10 var font = PlacesMaterialFont() font.labelLarge = .system(size: UIFontMetrics.default.scaledValue(for: 18)) font.headlineMedium = .system(size: UIFontMetrics.default.scaledValue(for: 15)) font.bodyLarge = .system(size: UIFontMetrics.default.scaledValue(for: 15)) font.bodyMedium = .system(size: UIFontMetrics.default.scaledValue(for: 12)) font.bodySmall = .system(size: UIFontMetrics.default.scaledValue(for: 11)) var attribution = PlacesMaterialAttribution() attribution.lightModeColor = .black attribution.darkModeColor = .white theme.color = color theme.shape = shape theme.font = font theme.attribution = attribution } else { return PlacesMaterialTheme() } } @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID("ChIJT7FdmYiAhYAROFOvrIxRJDU")) var body: some View { PlaceDetailsCompactView( orientation: .vertical, query: $query, contentType: [.media(), .address(), .rating(), .type(), .price(), .accessibleEntranceIcon(), .openNowStatus()], theme: theme, placeDetailsCallback: placeDetailsCallback, preferTruncation: false ) .frame(width: 350) }
This sample creates a compact view with a horizontal layout.
Swift
// Callback for the place details widget. let placeDetailsCallback: (PlaceDetailsResult) -> Void = { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } @Environment(\.colorScheme) var colorScheme var customTheme = false var theme: PlacesMaterialTheme { if customTheme { var theme = PlacesMaterialTheme() var color = PlacesMaterialColor() color.surface = (colorScheme == .dark ? .blue : .gray) color.outlineDecorative = (colorScheme == .dark ? .white : .black) color.onSurface = (colorScheme == .dark ? .yellow : .red) color.onSurfaceVariant = (colorScheme == .dark ? .white : .blue) color.onSecondaryContainer = (colorScheme == .dark ? .white : .red) color.secondaryContainer = (colorScheme == .dark ? .green : .purple) color.positive = (colorScheme == .dark ? .yellow : .red) color.primary = (colorScheme == .dark ? .yellow : .purple) color.info = (colorScheme == .dark ? .yellow : .purple) var shape = PlacesMaterialShape() shape.cornerRadius = 10 var font = PlacesMaterialFont() font.labelLarge = .system(size: UIFontMetrics.default.scaledValue(for: 18)) font.headlineMedium = .system(size: UIFontMetrics.default.scaledValue(for: 15)) font.bodyLarge = .system(size: UIFontMetrics.default.scaledValue(for: 15)) font.bodyMedium = .system(size: UIFontMetrics.default.scaledValue(for: 12)) font.bodySmall = .system(size: UIFontMetrics.default.scaledValue(for: 11)) var attribution = PlacesMaterialAttribution() attribution.lightModeColor = .black attribution.darkModeColor = .white theme.color = color theme.shape = shape theme.font = font theme.attribution = attribution } else { return PlacesMaterialTheme() } } @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID("ChIJT7FdmYiAhYAROFOvrIxRJDU")) var body: some View { PlaceDetailsCompactView( orientation: .horizontal, query: $query, contentType: [.media(), .address(), .rating(), .type(), .price(), .accessibleEntranceIcon(), .mapsLink(), .directionsLink()], theme: theme, placeDetailsCallback: placeDetailsCallback, preferTruncation: false ) .frame(width: 350) }
Customize place details
Places UI kit offers a design system approach to visual customization roughly based on Material Design (with some Google-Maps-specific modifications). See Material Design's reference for Color and Typography. By default, the style adheres to the Google Maps visual design language.

You can customize the following styles:
Width and height
For vertical views, the recommended width is between 180 pixels and 300 pixels. For horizontal views, the recommended width is between 180 pixels and 500 pixels.
Best practice is to not set a height. This will allow the content in the window to set the height, allowing all the information to be displayed.
Attribution colors
Google Maps' terms of service require you to use one of three brand colors for the Google Maps attribution. This attribution must be visible and accessible when customization changes have been made.
We offer 3 brand colors to choose from that can be independently set for light and dark themes:
- Light theme:
attributionColorLight
with enums for white, gray, and black. - Dark theme:
attributionColorDark
with enums for white, gray, and black.
Customization example
This sample shows how to customize the default style attributes.
Swift
// Callback for the place details widget. let placeDetailsCallback: (PlaceDetailsResult) -> Void = { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } @Environment(\.colorScheme) var colorScheme var theme: PlacesMaterialTheme { var theme = PlacesMaterialTheme() theme.colorSurface = (colorScheme == .dark ? .blue : .gray) theme.colorOutlineDecorative = (colorScheme == .dark ? .white : .black) theme.colorPrimary = (colorScheme == .dark ? .white : .black) theme.colorOnSurface = (colorScheme == .dark ? .yellow : .red) theme.colorOnSurfaceVariant = (colorScheme == .dark ? .white : .blue) theme.colorOnSecondaryContainer = (colorScheme == .dark ? .white : .red) theme.colorSecondaryContainer = (colorScheme == .dark ? .green : .purple) theme.colorPositive = (colorScheme == .dark ? .yellow : .red) theme.colorNegative = (colorScheme == .dark ? .white : .black) theme.colorInfo = (colorScheme == .dark ? .yellow : .purple) theme.cornerRadius = 10 theme.bodySmall = .system(size: 11) theme.bodyMedium = .system(size: 12) theme.labelLarge = .system(size: 13) theme.headlineMedium = .system(size: 14) theme.attributionColorLightTheme = .black theme.attributionColorDarkTheme = .white return theme } @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID("ChIJT7FdmYiAhYAROFOvrIxRJDU")) var body: some View { PlaceDetailsCompactView( orientation: .vertical, query: $query, contentType: [.media(), .address(), .rating(), .type(), .price(), .accessibleEntranceIcon(), .mapsLink(), .directionsLink()], theme: theme, placeDetailsCallback: placeDetailsCallback, preferTruncation: false ) .frame(width: 350) }