Cards as Choices

Interface patterns give you an opportunity to explore different interface designs. Be sure to check out How to Adapt a Pattern for Your Application.

Goal

Use this pattern to display sets of choices that are quick and easy to navigate. This page explains how you can use this pattern in your interface, and walks through the design structure in detail.

screenshot of the cards as choices pattern

Design structure

This page will break down the expression so you can better understand how to adapt this pattern to your own data so that it works to best suit your needs.

The main components in this pattern are column layouts, card layouts, rich text, and dynamic links. The image below displays how the pattern looks on a blank interface with callouts for the main components. You can examine the entire expression or jump down to the subsections below with referenced line numbers to see a detailed breakdown of the main components.

screenshot of the cards as choices pattern with callouts highlighting that the pattern contains rich text headers, as well as rich text icons and text within cards

Pattern expression

When you drag and drop the cards as choices pattern onto your interface, 216 lines of expressions will be added to the section where you dragged it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
{
  a!localVariables(
    local!locationChoices: {
      a!map(icon: "building",   name: "North Tower" ),
      a!map(icon: "building-o", name: "South Tower" )
    },
    local!typeChoices: {
      a!map(icon: "shower",           name: "Plumbing"   ),
      a!map(icon: "plug",             name: "Electrical" ),
      a!map(icon: "thermometer-half", name: "HVAC"       )
    },
    local!selectedLocation: 1,
    local!selectedType: 1,
    {
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: {
          a!richTextItem(
            text: "New Work Order",
            color: "STANDARD",
            size: "LARGE_PLUS",
            style: "STRONG"
          )
        },
        align: "CENTER"
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: repeat(3, char(10)),
        align: "CENTER"
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: {
          a!richTextItem(
            text: upper("Location"),
            color: "SECONDARY",
            size: "MEDIUM_PLUS"
          )
        },
        align: "CENTER"
      ),
      a!columnsLayout(
        columns: {
          /* Use an empty column layout on both sides to center the cards */
          a!columnLayout(),
          a!forEach(
            items: local!locationChoices,
            expression: a!columnLayout(
              contents: {
                a!cardLayout(
                  contents: {
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextIcon(
                          icon: if(
                            fv!index = local!selectedLocation,
                            "check-circle",
                            fv!item.icon
                          ),
                          color: "ACCENT",
                          size: "LARGE_PLUS"
                        )
                      },
                      align: "CENTER"
                    ),
                    a!richTextDisplayField(labelPosition: "COLLAPSED"),
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextItem(
                          text: fv!item.name,
                          color: if(
                            fv!index = local!selectedLocation,
                            "STANDARD",
                            "SECONDARY"
                          ),
                          size: "MEDIUM"
                        )
                      },
                      preventWrapping: true,
                      align: "CENTER"
                    )
                  },
                  /* Dynamic link is configured to allow for a selected card to be deselected */
                  link: a!dynamicLink(
                    value: if(fv!index = local!selectedLocation, 0, fv!index),
                    saveInto: local!selectedLocation
                  ),
                  style: if(
                    fv!index = local!selectedLocation,
                    "ACCENT",
                    "NONE"
                  ),
                  padding: "MORE",
                  marginBelow: "STANDARD",
                  showborder: not(fv!index = local!selectedLocation),
                  accessibilityText: if(
                    fv!index = local!selectedLocation,
                    "Selected location. Press enter to deselect.",
                    "Not selected. Press enter to select location."
                  )
                )
              },
              width: "NARROW"
            )
          ),
          a!columnLayout()
        },
        stackWhen: {"PHONE"}
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: repeat(3, char(10)),
        align: "CENTER"
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: {
          a!richTextItem(
            text: upper("Type"),
            color: "SECONDARY",
            size: "MEDIUM_PLUS"
          )
        },
        align: "CENTER"
      ),
      a!columnsLayout(
        columns: {
          a!columnLayout(),
          a!forEach(
            items: local!typeChoices,
            expression: a!columnLayout(
              contents: {
                a!cardLayout(
                  contents: {
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextIcon(
                          icon: if(
                            fv!index = local!selectedType,
                            "check-circle",
                            fv!item.icon
                          ),
                          color: "ACCENT",
                          size: "LARGE_PLUS"
                        )
                      },
                      align: "CENTER"
                    ),
                    a!richTextDisplayField(labelPosition: "COLLAPSED"),
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextItem(
                          text: fv!item.name,
                          color: if(
                            fv!index = local!selectedType,
                            "STANDARD",
                            "SECONDARY"
                          ),
                          size: "MEDIUM"
                        )
                      },
                      preventWrapping: true,
                      align: "CENTER"
                    )
                  },
                  /* Dynamic link is configured to allow for a selected card to be deselected */
                  link: a!dynamicLink(
                    value: if(fv!index = local!selectedType, 0, fv!index),
                    saveInto: local!selectedType
                  ),
                  style: if(
                    fv!index = local!selectedType,
                    "ACCENT",
                    "NONE"
                  ),
                  padding: "MORE",
                  marginBelow: "STANDARD",
                  showborder: not(fv!index = local!selectedType),
                  accessibilityText: if(
                    fv!index = local!selectedType,
                    "Selected type. Press enter to deselect.",
                    "Not selected. Press enter to select type."
                  )
                )
              },
              width: "NARROW"
            )
          ),
          a!columnLayout()
        },
        stackWhen: {"PHONE"}
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: repeat(3, char(10)),
        align: "CENTER"
      ),
      a!buttonArrayLayout(
        buttons: {
          a!buttonWidget(
            label: "Next",
            icon: "arrow-right",
            size: "LARGE",
            style: "PRIMARY"
          )
        },
        align: "CENTER"
      )
    }
  )
}

