Cards
Cards contain content and actions about a single subject.
Page Summary
Specifications references
Accessibility
Please follow accessibility criteria for development
Images in cards are considered as decorative, so they are ignored by Voice Over.
Variants
Cards are a contained and independent element that can display content and actions on a single topic.
There are a few ways cards can be presented. Ranging from a single title on its own for a simple card view or with more information shown in a subtitle and supporting text and actions at the bottom of the card.
Vertical Image First Card
This is a full width card displayed with an image as first element.
This card is composed of two parts:
- Media: (today an image)
- Content: with a title, an optional subtitle an optional supporting text and optional buttons (zero up to two)
Implementation
Card is configured like this:
ODSCardVerticalImageFirst(
title: Text("Title"),
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
subtitle: Text("Subtitle"),
text: Text("A supporting text to describe something")
) {
Button("Button 1") {
// do something here
}
} secondButton: {
Button("Button 2") {
// do something here
}
}
Vertical Header First Card
This is a full width card displaying with a title and a thumbnail on top as first element.
This card is composed of three parts:
- Header: with a title, an optional subtitle and an optional thmubnail
- Media: (today an image)
- Content: with an optional supporting text and optional buttons (zero up to two)
Implementation
Card is configured like this:
ODSCardVerticalHeaderFirst(
title: Text("Title"),
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
subtitle: Text("Subtitle"),
thumbnailSource: .image(Image("ods_empty", bundle: Bundle.ods)),
text: Text("A supporting text to describe something")
) {
Button("Button 1") {
// do something here
}
} secondButton: {
Button("Button 2") {
// do something here
}
}
Horizontal Card
This is a full width card displaying with image on left and content with texts on the right. Additonal action buttons can be added at the bottom of the card.
Thes content is composed by:
- a title
- an optional subtitle
- an optional text for larger description
Implementation
Card is configured like this:
ODSCardHorizontal(
title: Text("Title"),
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
imagePosition: .leading,
subtitle: Text("Subtitle"),
text: Text("A supporting text to describe something")
) {
Button("Button 1") {
// do something here
}
} secondButton : {
Button("Button 1") {
// do something here
}
}
Small Card
The small card if prefered for two-column portrait mobile screen display. As it is smaller than full-width cards, it contains only title and subtitle (optional) in one line (Truncated tail).
Implementation
Card is configured like this:
ODSCardSmall(
title: Text("Title"),
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
subtitle: Text("Subtitle")
)
How to add Small Card in Grid
class Model {
let title: String
let subtitle: String?
let imageSource: ODSImage.Source
init(title: String, imageSource: ODSImage.Source, subtitle: String? = nil) {
self.title = title
self.imageSource = imageSource
self.subtitle = subtitle
}
}
let models = [
Model(
title: "Title 1",
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
subtitle: "Subtitle 1"
)
Model(
title: "Title 2",
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
subtitle: "Subtitle 2"
)
//...
]
/// /!\ Don't forget to put the grid into a scrollview
ScrollView {
LazyVGrid(columns: columns, spacing: ODSSpacing.none) {
ForEach(models, id:\.title) { model in
ODSCardSmall(
title: Text(model.title),
imageSource: model.imageSource,
subtitle: Text(model.subtitle)
)
}
}
.padding(.all, ODSSpacing.m)
}
However for accessibility edge cases, like when text sizes are accessibility sizes, the behaviour is different for such components. They won’t be displayed in one truncated line because the text will be too truncated and difficult to read. If this choice is too impacting for your UI, it is possible to define the limit number of lines to use if a11y size are used
ODSCardSmall(
title: Text("Title"),
imageSource: .image(Image("ods_empty", bundle: Bundle.ods)),
subtitle: Text("Subtitle"),
// Here 3 is the number of lines you want for such edge cases
titleAccessibleLineLimit: 3,
subtitleAccessibleLineLimit: 3
)