Skip to content

Fiori Horizon Data Table Cards

Design

Fiori Horizon Data Table Cards are based on the Material Card View and consist of rows and columns with a title section that can also include subtitle, trend, timestamp and a photo. A maximum of four rows and two columns are supported with the count of the remaining rows displayed at the bottom of the card. The cards can also be displayed by setting an aspect ratio in which the height of the card scales as its width changes. Data Table Cards support both Light mode and Dark mode, as determined by the device's settings.

Data Table Cards in Light Mode Data Table Cards in Dark Mode
Data Table Cards in Light Mode Data Table Cards in Dark Mode

Development

Fiori Horizon Data Table Cards are implemented entirely using Jetpack Compose, including a Composable FioriHorizonTheme. To understand the fundamentals of Jetpack Compose, refer to the Android Developer's documentation.

The fiori-horizon-cards module provides four UI components for application developers to use out of the box:

  • DataTableCard: a UI component to display a single Data Table Card.
  • DataTableCardRow: a UI component to display a series of Data Table Cards in a horizontally scrollable row.
  • DataTableCardColumn: a UI component to display a series of Data Table Cards in a vertically scrollable column.
  • DataTableCardGrid: a UI component to display a series of Data Table Cards in a vertically scrollable grid.

The latter three components are all responsive to different screen sizes.

Usage in an Application

This section describes how to use the Data Table Card components in an application.

Sample Application on a Phone in Light Mode Sample Application on a Phone in Dark Mode

How to Create a DataTableCard

DataTableCard is a Composable function that takes four parameters:

  • A DataTableCardData that specifies the data to be displayed on the card.
  • A Modifier that defines the height and width of the card and/or a TestTag needed for Unit Tests. A default DataTableCardModifier is predefined to set the minimum height and width requirements.
  • A DataTableCardTextColors to customize the default text colors used.
  • A DatatableCardTextStyles to customize the default text styles used.
@Composable
fun DataTableCard(
    data: DataTableCardData,
    modifier: Modifier = dataTableCardModifier,
    textColors: DataTableCardTextColors = DataTableCardDefaults.textColors(),
    textStyles: DatatableCardTextStyles = DataTableCardDefaults.textStyles()
)

An object of DataTableCardData has to be passed in from the application in order to create a DataTableCard.

data class DataTableCardData(
    val tableData: @RawValue List<TableRow>?,
    val title: String? = null,
    val subtitle: String? = null,
    val trendLabel: @RawValue TrendLabel? = null,
    val timestamp: String? = null,
    val imageThumbnail: @RawValue ImageThumbnail? = null,
    val isAspectRatio: Boolean = false,
    val aspectRatio: Pair<Int, Int> = Pair(4, 3),
    val cardStyles: @RawValue CardStyles? = null,
    var cardClickable: Boolean? = true,
    var onCardClick: (() -> Unit)? = null,
    val emptyState: @RawValue EmptyState? = null
) : Parcelable

Creating a DataTableCard can be as simple as the following (if there is no need to provide a custom Modifier):

FioriHorizonTheme(darkTheme = false) {
    val dataTableCardData = remember { generateDataTableCardData() }
    DataTableCard (
        data = dataTableCardData
    )
}

How to Create a DataTableCard with Flexible Ratio and Aspect Ratio

Data Table Card also supports two sizing options: flexible ratio and aspect ratio. Flexible ratio is determined by a user’s layout grid, meaning that the Data Table Card resizes to fill up the space users have dedicated to place this component. In aspect ratio cards, as the width of card changes, the height scales up or down to fit the ratio. It is recommended to use a ratio of 4:3. It is not recommended to use aspect ratio for smaller screen sizes, as the content may not fit the card as intended.

By default, the cards are displayed in flexible ratio. In order to set the aspect ratio, the isAspectRatio property needs to be set to true and the ratio needs to be passed in the aspectRatio property inside DataTableCardData.

val dataTableCardAspectRatio = DataTableCardData(
    tableData = getDataTableCardRowList(),
    title = TITLE,
    timestamp = "5h ago",
    subtitle = SUBTITLE,
    imageThumbnail = IMAGETHUMBNAIL,
    isAspectRatio = true,
    aspectRatio = Pair(4, 3),
    onCardClick = getCardClick()
)