[Line 1-13] Define local variables

The local variables at the top of the expression are used to define the data that will be displayed in each card and set up a variable to store which card is selected.

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  a!localVariables(
    local!locationChoices: {
      a!map(icon: "building",   name: "North Tower" ),
      a!map(icon: "building-o", name: "South Tower" )
    },
    local!typeChoices: {
      a!map(icon: "shower",           name: "Plumbing"   ),
      a!map(icon: "plug",             name: "Electrical" ),
      a!map(icon: "thermometer-half", name: "HVAC"       )
    },
    local!selectedLocation: 1,
    local!selectedType: 1,

[Line 14-42] Formatting the first two headers and white space

This section uses rich text display fields, rich text items, and styled text to format the first two headers and the white space between them.

The New Work Order and Location headers are created using rich text items. The rich text display field (lines 21-31) creates white space between the headers by using the char() function within the repeat() function.

The char() function returns certain characters based on a numerical input. Here, char(10) is used to return a blank character. The repeat() function then repeats this blank character three times to create the desired amount of white space between the headers.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    {
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: {
          a!richTextItem(
            text: "New Work Order",
            color: "STANDARD",
            size: "LARGE_PLUS",
            style: "STRONG"
          )
        },
        align: "CENTER"
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: repeat(3, char(10)),
        align: "CENTER"
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: {
          a!richTextItem(
            text: upper("Location"),
            color: "SECONDARY",
            size: "MEDIUM_PLUS"
          )
        },
        align: "CENTER"
      ),

[Line 43-112] Configure location choices

This section uses column layouts, the a!forEach() function, card layouts, rich text, and dynamic links to create the Location card choices.

The card choices are created using the a!forEach() function. This function allows you to define one expression that will be iterated through for each card that you want to display. To center the card choices, there is a blank columns layout on either side of a!forEach().

The card choices themselves are made up of a styled icon, styled text, and a dynamic link. The dynamic link allows the cards to be selected and deselected. The style of the card, icon displayed, and text color change depending on whether or not the card is selected. The selected card uses the "ACCENT" style and a circle check icon. The card that isn't selected uses the "NONE" style and the "SECONDARY" text color.

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
      a!columnsLayout(
        columns: {
          /* Use an empty column layout on both sides to center the cards */
          a!columnLayout(),
          a!forEach(
            items: local!locationChoices,
            expression: a!columnLayout(
              contents: {
                a!cardLayout(
                  contents: {
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextIcon(
                          icon: if(
                            fv!index = local!selectedLocation,
                            "check-circle",
                            fv!item.icon
                          ),
                          color: "ACCENT",
                          size: "LARGE_PLUS"
                        )
                      },
                      align: "CENTER"
                    ),
                    a!richTextDisplayField(labelPosition: "COLLAPSED"),
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextItem(
                          text: fv!item.name,
                          color: if(
                            fv!index = local!selectedLocation,
                            "STANDARD",
                            "SECONDARY"
                          ),
                          size: "MEDIUM"
                        )
                      },
                      preventWrapping: true,
                      align: "CENTER"
                    )
                  },
                  /* Dynamic link is configured to allow for a selected card to be deselected */
                  link: a!dynamicLink(
                    value: if(fv!index = local!selectedLocation, 0, fv!index),
                    saveInto: local!selectedLocation
                  ),
                  style: if(
                    fv!index = local!selectedLocation,
                    "ACCENT",
                    "NONE"
                  ),
                  padding: "MORE",
                  marginBelow: "STANDARD",
                  showborder: not(fv!index = local!selectedLocation),
                  accessibilityText: if(
                    fv!index = local!selectedLocation,
                    "Selected location. Press enter to deselect.",
                    "Not selected. Press enter to select location."
                  )
                )
              },
              width: "NARROW"
            )
          ),
          a!columnLayout()
        },
        stackWhen: {"PHONE"}
      ),

