0
# Google Apps Card Framework
1
2
UI components and interactions for building interactive cards in Google Workspace applications. This framework enables rich user interfaces within Gmail, Google Chat, Google Calendar, and other Workspace apps.
3
4
## Core Card Components
5
6
### Card
7
8
Main card container that holds all other UI components.
9
10
```java { .api }
11
class Card {
12
repeated CardSection getSectionsList();
13
CardHeader getHeader();
14
String getName();
15
CardFixedFooter getFixedFooter();
16
DisplayStyle getDisplayStyle();
17
18
static Card.Builder newBuilder();
19
int getSectionsCount();
20
CardSection getSections(int index);
21
boolean hasHeader();
22
boolean hasFixedFooter();
23
}
24
25
enum DisplayStyle {
26
DISPLAY_STYLE_UNSPECIFIED(0),
27
PEEK(1),
28
REPLACE(2);
29
30
int getNumber();
31
static DisplayStyle forNumber(int value);
32
}
33
```
34
35
### CardHeader
36
37
Header section of a card with title, subtitle, and image.
38
39
```java { .api }
40
class CardHeader {
41
String getTitle();
42
String getSubtitle();
43
ImageStyle getImageStyle();
44
String getImageUrl();
45
ImageAltTextType getImageAltText();
46
47
static CardHeader.Builder newBuilder();
48
}
49
50
enum ImageStyle {
51
IMAGE_STYLE_UNSPECIFIED(0),
52
IMAGE(1),
53
AVATAR(2);
54
55
int getNumber();
56
static ImageStyle forNumber(int value);
57
}
58
```
59
60
### CardSection
61
62
Individual section within a card containing widgets.
63
64
```java { .api }
65
class CardSection {
66
String getHeader();
67
repeated Widget getWidgetsList();
68
boolean getCollapsible();
69
int getUncollapsibleWidgetsCount();
70
71
static CardSection.Builder newBuilder();
72
int getWidgetsCount();
73
Widget getWidgets(int index);
74
}
75
```
76
77
## Widget Types
78
79
### Widget
80
81
Base widget container that can hold different types of UI components.
82
83
```java { .api }
84
class Widget {
85
TextParagraph getTextParagraph();
86
Image getImage();
87
DecoratedText getDecoratedText();
88
ButtonList getButtonList();
89
TextInput getTextInput();
90
SelectionInput getSelectionInput();
91
DateTimePicker getDateTimePicker();
92
Divider getDivider();
93
Grid getGrid();
94
Columns getColumns();
95
HorizontalAlignment getHorizontalAlignment();
96
97
static Widget.Builder newBuilder();
98
// Has methods for each widget type
99
boolean hasTextParagraph();
100
boolean hasImage();
101
boolean hasDecoratedText();
102
// ... etc
103
}
104
105
enum HorizontalAlignment {
106
HORIZONTAL_ALIGNMENT_UNSPECIFIED(0),
107
START(1),
108
CENTER(2),
109
END(3);
110
111
int getNumber();
112
static HorizontalAlignment forNumber(int value);
113
}
114
```
115
116
## Text and Display Components
117
118
### TextParagraph
119
120
Simple text display widget.
121
122
```java { .api }
123
class TextParagraph {
124
String getText();
125
int getMaxLines();
126
127
static TextParagraph.Builder newBuilder();
128
}
129
```
130
131
### DecoratedText
132
133
Text with optional icons, buttons, and formatting.
134
135
```java { .api }
136
class DecoratedText {
137
Icon getIcon();
138
String getTopLabel();
139
String getText();
140
boolean getWrapText();
141
String getBottomLabel();
142
OnClick getOnClick();
143
Button getButton();
144
SwitchControl getSwitchControl();
145
146
static DecoratedText.Builder newBuilder();
147
boolean hasIcon();
148
boolean hasOnClick();
149
boolean hasButton();
150
boolean hasSwitchControl();
151
}
152
```
153
154
### Image
155
156
Image display widget with various styling options.
157
158
```java { .api }
159
class Image {
160
String getImageUrl();
161
OnClick getOnClick();
162
double getAspectRatio();
163
String getAltText();
164
165
static Image.Builder newBuilder();
166
boolean hasOnClick();
167
}
168
```
169
170
### Icon
171
172
Icon representation with various sources.
173
174
```java { .api }
175
class Icon {
176
String getKnownIcon();
177
String getIconUrl();
178
String getAltText();
179
ImageType getImageType();
180
181
static Icon.Builder newBuilder();
182
}
183
184
enum ImageType {
185
IMAGE_TYPE_UNSPECIFIED(0),
186
SQUARE(1),
187
CIRCLE(2);
188
189
int getNumber();
190
static ImageType forNumber(int value);
191
}
192
```
193
194
## Input Components
195
196
### TextInput
197
198
Text input field for user data entry.
199
200
```java { .api }
201
class TextInput {
202
String getName();
203
String getLabel();
204
String getHintText();
205
String getValue();
206
Type getType();
207
OnChangeAction getOnChangeAction();
208
Suggestions getSuggestions();
209
boolean getMultiline();
210
211
static TextInput.Builder newBuilder();
212
213
enum Type {
214
SINGLE_LINE(0),
215
MULTIPLE_LINE(1);
216
217
int getNumber();
218
static Type forNumber(int value);
219
}
220
221
boolean hasOnChangeAction();
222
boolean hasSuggestions();
223
}
224
```
225
226
### SelectionInput
227
228
Selection input with various selection types.
229
230
```java { .api }
231
class SelectionInput {
232
String getName();
233
String getLabel();
234
Type getType();
235
repeated SelectionItem getItemsList();
236
OnChangeAction getOnChangeAction();
237
PlatformDataSource getPlatformDataSource();
238
239
static SelectionInput.Builder newBuilder();
240
241
enum Type {
242
CHECK_BOX(0),
243
RADIO_BUTTON(1),
244
SWITCH(2),
245
DROPDOWN(3);
246
247
int getNumber();
248
static Type forNumber(int value);
249
}
250
251
int getItemsCount();
252
SelectionItem getItems(int index);
253
boolean hasOnChangeAction();
254
boolean hasPlatformDataSource();
255
}
256
257
class SelectionItem {
258
String getText();
259
String getValue();
260
boolean getSelected();
261
262
static SelectionItem.Builder newBuilder();
263
}
264
```
265
266
### DateTimePicker
267
268
Date and time picker input.
269
270
```java { .api }
271
class DateTimePicker {
272
String getName();
273
String getLabel();
274
Type getType();
275
long getValueMsEpoch();
276
int getTimezoneOffsetDate();
277
OnChangeAction getOnChangeAction();
278
279
static DateTimePicker.Builder newBuilder();
280
281
enum Type {
282
DATE_AND_TIME(0),
283
DATE_ONLY(1),
284
TIME_ONLY(2);
285
286
int getNumber();
287
static Type forNumber(int value);
288
}
289
290
boolean hasOnChangeAction();
291
}
292
```
293
294
### Suggestions
295
296
Auto-complete suggestions for text inputs.
297
298
```java { .api }
299
class Suggestions {
300
repeated SuggestionItem getItemsList();
301
302
static Suggestions.Builder newBuilder();
303
int getItemsCount();
304
SuggestionItem getItems(int index);
305
}
306
307
class SuggestionItem {
308
String getText();
309
310
static SuggestionItem.Builder newBuilder();
311
}
312
```
313
314
## Interactive Components
315
316
### Button
317
318
Interactive button with various styles and actions.
319
320
```java { .api }
321
class Button {
322
String getText();
323
Icon getIcon();
324
Color getColor();
325
OnClick getOnClick();
326
boolean getDisabled();
327
String getAltText();
328
329
static Button.Builder newBuilder();
330
boolean hasIcon();
331
boolean hasColor();
332
boolean hasOnClick();
333
}
334
335
enum Color {
336
COLOR_UNSPECIFIED(0),
337
RED(1),
338
GREEN(2),
339
BLUE(3),
340
GREY(4);
341
342
int getNumber();
343
static Color forNumber(int value);
344
}
345
```
346
347
### ButtonList
348
349
List of buttons arranged horizontally or vertically.
350
351
```java { .api }
352
class ButtonList {
353
repeated Button getButtonsList();
354
355
static ButtonList.Builder newBuilder();
356
int getButtonsCount();
357
Button getButtons(int index);
358
}
359
```
360
361
### SwitchControl
362
363
Toggle switch control.
364
365
```java { .api }
366
class SwitchControl {
367
String getName();
368
String getValue();
369
boolean getSelected();
370
OnChangeAction getOnChangeAction();
371
ControlType getControlType();
372
373
static SwitchControl.Builder newBuilder();
374
boolean hasOnChangeAction();
375
376
enum ControlType {
377
SWITCH(0),
378
CHECKBOX(1);
379
380
int getNumber();
381
static ControlType forNumber(int value);
382
}
383
}
384
```
385
386
## Layout Components
387
388
### Grid
389
390
Grid layout for organizing widgets in rows and columns.
391
392
```java { .api }
393
class Grid {
394
String getTitle();
395
repeated GridItem getItemsList();
396
int getColumnCount();
397
OnClick getOnClick();
398
BorderStyle getBorderStyle();
399
400
static Grid.Builder newBuilder();
401
int getItemsCount();
402
GridItem getItems(int index);
403
boolean hasOnClick();
404
boolean hasBorderStyle();
405
}
406
407
class GridItem {
408
String getId();
409
Image getImage();
410
String getTitle();
411
String getSubtitle();
412
GridItemLayout getLayout();
413
414
static GridItem.Builder newBuilder();
415
boolean hasImage();
416
417
enum GridItemLayout {
418
GRID_ITEM_LAYOUT_UNSPECIFIED(0),
419
TEXT_BELOW(1),
420
TEXT_ABOVE(2);
421
422
int getNumber();
423
static GridItemLayout forNumber(int value);
424
}
425
}
426
```
427
428
### Columns
429
430
Column-based layout for widgets.
431
432
```java { .api }
433
class Columns {
434
repeated Column getColumnsList();
435
436
static Columns.Builder newBuilder();
437
int getColumnsCount();
438
Column getColumns(int index);
439
}
440
441
class Column {
442
HorizontalSizeStyle getHorizontalSizeStyle();
443
HorizontalAlignment getHorizontalAlignment();
444
VerticalAlignment getVerticalAlignment();
445
repeated Widget getWidgetsList();
446
447
static Column.Builder newBuilder();
448
int getWidgetsCount();
449
Widget getWidgets(int index);
450
451
enum HorizontalSizeStyle {
452
HORIZONTAL_SIZE_STYLE_UNSPECIFIED(0),
453
FILL_AVAILABLE_SPACE(1),
454
FILL_MINIMUM_SPACE(2);
455
456
int getNumber();
457
static HorizontalSizeStyle forNumber(int value);
458
}
459
460
enum VerticalAlignment {
461
VERTICAL_ALIGNMENT_UNSPECIFIED(0),
462
CENTER(1),
463
TOP(2),
464
BOTTOM(3);
465
466
int getNumber();
467
static VerticalAlignment forNumber(int value);
468
}
469
}
470
```
471
472
### Divider
473
474
Visual divider between sections.
475
476
```java { .api }
477
class Divider {
478
// Divider has no configurable properties
479
static Divider.Builder newBuilder();
480
}
481
```
482
483
## Actions and Events
484
485
### OnClick
486
487
Click event handler for interactive elements.
488
489
```java { .api }
490
class OnClick {
491
Action getAction();
492
OpenLink getOpenLink();
493
Card getCard();
494
495
static OnClick.Builder newBuilder();
496
boolean hasAction();
497
boolean hasOpenLink();
498
boolean hasCard();
499
}
500
```
501
502
### Action
503
504
Defines an action to be performed.
505
506
```java { .api }
507
class Action {
508
String getFunction();
509
repeated ActionParameter getParametersList();
510
String getLoadIndicator();
511
boolean getPersistValues();
512
String getInteraction();
513
514
static Action.Builder newBuilder();
515
int getParametersCount();
516
ActionParameter getParameters(int index);
517
518
enum LoadIndicator {
519
SPINNER(0),
520
NONE(1);
521
522
int getNumber();
523
static LoadIndicator forNumber(int value);
524
}
525
526
enum Interaction {
527
INTERACTION_UNSPECIFIED(0),
528
OPEN_DIALOG(1);
529
530
int getNumber();
531
static Interaction forNumber(int value);
532
}
533
}
534
535
class ActionParameter {
536
String getKey();
537
String getValue();
538
539
static ActionParameter.Builder newBuilder();
540
}
541
```
542
543
### OnChangeAction
544
545
Action triggered when input values change.
546
547
```java { .api }
548
class OnChangeAction {
549
Action getAction();
550
551
static OnChangeAction.Builder newBuilder();
552
boolean hasAction();
553
}
554
```
555
556
### OpenLink
557
558
Action to open a URL.
559
560
```java { .api }
561
class OpenLink {
562
String getUrl();
563
OpenAs getOpenAs();
564
OnClose getOnClose();
565
566
static OpenLink.Builder newBuilder();
567
568
enum OpenAs {
569
FULL_SIZE(0),
570
OVERLAY(1);
571
572
int getNumber();
573
static OpenAs forNumber(int value);
574
}
575
576
enum OnClose {
577
NOTHING(0),
578
RELOAD(1);
579
580
int getNumber();
581
static OnClose forNumber(int value);
582
}
583
}
584
```
585
586
## Styling Components
587
588
### BorderStyle
589
590
Border styling options for grid and other components.
591
592
```java { .api }
593
class BorderStyle {
594
Type getType();
595
Color getStrokeColor();
596
int getCornerRadius();
597
598
static BorderStyle.Builder newBuilder();
599
boolean hasStrokeColor();
600
601
enum Type {
602
TYPE_UNSPECIFIED(0),
603
NO_BORDER(1),
604
STROKE(2);
605
606
int getNumber();
607
static Type forNumber(int value);
608
}
609
}
610
```
611
612
### CardFixedFooter
613
614
Fixed footer for cards with primary and secondary buttons.
615
616
```java { .api }
617
class CardFixedFooter {
618
Button getPrimaryButton();
619
Button getSecondaryButton();
620
621
static CardFixedFooter.Builder newBuilder();
622
boolean hasPrimaryButton();
623
boolean hasSecondaryButton();
624
}
625
```
626
627
## Usage Examples
628
629
### Creating a Basic Card
630
631
```java
632
import com.google.apps.card.v1.*;
633
634
Card basicCard = Card.newBuilder()
635
.setHeader(CardHeader.newBuilder()
636
.setTitle("Project Status")
637
.setSubtitle("Development Update")
638
.setImageStyle(ImageStyle.AVATAR)
639
.setImageUrl("https://example.com/project-icon.png")
640
.build())
641
.addSections(CardSection.newBuilder()
642
.setHeader("Current Status")
643
.addWidgets(Widget.newBuilder()
644
.setTextParagraph(TextParagraph.newBuilder()
645
.setText("The project is 85% complete. All major features have been implemented.")
646
.build())
647
.build())
648
.addWidgets(Widget.newBuilder()
649
.setDecoratedText(DecoratedText.newBuilder()
650
.setTopLabel("Progress")
651
.setText("85%")
652
.setIcon(Icon.newBuilder()
653
.setKnownIcon("STAR")
654
.build())
655
.build())
656
.build())
657
.build())
658
.build();
659
```
660
661
### Form Input Card
662
663
```java
664
Card formCard = Card.newBuilder()
665
.setHeader(CardHeader.newBuilder()
666
.setTitle("User Registration")
667
.build())
668
.addSections(CardSection.newBuilder()
669
.addWidgets(Widget.newBuilder()
670
.setTextInput(TextInput.newBuilder()
671
.setName("firstName")
672
.setLabel("First Name")
673
.setHintText("Enter your first name")
674
.setType(TextInput.Type.SINGLE_LINE)
675
.build())
676
.build())
677
.addWidgets(Widget.newBuilder()
678
.setTextInput(TextInput.newBuilder()
679
.setName("email")
680
.setLabel("Email Address")
681
.setHintText("you@example.com")
682
.setType(TextInput.Type.SINGLE_LINE)
683
.build())
684
.build())
685
.addWidgets(Widget.newBuilder()
686
.setSelectionInput(SelectionInput.newBuilder()
687
.setName("department")
688
.setLabel("Department")
689
.setType(SelectionInput.Type.DROPDOWN)
690
.addItems(SelectionItem.newBuilder()
691
.setText("Engineering")
692
.setValue("eng")
693
.build())
694
.addItems(SelectionItem.newBuilder()
695
.setText("Marketing")
696
.setValue("marketing")
697
.build())
698
.build())
699
.build())
700
.build())
701
.setFixedFooter(CardFixedFooter.newBuilder()
702
.setPrimaryButton(Button.newBuilder()
703
.setText("Submit")
704
.setColor(Button.Color.BLUE)
705
.setOnClick(OnClick.newBuilder()
706
.setAction(Action.newBuilder()
707
.setFunction("submitRegistration")
708
.build())
709
.build())
710
.build())
711
.setSecondaryButton(Button.newBuilder()
712
.setText("Cancel")
713
.build())
714
.build())
715
.build();
716
```
717
718
### Interactive Grid Card
719
720
```java
721
Card gridCard = Card.newBuilder()
722
.setHeader(CardHeader.newBuilder()
723
.setTitle("Project Gallery")
724
.build())
725
.addSections(CardSection.newBuilder()
726
.addWidgets(Widget.newBuilder()
727
.setGrid(Grid.newBuilder()
728
.setTitle("Recent Projects")
729
.setColumnCount(2)
730
.setBorderStyle(BorderStyle.newBuilder()
731
.setType(BorderStyle.Type.STROKE)
732
.setCornerRadius(8)
733
.build())
734
.addItems(GridItem.newBuilder()
735
.setId("project1")
736
.setTitle("Mobile App")
737
.setSubtitle("iOS & Android")
738
.setImage(Image.newBuilder()
739
.setImageUrl("https://example.com/mobile-icon.png")
740
.build())
741
.setLayout(GridItem.GridItemLayout.TEXT_BELOW)
742
.build())
743
.addItems(GridItem.newBuilder()
744
.setId("project2")
745
.setTitle("Web Dashboard")
746
.setSubtitle("React Application")
747
.setImage(Image.newBuilder()
748
.setImageUrl("https://example.com/web-icon.png")
749
.build())
750
.setLayout(GridItem.GridItemLayout.TEXT_BELOW)
751
.build())
752
.setOnClick(OnClick.newBuilder()
753
.setAction(Action.newBuilder()
754
.setFunction("openProject")
755
.addParameters(ActionParameter.newBuilder()
756
.setKey("projectId")
757
.setValue("${selectedItem.id}")
758
.build())
759
.build())
760
.build())
761
.build())
762
.build())
763
.build())
764
.build();
765
```
766
767
### Multi-Column Layout
768
769
```java
770
Card columnsCard = Card.newBuilder()
771
.setHeader(CardHeader.newBuilder()
772
.setTitle("Dashboard")
773
.build())
774
.addSections(CardSection.newBuilder()
775
.addWidgets(Widget.newBuilder()
776
.setColumns(Columns.newBuilder()
777
.addColumns(Column.newBuilder()
778
.setHorizontalSizeStyle(Column.HorizontalSizeStyle.FILL_AVAILABLE_SPACE)
779
.setVerticalAlignment(Column.VerticalAlignment.TOP)
780
.addWidgets(Widget.newBuilder()
781
.setTextParagraph(TextParagraph.newBuilder()
782
.setText("Left Column Content")
783
.build())
784
.build())
785
.addWidgets(Widget.newBuilder()
786
.setButton(Button.newBuilder()
787
.setText("Action 1")
788
.setColor(Button.Color.BLUE)
789
.build())
790
.build())
791
.build())
792
.addColumns(Column.newBuilder()
793
.setHorizontalSizeStyle(Column.HorizontalSizeStyle.FILL_AVAILABLE_SPACE)
794
.setVerticalAlignment(Column.VerticalAlignment.TOP)
795
.addWidgets(Widget.newBuilder()
796
.setTextParagraph(TextParagraph.newBuilder()
797
.setText("Right Column Content")
798
.build())
799
.build())
800
.addWidgets(Widget.newBuilder()
801
.setButton(Button.newBuilder()
802
.setText("Action 2")
803
.setColor(Button.Color.GREEN)
804
.build())
805
.build())
806
.build())
807
.build())
808
.build())
809
.build())
810
.build();
811
```
812
813
### Date/Time Picker Example
814
815
```java
816
Card schedulingCard = Card.newBuilder()
817
.setHeader(CardHeader.newBuilder()
818
.setTitle("Schedule Meeting")
819
.build())
820
.addSections(CardSection.newBuilder()
821
.addWidgets(Widget.newBuilder()
822
.setDateTimePicker(DateTimePicker.newBuilder()
823
.setName("meetingDate")
824
.setLabel("Meeting Date")
825
.setType(DateTimePicker.Type.DATE_AND_TIME)
826
.setOnChangeAction(OnChangeAction.newBuilder()
827
.setAction(Action.newBuilder()
828
.setFunction("validateDate")
829
.build())
830
.build())
831
.build())
832
.build())
833
.addWidgets(Widget.newBuilder()
834
.setTextInput(TextInput.newBuilder()
835
.setName("agenda")
836
.setLabel("Meeting Agenda")
837
.setMultiline(true)
838
.setSuggestions(Suggestions.newBuilder()
839
.addItems(SuggestionItem.newBuilder()
840
.setText("Project Review")
841
.build())
842
.addItems(SuggestionItem.newBuilder()
843
.setText("Budget Discussion")
844
.build())
845
.build())
846
.build())
847
.build())
848
.build())
849
.build();
850
```
851
852
## Best Practices
853
854
### Card Design
855
856
1. **Keep it simple**: Avoid overwhelming users with too many widgets in a single card
857
2. **Logical grouping**: Use sections to group related content
858
3. **Consistent styling**: Use consistent colors and icons throughout your cards
859
4. **Clear labels**: Provide clear, descriptive labels for all input fields
860
861
### Performance
862
863
1. **Lazy loading**: Load card content incrementally for better performance
864
2. **Image optimization**: Use appropriately sized images and consider caching
865
3. **Action debouncing**: Debounce user input actions to avoid excessive API calls
866
867
### Accessibility
868
869
1. **Alt text**: Always provide alt text for images and icons
870
2. **Keyboard navigation**: Ensure all interactive elements are keyboard accessible
871
3. **Screen readers**: Test with screen readers to ensure good accessibility
872
4. **Color contrast**: Use sufficient color contrast for text and backgrounds