Sample Android Application on a Large Tablet

How to Create an EmptyState DataTableCard

When there is no data available, possibly due to an error, an empty state can be displayed on the Data Table Card along with a message explaining the reason to the user. The empty state can additionally have an image and a button which can direct the user to the next step.

To display an empty state, pass the relevant details to the emptyState property inside the DataTableCardData.

val dataTableCardEmptyState = DataTableCardData(
    tableData = arrayListOf(),
    title = TITLE,
    subtitle = SUBTITLE,
    emptyState = EmptyState(
        title = "Unable to load data",
        description = "Check your internet connection or try reloading.",
        buttonText = "Button", buttonOnClick = ({
            Toast.makeText(context, "Button clicked", Toast.LENGTH_SHORT).show()
        }),
        isFullScreen = false
    )
)
Data Table Cards in Light Mode Data Table Cards in Dark Mode

How to Create a DataTableCardRow, DataTableCardColumn, or DataTableCardGrid

Users can also create a list of Data Table Cards to be displayed on the screen. The SDK provides three different ready-to-use layouts to support this:

  • DataTableCardRow to display a list of Data Table Cards in a horizontally scrollable row.
  • DataTableCardColumn to display a collection of Data Table Cards in a vertically scrollable row.
  • DataTableCardGrid to display a series of Data Table Cards in a vertically scrollable grid.

The DataTableCardRow Composable function allows users to customize the text colors and text styles of the DataTableCard. The other two variants are also similar. The signature of the function is as follows:

@Composable
fun DataTableCardRow(
    cardList: List<DataTableCardDataCustomStyleForCollection>,
    screenType: Enum<ScreenType>,
    modifier: Modifier = Modifier
)

The DataTableCardDataCustomStyleForCollection is comprised of:

data class DataTableCardDataCustomStyleForCollection(
    val data: DataTableCardData,
    val textColors: @RawValue DataTableCardTextColors? = null,
    val textStyles: @RawValue DatatableCardTextStyles? = null
) : Parcelable

In order to create a DataTableCardRow with the default text colors and text styles, use the following function:

@Composable
fun DataTableCardRow(
    cardList: List<DataTableCardData>,
    screenType: Enum<ScreenType>,
    modifier: Modifier = Modifier
)

Customizing the DataTableCard Text Color and Style

The default colors and styles of the text in a Data Table Card adhere to the Fiori Horizon design. However, users can also customize them with their own colors and styles. In order to change the text color and text style, use the DataTableCardDefaults.textColors() and DataTableCardDefaults.textStyles() Composable functions, respectively, and pass in the required colors and styles for the different texts seen within the Data Table Card.

val customTitleColor = MaterialTheme.fioriHorizonAttributes.SapFioriColorSemanticCritical
val customSubtitleColor = MaterialTheme.fioriHorizonAttributes.SapFioriColorAccent4
val customTimestampColor = MaterialTheme.fioriHorizonAttributes.SapFioriColorSemanticNegative
val customMoreEntriesColor = MaterialTheme.fioriHorizonAttributes.SapFioriColorAccent12

val customTitleStyle = FioriTextStyleH6
val customSubtitleStyle = FioriTextStyleSubtitle2
val customTimestampStyle = FioriTextStyleSubtitle3
val customMoreEntriesStyle = FioriTextStyleBody1

FioriHorizonTheme {
    DataTableCard(
        data = generateDataTableCardData(),
        textColors = DataTableCardDefaults.textColors(
            titleColor = customTitleColor,
            subtitleColor = customSubtitleColor,
            timestampColor = customTimestampColor,
            moreEntriesColor = customMoreEntriesColor
        ),
        textStyles = DataTableCardDefaults.textStyles(
            titleStyle = customTitleStyle,
            subtitleStyle = customSubtitleStyle,
            timestampStyle = customTimestampStyle,
            moreEntriesStyle = customMoreEntriesStyle
        )
    )
}

Last update: February 20, 2023