[Line 113-128] Format the type heading and white space

This formatting section is similar to the first, but only creates a heading for Type.

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: repeat(3, char(10)),
        align: "CENTER"
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: {
          a!richTextItem(
            text: upper("Type"),
            color: "SECONDARY",
            size: "MEDIUM_PLUS"
          )
        },
        align: "CENTER"
      ),

[Line 129-216] Configure type choices

This section is similar to the configure Location choices section and creates card choices to go beneath the Type header. This section also includes an additional rich text display field and a buttons layout. This rich text display (lines 198-202) is used to create white space above the Next button.

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
      a!columnsLayout(
        columns: {
          a!columnLayout(),
          a!forEach(
            items: local!typeChoices,
            expression: a!columnLayout(
              contents: {
                a!cardLayout(
                  contents: {
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextIcon(
                          icon: if(
                            fv!index = local!selectedType,
                            "check-circle",
                            fv!item.icon
                          ),
                          color: "ACCENT",
                          size: "LARGE_PLUS"
                        )
                      },
                      align: "CENTER"
                    ),
                    a!richTextDisplayField(labelPosition: "COLLAPSED"),
                    a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: {
                        a!richTextItem(
                          text: fv!item.name,
                          color: if(
                            fv!index = local!selectedType,
                            "STANDARD",
                            "SECONDARY"
                          ),
                          size: "MEDIUM"
                        )
                      },
                      preventWrapping: true,
                      align: "CENTER"
                    )
                  },
                  /* Dynamic link is configured to allow for a selected card to be deselected */
                  link: a!dynamicLink(
                    value: if(fv!index = local!selectedType, 0, fv!index),
                    saveInto: local!selectedType
                  ),
                  style: if(
                    fv!index = local!selectedType,
                    "ACCENT",
                    "NONE"
                  ),
                  padding: "MORE",
                  marginBelow: "STANDARD",
                  showborder: not(fv!index = local!selectedType),
                  accessibilityText: if(
                    fv!index = local!selectedType,
                    "Selected type. Press enter to deselect.",
                    "Not selected. Press enter to select type."
                  )
                )
              },
              width: "NARROW"
            )
          ),
          a!columnLayout()
        },
        stackWhen: {"PHONE"}
      ),
      a!richTextDisplayField(
        labelPosition: "COLLAPSED",
        value: repeat(3, char(10)),
        align: "CENTER"
      ),
      a!buttonArrayLayout(
        buttons: {
          a!buttonWidget(
            label: "Next",
            icon: "arrow-right",
            size: "LARGE",
            style: "PRIMARY"
          )
        },
        align: "CENTER"
      )
    }
  )
}
Open in Github Built: Thu, Feb 23, 2023 (02:59:22 PM)

On This Page

FEEDBACK