Milestone Stamp Pattern

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 the milestone stamp pattern to visually guide users through sequential steps to complete tasks and show users their progress as they move through the steps. This page explains how you can use this pattern in your interface, and walks through the design structure in detail.

milestone_stamp.png

Design structure

The main components of this pattern are stamps, rich text display fields, and side by side layouts. They're configured to display the progress of a given task. The image below shows the pattern with callouts for the main components. You can examine the entire expression or jump down to the subsections with referenced line numbers to see a detailed breakdown of the main components.

milestone_stamp_details.png

Pattern expression

When you drag and drop the milestone (stamp) pattern onto your interface, 147 lines of expression 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
{
  a!localVariables(
    /* List of icons in milestone (stamp) */
    local!milestoneStampIcons: {"plane", "ticket", "shopping-cart", "check"},
    local!currentMilestoneStampStep: 2,
    {
      /* Display stamps */
      a!sideBySideLayout(
        items: {
          a!sideBySideItem(),
          a!forEach(
            items: local!milestoneStampIcons,
            expression: if(
              /* If final step is completed */
              and(
                fv!index = local!currentMilestoneStampStep,
                fv!index = length(local!milestoneStampIcons)
              ),
              a!sideBySideItem(
                item: a!stampField(
                  icon: fv!item,
                  backgroundColor: "ACCENT",
                  size: "TINY"
                ),
                width: "MINIMIZE"
              ),
              if(
                /* Completed step so far */
                fv!index < local!currentMilestoneStampStep,
                {
                  a!sideBySideItem(
                    item: a!stampField(
                      icon: fv!item,
                      backgroundColor: "ACCENT",
                      size: "TINY"
                    ),
                    width: "MINIMIZE"
                  ),
                  a!sideBySideItem(
                    item: a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: if(
                          a!isPageWidth("PHONE"),
                          repeat(2, char(9473)),
                          if(
                            a!isPageWidth("TABLET_PORTRAIT"),
                            repeat(3, char(9473)),
                            repeat(6, char(9473))
                          )
                        ),
                        color: "ACCENT",
                        size: "LARGE"
                      )
                    ),
                    width: "MINIMIZE"
                  )
                },
                if(
                  /* Current completed step */
                  fv!index = local!currentMilestoneStampStep,
                  {
                    a!sideBySideItem(
                      item: a!stampField(
                        icon: fv!item,
                        backgroundColor: "ACCENT",
                        size: "TINY"
                      ),
                      width: "MINIMIZE"
                    ),
                    a!sideBySideItem(
                      item: a!richTextDisplayField(
                        labelPosition: "COLLAPSED",
                        value: a!richTextItem(
                          text: if(
                            a!isPageWidth("PHONE"),
                            repeat(2, char(9473)),
                            if(
                              a!isPageWidth("TABLET_PORTRAIT"),
                              repeat(3, char(9473)),
                              repeat(6, char(9473))
                            )
                          ),
                          color: "#d4d4d4",
                          size: "LARGE"
                        )
                      ),
                      width: "MINIMIZE"
                    )
                  },
                  /* Future steps to complete */
                  if(
                    fv!index < length(local!milestoneStampIcons),
                    {
                      a!sideBySideItem(
                        item: a!stampField(
                          icon: fv!item,
                          backgroundColor: "#d4d4d4",
                          contentColor: "STANDARD",
                          size: "TINY"
                        ),
                        width: "MINIMIZE"
                      ),
                      a!sideBySideItem(
                        item: a!richTextDisplayField(
                          labelPosition: "COLLAPSED",
                          value: a!richTextItem(
                            text: if(
                              a!isPageWidth("PHONE"),
                              repeat(2, char(9473)),
                              if(
                                a!isPageWidth("TABLET_PORTRAIT"),
                                repeat(3, char(9473)),
                                repeat(6, char(9473))
                              )
                            ),
                            color: "#d4d4d4",
                            size: "LARGE"
                          )
                        ),
                        width: "MINIMIZE"
                      )
                    },
                    /* If final step is incomplete */
                    a!sideBySideItem(
                      item: a!stampField(
                        icon: fv!item,
                        backgroundColor: "#d4d4d4",
                        contentColor: "STANDARD",
                        size: "TINY"
                      ),
                      width: "MINIMIZE"
                    )
                  )
                )
              )
            )
          ),
          a!sideBySideItem()
        },
        alignVertical: "MIDDLE",
        spacing: "NONE",
        marginBelow: "NONE"
      )
    }
  )
}

[Line 1-5] Define the stamps for each milestone

At the top of the pattern, local variables set up an array of icons that will be used as stamps for each milestone in the expression.

1
2
3
4
5
{
  a!localVariables(
    /* List of icons in milestone (stamp) */
    local!milestoneStampIcons: {"plane", "ticket", "shopping-cart", "check"},
    local!currentMilestoneStampStep: 2,

[Line 6-26] Display your stamps

The first component we set up is the a!sideBySideLayout() function. Then, we list the different items we want to display side by side. Inside the items array, we use the a!forEach() looping function. We use this to iterate over every icon listed in the local variables section of the expression.

Once the looping function is set up, we use the conditional if() statement to configure which milestone has been reached by the user and to display the correct highlighted icons. This conditional styling based on the data that's displayed makes it easy for the viewer to quickly see how far their progress is on a task. Once the conditional styling is set up, we then use the a!stampField function to pick out the background color, icon, and size of the stamp we want to display.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
      /* Display stamps */
      a!sideBySideLayout(
        items: {
          a!sideBySideItem(),
          a!forEach(
            items: local!milestoneStampIcons,
            expression: if(
              /* If final step is completed */
              and(
                fv!index = local!currentMilestoneStampStep,
                fv!index = length(local!milestoneStampIcons)
              ),
              a!sideBySideItem(
                item: a!stampField(
                  icon: fv!item,
                  backgroundColor: "ACCENT",
                  size: "TINY"
                ),
                width: "MINIMIZE"
              ),

[Line 39-57] Display your milestone

This section uses a!sidebySideItem() and a!richTextDisplayField() to display the milestone in the pattern. We also use a!isPageWidth() to determine how to display the milestone on Appian for Mobile Devices application.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
a!sideBySideItem(
                    item: a!richTextDisplayField(
                      labelPosition: "COLLAPSED",
                      value: a!richTextItem(
                        text: if(
                          a!isPageWidth("PHONE"),
                          repeat(2, char(9473)),
                          if(
                            a!isPageWidth("TABLET_PORTRAIT"),
                            repeat(3, char(9473)),
                            repeat(6, char(9473))
                          )
                        ),
                        color: "ACCENT",
                        size: "LARGE"
                      )
                    ),
                    width: "MINIMIZE"
                  )

The rest of the pattern follows the same set up as the above sections to configure future milestone steps to complete and determine if the final milestone step is complete.

Open in Github Built: Thu, Feb 23, 2023 (02:59:22 PM)

On This Page

FEEDBACK