Skip to content

Temp cardscript readme

Tim Needham edited this page Jan 9, 2019 · 2 revisions

Cardscript

Version 0.0.6

Build Status CodeFactor Known Vulnerabilities JavaScript Style Guide lerna Dependabot badge PRs Welcome

The goal of Cardscript is to provide a JSON-based language to describe User Interfaces (especially those which form part of a digital service).

Getting started

Get hands-on with Cardscript using the online Cardscript Playpen!

Table of Contents

Structure of a Card

In Cardscript, a card is represented by a JSON Object.

Example: Simple Card

The content of a card is specified by configuring one-or-more elements, which are represented by JSON objects.

  • In this example, a card is defined that contains two elements, one that defines a suitable Jumbotron (with some text and an accompanying image), followed by a second Input.Text-element for letting the user enter their name.
{
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "Container",
      "items": [
        {
          "type": "Jumbotron",
          "backgroundImage": "wmfs/happy-people.jpg",
          "title": "Register!",
          "subtitle": "Let's get to know each other a bit better...",
          "wash": "black"
        },
        {
          "type": "TextBlock",
          "text": "Name",
          "wrap": true,
          "separator": true
        },
        {
          "type": "Input.Text",
          "id": "name",
          "placeholder": "e.g. Lucy Smith"
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Submit"
    }
  ]
}

Concepts

Cardscript is built on a handful of key concepts...

Cards

The purpose of Cardscript is to define a user interface, referred to as a "card".

  • With Cardscript it's possible to configure a card with structure, validation, conditional content, dynamic values and context-sensitive behaviours (e.g. operating differently with an internet connection as opposed to without).
  • Cardscript definitions are naturally stored in .json files (typically one-file-per-view).
  • In certain situations YAML (itself just a superset of JSON) may offer an interesting alternative to serialising Cardscript definitions (the cardscript-parser utility supports both)..
  • Please note that a JSON Schema is available here, which may be used to validate the basic integrity of Cardscript content.
  • For more comprehensive Cardscript validation, please refer to the cardscript-schema package.

Apps

Views defined in Cardscript may be rendered and executed by software. In this document, such software is referred to an "app".

  • Apps can be implemented in any frontend-framework, language or library.
  • Cardscript does not impose any aesthetic or UI constraints onto apps which implement it.
  • Cardscript content can be embedded inside apps with GUI, CLI and even Voice-User interfaces.
  • Please note several utilities are available to help embed Cardscript into apps. Please see Appendix B: Cardscript Utilities for further information.

Elements

Cards are constructed from an ordered list of "elements".

  • To avoid overloading frontend-terms like 'component', Cardscript refers to each object in the elements array as an element.
  • Consider an element as an area of a view responsible for a particular task: either collecting a specific piece of information from a user or visualising some data.
  • As such, elements can be interactive (Input.Text, Input.Number, etc.) and non-interactive (Jumbotron, Media etc.)
  • The order that Element objects appear within a view definition is important - representing the order users will encounter them.
  • Cardscript is a delightful walled-garden, offering a fixed set of 46 p re-configured elements. If you need another element-type or an extra attribute... pull requests are very welcome! 😊

Ahead of the Reference section, here's a quick summary of the 46 elements supported in Cardscript 0.0.6:

Element summary

Element Type Description
Action.Cancel Allows to cancel out of a form.
Action.OpenUrl When invoked, show the given url either by launching it in an external web browser or showing in-situ with embedded web browser.
Action.Save Allows to save a form to continue later.
Action.ShowCard Defines an AdaptiveCard which is shown to the user when the button or link is clicked.
Action.Submit Gathers input fields, merges with optional data field, and sends an event to the client. It is up to the client to determine how this data is processed. For example: With BotFramework bots, the client would send an activity through the messaging medium to the bot.
ActionSet ActionSet allows actions to be displayed within a card.
AdaptiveCard Root element in an Adaptive Card.
AddressBlock Displays an address.
CardList A container which opens a modal when clicked on to show a card.
Chip A chip to display some text.
Collapsible A container which expands when clicked on to show a card.
Column Defines a container that is part of a ColumnSet.
ColumnSet ColumnSet divides a region into Columns, allowing elements to sit side-by-side.
Container Containers group items together.
Fact Describes a Fact in a FactSet as a key/value pair.
FactSet The FactSet element displays a series of facts (i.e. name/value pairs) in a tabular form.
Image Displays an image.
ImageSet The ImageSet displays a collection of Images similar to a gallery.
Input.Address Lets a user enter an address.
Input.ApiLookup Lets a user look up a value via an API.
Input.Choice Describes a choice for use in a ChoiceSet.
Input.ChoiceSet Allows a user to input a Choice.
Input.Currency Lets a user enter a currency value.
Input.Date Lets a user choose a date.
Input.DateTime Lets a user enter a telephone number.
Input.Email Lets a user enter an email.
Input.FileUpload Lets a user upload a file.
Input.Gender Lets a user enter a gender.
Input.Name Lets a user enter a name.
Input.Number Allows a user to enter a number.
Input.Signature Lets a user enter a signature.
Input.Slider Lets a user enter value with a slider.
Input.TelephoneNumber Lets a user enter a telephone number.
Input.Text Lets a user enter text.
Input.Time Lets a user select a time.
Input.Toggle Lets a user choose between two options.
Jumbotron An element typically placed at the top of a card to describe its purpose.
Map Displays a map.
Media Displays a media player for audio or video content.
MediaSource Defines a source for a Media element
PhaseBanner Displays a banner highlighting a phase.
Separator Displays a horizontal line.
Tab Defines a container that is part of a TabSet.
TabSet TabSet allows to display content through various tabs.
Table Displays text, allowing control over font sizes, weight, and color.
TextBlock Displays text, allowing control over font sizes, weight, and color.

Containers

All the elements that define a view's content are specified in a simple array. This design helps align Cardscript with vertical-scrolling interfaces with very little friction. To assist with navigation (especially around larger, more complex content) it might be useful to split a view into more manageable pieces.

  • In Cardscript, containers allow elements to be grouped into related chunks.

Example JSON

{
  "title": "Simple set demo!",
  "widgets": [
    {
      "type": "set",
      "attributes": {
        "tocTitle": "Profile"
      }
    },
    {
      "id": "name",
      "type": "text",
      "attributes": {
        "heading": "Name",
        "placeholder": "e.g. Lucy Smith",
        "mandatory": true,
        "minCharacters": 1,
        "maxCharacters": 100,
        "help": "Enter your full name here"
      }
    },
    {
      "type": "endSet"
    }
  ]
}
  • In this example, we are declaring that a text element (with the id name) should be rendered within a container (which should appear in a Table of Contents with the heading "Profile").
  • The beginning of each container is marked with a container element.
  • Nesting of containers is possible and containers are especially powerful when combined with dynamic expressions to conditionally show/hide content.
  • Containers also enable apps to offer progress tracking functionality.
  • Multi-step "wizard" interfaces are also easily achieved via containers.
  • The CardList element uses exactly the same technique to define repeating-groups of elements.

Expressions

Cardscript uses expressions to deliver dynamic content. Expressions are used to:

  • Conditionally show/hide elements depending on values as they change.
  • Validate card content based on more complex business rules.
  • Affect the contents of enumerated lists.
  • Default dynamic values.
  • Calculate running totals, real-time summaries etc.

Consider an expression to be something that could be evaluated in a Javascript if (...) {} statement.

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "Jumbotron",
      "backgroundImage": "wmfs/happy-people.jpg",
      "title": "All done!",
      "subtitle": "We're all done here, we would really appreciate some feedback though!",
      "wash": "black"
    },
    {
      "spacing": "large",
      "id": "userWantsToGiveFeedback",
      "type": "Input.Toggle",
      "title": "I would like to leave some feedback"
    },
    {
      "spacing": "large",
      "id": "feedback",
      "showWhen": "data.userWantsToGiveFeedback === true",
      "type": "Input.Text",
      "isMultiline": "true",
      "placeholder": "Feedback"
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.0"
}

In the example above we have three elements:

  1. The first element is a simple jumbotron.
  2. The second element is a simple boolean on/off Input.Toggle (with the id of userWantsToGiveFeedback) which is by default set to false.
  3. The third element is an Input.Text box (with the id of feedback) for collecting feedback from the user.

The feedback element should only show if the userWantsToGiveFeedback toggle is thrown on (i.e. true).

There are a few new things going on here. Most types of element (here the Toggle and Input.Text types) expect an app to read and write their values to an underlying data object (using their respective id values as keys). It is also expected that any app implementing Cardscript should also make this data object available within a safe sandbox while evaluating expressions.

In the previous example we can see the showWhen attribute is being used on the feedback element. The string value here is an expression, which will control the visibility of the element (i.e. it should only be shown to the user when the expression evaluates to true).

Expression sandbox

Apps must ensure expressions are evaluated in a safe sandbox context. As such only certain objects may be referred to within an expression:

Sandbox object Description
data The current card data being stored. Should be kept fresh in real-time using UI binding techniques.
env Some environmental information, e.g. the user's name, if the app has access to an internet connection etc.
env object properties

Apps are expected to provide the following details via an env object when evaluating expressions:

Property Type Description
username string Username of the the user currently using the form.
startedOffline boolean Indicates if the form was started online, or not.

Reference

Card Elements

Cardscript 0.0.6 supports a set of 46 common attributes from which elements can be configured. Not one element-type requires all these attributes. Attributes are often optional and some element-types don't need an attributes object at all.

Element Name Type Description
Action.Cancel object Allows to cancel out of a form.
Action.OpenUrl object When invoked, show the given url either by launching it in an external web browser or showing in-situ with embedded web browser.
Action.Save object Allows to save a form to continue later.
Action.ShowCard object Defines an AdaptiveCard which is shown to the user when the button or link is clicked.
Action.Submit object Gathers input fields, merges with optional data field, and sends an event to the client. It is up to the client to determine how this data is processed. For example: With BotFramework bots, the client would send an activity through the messaging medium to the bot.
ActionSet object ActionSet allows actions to be displayed within a card.
AdaptiveCard object Root element in an Adaptive Card.
AddressBlock object Displays an address.
CardList object A container which opens a modal when clicked on to show a card.
Chip object A chip to display some text.
Collapsible object A container which expands when clicked on to show a card.
Column object Defines a container that is part of a ColumnSet.
ColumnSet object ColumnSet divides a region into Columns, allowing elements to sit side-by-side.
Container object Containers group items together.
Fact object Describes a Fact in a FactSet as a key/value pair.
FactSet object The FactSet element displays a series of facts (i.e. name/value pairs) in a tabular form.
Image object Displays an image.
ImageSet object The ImageSet displays a collection of Images similar to a gallery.
Input.Address object Lets a user enter an address.
Input.ApiLookup object Lets a user look up a value via an API.
Input.Choice object Describes a choice for use in a ChoiceSet.
Input.ChoiceSet object Allows a user to input a Choice.
Input.Currency object Lets a user enter a currency value.
Input.Date object Lets a user choose a date.
Input.DateTime object Lets a user enter a telephone number.
Input.Email object Lets a user enter an email.
Input.FileUpload object Lets a user upload a file.
Input.Gender object Lets a user enter a gender.
Input.Name object Lets a user enter a name.
Input.Number object Allows a user to enter a number.
Input.Signature object Lets a user enter a signature.
Input.Slider object Lets a user enter value with a slider.
Input.TelephoneNumber object Lets a user enter a telephone number.
Input.Text object Lets a user enter text.
Input.Time object Lets a user select a time.
Input.Toggle object Lets a user choose between two options.
Jumbotron object An element typically placed at the top of a card to describe its purpose.
Map object Displays a map.
Media object Displays a media player for audio or video content.
MediaSource object Defines a source for a Media element
PhaseBanner object Displays a banner highlighting a phase.
Separator object Displays a horizontal line.
Tab object Defines a container that is part of a TabSet.
TabSet object TabSet allows to display content through various tabs.
Table object Displays text, allowing control over font sizes, weight, and color.
TextBlock object Displays text, allowing control over font sizes, weight, and color.

Element List

Here is the full list of all 46 elements supported in Cardscript 0.0.6 (please see Element summary for a handy index).


The Action.Cancel element

Allows to cancel out of a form.

Example JSON

{
  "type": "Action.Cancel",
  "title": "Cancel"
}

Properties

Name Type Required Description
type string Required Must be "Action.Cancel".
title string Optional Label for button or link that represents this action.
iconUrl string Optional Optional icon to be shown on the action in conjunction with the title

The Action.OpenUrl element

When invoked, show the given url either by launching it in an external web browser or showing in-situ with embedded web browser.

Example JSON

{
  "type": "Action.OpenUrl",
  "title": "Open Url",
  "url": "https://github.com/wmfs/cardscript"
}

Properties

Name Type Required Description
type string Required Must be "Action.OpenUrl".
title string Optional Label for button or link that represents this action.
iconUrl string Optional Optional icon to be shown on the action in conjunction with the title
url string Required The URL to open.

The Action.Save element

Allows to save a form to continue later.

Example JSON

{
  "type": "Action.Save",
  "title": "Save"
}

Properties

Name Type Required Description
type string Required Must be "Action.Save".
title string Optional Label for button or link that represents this action.
iconUrl string Optional Optional icon to be shown on the action in conjunction with the title

The Action.ShowCard element

Defines an AdaptiveCard which is shown to the user when the button or link is clicked.

Example JSON

{
  "type": "Action.ShowCard",
  "title": "Action.ShowCard",
  "card": {
    "type": "AdaptiveCard",
    "body": [
      {
        "type": "TextBlock",
        "text": "What do you think?"
      },
      {
        "id": "opinion",
        "type": "Input.Text",
        "spacing": "large",
        "default": "Amazing!"
      }
    ]
  }
}

Properties

Name Type Required Description
type string Required Must be "Action.ShowCard".
title string Optional Label for button or link that represents this action.
iconUrl string Optional Optional icon to be shown on the action in conjunction with the title
card Required

The Action.Submit element

Gathers input fields, merges with optional data field, and sends an event to the client. It is up to the client to determine how this data is processed. For example: With BotFramework bots, the client would send an activity through the messaging medium to the bot.

Example JSON

{
  "type": "Action.Submit",
  "title": "Submit",
  "data": {
    "x": "y"
  }
}

Properties

Name Type Required Description
type string Required Must be "Action.Submit".
title string Optional Label for button or link that represents this action.
iconUrl string Optional Optional icon to be shown on the action in conjunction with the title
data string,object Optional Initial data that input fields will be combined with. These are essentially 'hidden' properties.

The ActionSet element

ActionSet allows actions to be displayed within a card.

Example JSON

{
  "type": "ActionSet",
  "spacing": "large",
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "Open Url",
      "url": "https://github.com/wmfs/cardscript"
    },
    {
      "type": "Action.Submit",
      "title": "Submit",
      "data": {
        "x": "y"
      }
    }
  ]
}

Properties

Name Type Required Description
type string Required Must be "ActionSet".
actions Required The Actions to show in the card's action bar.
spacing Optional

The AdaptiveCard element

Root element in an Adaptive Card.

Example JSON

{
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "Container",
      "items": [
        {
          "type": "Jumbotron",
          "backgroundImage": "wmfs/happy-people.jpg",
          "title": "Register!",
          "subtitle": "Let's get to know each other a bit better...",
          "wash": "black"
        },
        {
          "type": "TextBlock",
          "text": "Name",
          "wrap": true,
          "separator": true
        },
        {
          "type": "Input.Text",
          "id": "name",
          "placeholder": "e.g. Lucy Smith"
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Submit"
    }
  ]
}

Properties

Name Type Required Description
type string Required Must be "AdaptiveCard".
actions Optional The Actions to show in the card's action bar.
body Optional The card elements to show in the primary card region.
selectAction object Optional An Action that will be invoked when the card is tapped or selected. Action.ShowCard is not supported.

The AddressBlock element

Displays an address.

Example JSON

{
  "type": "AddressBlock",
  "dataPath": "addressBlock"
}

Properties

Name Type Required Description
type string Required Must be "AddressBlock".
title string Optional Title of the AddressBlock.
dataPath string Required Points to the holding the address.
multiline boolean Optional Wether the address in multiple lines.
lineDelimited string Optional The string of character(s) which the address is delimited by.

The CardList element

A container which opens a modal when clicked on to show a card.

Example JSON

{
  "id": "cardList",
  "type": "CardList",
  "editable": true,
  "instanceTitleTemplate": "You thought: '{{item.opinion}}'.",
  "addButtonLabel": "Click me!",
  "card": {
    "type": "AdaptiveCard",
    "body": [
      {
        "type": "TextBlock",
        "text": "What do you think?"
      },
      {
        "id": "opinion",
        "type": "Input.Text",
        "spacing": "large",
        "value": "Amazing!"
      }
    ]
  }
}

Properties

Name Type Required Description
id string Required A unique identifier associated with the element.
type string Required Must be "CardList".
addButtonLabel string Optional Text to be displayed as label of button.
card Required
instanceTitleTemplate string Optional A handlebars-like template for conjuring a title per instance.
instanceSubtitleTemplate string Optional A handlebars-like template for conjuring a subtitle per instance.
editable boolean Optional The CardList element can either act as a modal to display a block of Card Elements or as a form which can be completed and pushed to an array.

The Chip element

A chip to display some text.

Example JSON

{
  "type": "Chip",
  "text": "Example",
  "color": "good"
}

Properties

Name Type Required Description
type string Required Must be "Chip".
text string Required Text to be displayed in chip.
color string Optional Color of the chip

The Collapsible element

A container which expands when clicked on to show a card.

Example JSON

{
  "type": "Collapsible",
  "title": "Click me!",
  "card": {
    "type": "AdaptiveCard",
    "body": [
      {
        "type": "TextBlock",
        "text": "Hello!"
      }
    ]
  }
}

Properties

Name Type Required Description
type string Required Must be "Collapsible".
title string Required Text to be displayed as label.
card Required

The Column element

Defines a container that is part of a ColumnSet.

Example JSON

{
  "type": "Column",
  "items": [
    {
      "type": "TextBlock",
      "text": "col-1"
    },
    {
      "type": "TextBlock",
      "text": "col-1"
    }
  ]
}

Properties

Name Type Required Description
items Required The card elements to include in the Column.
selectAction object Optional An Action that will be invoked when the Column is tapped or selected. Action.ShowCard is not supported.
style string Optional Style hint for Column.
width string,number Optional "auto", "stretch", or a number representing relative width of the column in the column group.
type string Optional Must be "Column".

The ColumnSet element

ColumnSet divides a region into Columns, allowing elements to sit side-by-side.

Example JSON

{
  "type": "ColumnSet",
  "columns": [
    {
      "type": "Column",
      "items": [
        {
          "type": "TextBlock",
          "text": "col-1"
        },
        {
          "type": "TextBlock",
          "text": "col-1"
        }
      ]
    },
    {
      "type": "Column",
      "items": [
        {
          "type": "TextBlock",
          "text": "col-2"
        }
      ]
    }
  ]
}

Properties

Name Type Required Description
columns array Optional The array of Columns to divide the region into.
selectAction object Optional An Action that will be invoked when the ColumnSet is tapped or selected. Action.ShowCard is not supported.
type string Required Must be "ColumnSet".

The Container element

Containers group items together.

Example JSON

{
  "type": "Container",
  "color": "accent",
  "spacing": "large",
  "items": [
    {
      "type": "TextBlock",
      "text": "Accent!"
    }
  ]
}

Properties

Name Type Required Description
type string Required Must be "Container".
color string Optional Controls the color of the Container.
items Required The card elements to render inside the Container.
selectAction object Optional An Action that will be invoked when the Container is tapped or selected. Action.ShowCard is not supported.
style string Optional Style hint for Container.
verticalContentAlignment string Optional Defines how the content should be aligned vertically within the container.

The Fact element

Describes a Fact in a FactSet as a key/value pair.

Example JSON

{
  "title": "Hello:",
  "value": "World"
}

Properties

Name Type Required Description
type string Optional
title string Required The title of the fact.
value string Required The value of the fact.

The FactSet element

The FactSet element displays a series of facts (i.e. name/value pairs) in a tabular form.

Example JSON

{
  "type": "FactSet",
  "facts": [
    {
      "title": "Hello:",
      "value": "World"
    },
    {
      "title": "HELLO:",
      "value": "WORLD"
    }
  ]
}

Properties

Name Type Required Description
facts array Required The array of Facts.
type string Required Must be "FactSet".

The Image element

Displays an image.

Example JSON

{
  "type": "Image",
  "url": "https://tymly.io/wp-content/uploads/2017/11/logo-tymly-main-colour.png",
  "size": "large",
  "horizontalAlignment": "left"
}

Properties

Name Type Required Description
altText string Optional Alternate text describing the image.
horizontalAlignment Optional
selectAction object Optional An Action that will be invoked when the Image is tapped or selected. Action.ShowCard is not supported.
size Optional
style Optional
type string Required Must be "Image".
url string Required The URL to the image.

The ImageSet element

The ImageSet displays a collection of Images similar to a gallery.

Example JSON

{
  "type": "ImageSet",
  "images": [
    {
      "type": "Image",
      "url": "https://tymly.io/wp-content/uploads/2017/11/logo-tymly-main-colour.png",
      "size": "medium"
    },
    {
      "type": "Image",
      "url": "https://tymly.io/wp-content/uploads/2017/11/logo-tymly-main-colour.png",
      "size": "medium"
    }
  ]
}

Properties

Name Type Required Description
images array Required The array of Image elements to show.
imageSize Optional
type string Required Must be "ImageSet".

The Input.Address element

Lets a user enter an address.

Example JSON

{
  "id": "inputAddress",
  "type": "Input.Address"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Address".

The Input.ApiLookup element

Lets a user look up a value via an API.

Example JSON

{
  "id": "inputApiLookup",
  "type": "Input.ApiLookup"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.ApiLookup".

The Input.Choice element

Describes a choice for use in a ChoiceSet.

Example JSON

{
  "title": "Choice 1",
  "value": "CHOICE_1"
}

Properties

Name Type Required Description
type string Optional
title string Required Text to display.
value string Required The raw value for the choice. NOTE: do not use a , in the value, since a ChoiceSet with isMultiSelect set to true returns a comma-delimited string of choice values.

The Input.ChoiceSet element

Allows a user to input a Choice.

Example JSON

{
  "type": "Input.ChoiceSet",
  "id": "choice",
  "spacing": "medium",
  "value": "CHOICE_1",
  "choices": [
    {
      "title": "Choice 1",
      "value": "CHOICE_1"
    },
    {
      "title": "Choice 2",
      "value": "CHOICE_2"
    },
    {
      "title": "Choice 3",
      "value": "CHOICE_3"
    }
  ],
  "style": "expanded"
}

Properties

Name Type Required Description
choices array Required Choice options.
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
isMultiSelect boolean Optional Allow multiple choices to be selected.
style Optional
type string Required Must be "Input.ChoiceInput".
value string Optional The initial choice (or set of choices) that should be selected. For multi-select, specify a comma-separated string of values.

The Input.Currency element

Lets a user enter a currency value.

Example JSON

{
  "id": "currency",
  "type": "Input.Currency",
  "placeholder": "Input.Currency",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Currency".
placeholder string Optional Description of the input desired. Displayed when no text has been input.
max number Optional Hint of maximum value (may be ignored by some clients).
min number Optional Hint of minimum value (may be ignored by some clients).

The Input.Date element

Lets a user choose a date.

Example JSON

{
  "id": "date",
  "type": "Input.Date",
  "placeholder": "Input.Date",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
max string Optional Hint of maximum value expressed in ISO-8601 format (may be ignored by some clients).
min string Optional Hint of minimum value expressed in ISO-8601 format (may be ignored by some clients).
placeholder string Optional Description of the input desired. Displayed when no selection has been made.
type string Required Must be "Input.Date".
value string Optional The initial value for this field expressed in ISO-8601 format.

The Input.DateTime element

Lets a user enter a telephone number.

Example JSON

{
  "id": "date",
  "type": "Input.DateTime",
  "placeholder": "Input.DateTime",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.DateTime".
placeholder string Optional Description of the input desired. Displayed when no text has been input.

The Input.Email element

Lets a user enter an email.

Example JSON

{
  "id": "email",
  "type": "Input.Email",
  "placeholder": "Input.Email",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Email".
placeholder string Optional Description of the input desired. Displayed when no text has been input.

The Input.FileUpload element

Lets a user upload a file.

Example JSON

{
  "type": "Input.FileUpload",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.FileUpload".

The Input.Gender element

Lets a user enter a gender.

Example JSON

{
  "id": "inputGender",
  "type": "Input.Gender",
  "preferNotToSay": true,
  "preferToSelfDescribe": true,
  "includeTransgender": true
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Gender".
term string Optional Whether the gender or sex should be asked.
preferNotToSay boolean Optional Includes Prefer not to say gender in list.
preferToSelfDescribe boolean Optional Includes Prefer not to self describe gender in list.
includeTransgender boolean Optional Includes transgender in list.

The Input.Name element

Lets a user enter a name.

Example JSON

{
  "id": "name",
  "type": "Input.Name",
  "placeholder": "Input.Name",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Name".

The Input.Number element

Allows a user to enter a number.

Example JSON

{
  "id": "number",
  "type": "Input.Number",
  "placeholder": "Input.Number",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
max number Optional Hint of maximum value (may be ignored by some clients).
min number Optional Hint of minimum value (may be ignored by some clients).
placeholder string Optional Description of the input desired. Displayed when no selection has been made.
type string Required Must be "Input.Number".
value number Optional Initial value for this field.

The Input.Signature element

Lets a user enter a signature.

Example JSON

{
  "id": "inputSignature",
  "type": "Input.Signature",
  "agreement": "I agree that...",
  "saveText": "Send",
  "guidance": "Please enter your signature below..."
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Signature".
agreement string Optional Agreement text to be displayed above the signature pad.
saveText string Optional Customise the text of the save button.
guidance string Optional Guidance text to be displayed with the signature button.

The Input.Slider element

Lets a user enter value with a slider.

Example JSON

{
  "id": "slider",
  "type": "Input.Slider",
  "spacing": "medium",
  "min": -20,
  "max": 20,
  "step": 4,
  "value": 3
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.Slider".
min number Optional Minimum value of the model.
max number Optional Maximum value of the model.
step number Optional Step amount between values.
value string Optional The initial value for this field.

The Input.TelephoneNumber element

Lets a user enter a telephone number.

Example JSON

{
  "id": "inputTelephoneNumber",
  "type": "Input.TelephoneNumber",
  "placeholder": "Input.TelephoneNumber",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
type string Required Must be "Input.TelephoneNumber".

The Input.Text element

Lets a user enter text.

Example JSON

{
  "id": "textEditor",
  "type": "Input.Text",
  "placeholder": "Input.Text",
  "spacing": "medium",
  "editor": true,
  "value": "editor: true"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
isMultiline boolean Optional If true, allow multiple lines of input.
maxLength number Optional Hint of maximum length characters to collect (may be ignored by some clients).
placeholder string Optional Description of the input desired. Displayed when no text has been input.
style Optional
type string Required Must be "Input.Text".
value string Optional The initial value for this field.
editor boolean Optional Whether the field should be a WYSIWYG (“what you see is what you get”) editor, if false then plain text field.

The Input.Time element

Lets a user select a time.

Example JSON

{
  "id": "time",
  "type": "Input.Time",
  "placeholder": "Input.Time",
  "spacing": "medium"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
max string Optional Hint of maximum value (may be ignored by some clients).
min string Optional Hint of minimum value (may be ignored by some clients).
placeholder string Optional Description of the input desired. Displayed when no time has been selected.
type string Required Must be "Input.Time".
value string Optional The initial value for this field expressed in ISO-8601 format.

The Input.Toggle element

Lets a user choose between two options.

Example JSON

{
  "id": "toggle",
  "type": "Input.Toggle",
  "spacing": "medium",
  "title": "Input.Toggle"
}

Properties

Name Type Required Description
id string Required Unique identifier for the value. Used to identify collected input when the Submit action is performed.
title string Required Title for the toggle
type string Required Input.Toggle
value string Optional The current selected value. If the item is selected that "valueOn" will be used, otherwise "valueOff"
valueOff string Optional The value when toggle is off
valueOn string Optional The value when toggle is on

The Jumbotron element

An element typically placed at the top of a card to describe its purpose.

Example JSON

{
  "type": "Jumbotron",
  "backgroundImage": "wmfs/pizza.jpg",
  "title": "Title",
  "subtitle": "Subtitle",
  "wash": "black"
}

Properties

Name Type Required Description
type string Required Must be "Jumbotron".
title string Required Text to be displayed as heading.
subtitle string Optional Text to be displayed as subheading.
wash string Optional Type of wash to have over the background.
backgroundImage string Optional Relative URL to image to be displayed as background.

The Map element

Displays a map.

Example JSON

{
  "type": "Map"
}

Properties

Name Type Required Description
type string Required Must be "Map".

The Media element

Displays a media player for audio or video content.

Example JSON

{
  "type": "Media",
  "poster": "https://adaptivecards.io/content/poster-video.png",
  "sources": [
    {
      "mimeType": "video/mp4",
      "url": "https://adaptivecardsblob.blob.core.windows.net/assets/AdaptiveCardsOverviewVideo.mp4"
    }
  ]
}

Properties

Name Type Required Description
type string Required Must be "Media".
sources array Optional Array of media sources to attempt to play.
poster string Optional URL of an image to display before playing.
altText string Optional Alternate text describing the audio or video.

The MediaSource element

Defines a source for a Media element

Example JSON

{
  "mimeType": "video/mp4",
  "url": "https://adaptivecardsblob.blob.core.windows.net/assets/AdaptiveCardsOverviewVideo.mp4"
}

Properties

Name Type Required Description
mimeType string Required Mime type of associated media (e.g. "video/mp4").
url string Required URL to media.

The PhaseBanner element

Displays a banner highlighting a phase.

Example JSON

{
  "type": "PhaseBanner",
  "phase": "alpha"
}

Properties

Name Type Required Description
type string Required Must be "PhaseBanner".
phase string Optional The phase which the service is in.

The Separator element

Displays a horizontal line.

Example JSON

{
  "type": "Separator"
}

Properties

Name Type Required Description
type string Required Must be "Separator".

The Tab element

Defines a container that is part of a TabSet.

Example JSON

{
  "type": "Tab",
  "title": "Tab 1",
  "items": [
    {
      "type": "TextBlock",
      "text": "Tab 1 Content"
    }
  ]
}

Properties

Name Type Required Description
type string Optional Must be "Tab".
items Required The card elements to include in the Tab.
title string Required The title of the Tab.

The TabSet element

TabSet allows to display content through various tabs.

Example JSON

{
  "type": "TabSet",
  "spacing": "large",
  "tabs": [
    {
      "type": "Tab",
      "title": "Tab 1",
      "items": [
        {
          "type": "TextBlock",
          "text": "Tab 1 Content"
        }
      ]
    },
    {
      "type": "Tab",
      "title": "Tab 2",
      "items": [
        {
          "type": "TextBlock",
          "text": "Tab 2 Content"
        }
      ]
    }
  ]
}

Properties

Name Type Required Description
type string Required Must be "TabSet".
tabs array Optional The array of Tabs to divide content.

The Table element

Displays text, allowing control over font sizes, weight, and color.

Example JSON

{
  "type": "Table",
  "title": "Opinions (Add some via CardList example above to see them appear in Table here)",
  "arrayPath": "cardList",
  "columns": [
    {
      "title": "Opinion",
      "field": "opinion"
    }
  ],
  "resultLimit": 5
}

Properties

Name Type Required Description
type string Required Must be "Table".
title string Optional Title displayed for the Table.
arrayPath string Required Points to the array of data to be displayed.
columns array Required
resultLimit integer Optional Limit the results per page.

The TextBlock element

Displays text, allowing control over font sizes, weight, and color.

Example JSON

{
  "type": "TextBlock",
  "text": "color: good",
  "color": "good"
}

Properties

Name Type Required Description
color string Optional Controls the color of TextBlock elements.
horizontalAlignment Optional
isSubtle boolean Optional If true, displays text slightly toned down to appear less prominent.
maxLines number Optional Specifies the maximum number of lines to display.
size string Optional Controls size of text.
text string Required Text to display.
type string Required Must be "TextBlock".
weight string Optional Controls the weight of TextBlock elements.
wrap boolean Optional If true, allow text to wrap. Otherwise, text is clipped.

License (MIT)

The Cardscript specification and related tooling is provided under MIT.


Appendices

Appendix A: Cardscript Motivation

Cardscript is the product of a small in-house development team at West Midlands Fire Service. Our work over the last 20 years has often involved collecting data from a variety of teams and environments. During this time, our best experiences have come from taking a declarative approach to defining form content.

  • Originally we used XML to define the content of our forms (or workbooks as they became known). From there it was a relatively simple process to write a renderer to conjure appropriate UIs from those definitions. Over the intervening years we have defined some 50 workbooks in XML to collect over 3 million documents and we've extended our DSL to support growing business need.

  • We're now actively working on our third-generation view rendering engine. While designing the accompanying backend, we've found great benefit in aligning to open standards (for example our workflow is now defined in Amazon State Language).

  • Given our positive experiences of declarative techniques and open standards, it was a natural evolution for our new declarative-UI engine to incorporate an open standard. We therefore prototyped using a few projects (for example Schema Form) and shipped our MVP using Mozilla React Schema Form.

They're great libraries and helped us get up-and-running quickly.

In hindsight, both these specifications are restricted by being bound to an underlying UI technology (i.e. Angular and React respectively). Both projects mandate a traditional web-form interface too. What if we're only working in a CLI context, or want to try some voice-interface technology? And what if we wanted to define dashboards and similar read-only content?

  • React Schema Form and Schema.io work well for reasonably trivial UI content, but start adding requirements for expression-based conditionality/validation, different layout structures, differing online/offline behaviours etc. and we were soon "working against" both approaches - even to deliver quite basic experiences.

To compound matters, the underlying use of JSON Schema involves a lot of duplication and arbitrary splitting between model and UI definitions: which soon builds friction when describing larger UIs. In turn, we found this complexity bleeds into tooling and the wider architecture.

So with a shopping-list in-hand:

  1. Must be an open standard and encourage contributions
  2. Must be easily extended to include new capabilities
  3. Must not be tied to any particular frontend technology or project
  4. Must not be tied to a particular UI pattern
  5. Must use a standard expression language (strong preference towards Javascript)
  6. Must support complex validation expressions
  7. Must support dynamic show/hide expressions (with optimisation for large chunks of the view)
  8. Must support online/offline behaviours
  9. Must have a schema to validate declarations and support tooling
  10. Must have an open SDK or similar to assist implementation
  11. Must be well documented
  12. Must have minimum of friction for embedding in a variety of app styles
  13. Strong preference towards JSON-based languages

...we went looking for an open standard capable of replacing our existing library of XML-defined views (some of which are pretty hefty in terms of number of components and logic).

Spoiler: We couldn't find one. Which was disappointing (and unexpected), because the experience of adopting Amazon State Language had been great. We were edging closer to defining our own, but at the same time very mindful of this sort of thing:

How standards proliferate Licensed under CC BY-NC 2.5 by xkcd.com

  • A particularity bad smell came about when we developed a simple intermediary format (to ease tooling complexity and authoring processes) which we could translate back into React Schema Form definitions. It was becoming evident we didn't have a good fit for what we wanted to do, and that using a badly-fitting standard is actually worse than not using a standard at all.

  • The XML used in our outgoing generation had some problems: requiring it's own expression-language was a particular mis-step and XML feels ancient if used directly on the client app (especially in Single Page Applications and Progressive Web Apps contexts).

So... Cardscript!

  • It does all the things we need, and we think it might be useful to other organisations if it became a standard.

Appendix B: Cardscript Utilities

Here are some Node.js-based utilities to help working with Cardscript:

Package Description Github NPM
cardscript-doc-generator Produces Cardscript's main README.md file using Cardscript's JSON Schema and other sources. Here Here
cardscript-examples Example Cardscript JSON files, to help with testing and documentation. Includes loader utility. Here Here
cardscript-cleaner Cleans Cardscript form data to ensure we only submit the data that we should. Here Here
cardscript-extract-defaults Extracts sensible defaults from some Cardscript. Here Here
cardscript-extract-lists Extracts list objects from some Cardscript. Here Here
cardscript-parser Like JSON.parse(), but for Cardscript. And it supports YAML. Here Here
cardscript-quasar-playpen Cardscript Playpen Here Here
cardscript-schema Contains a JSON Schema for Cardscript, along with a validation utility. Here Here
cardscript-table-of-contents Extracts a table-of-contents from some Cardscript. Here Here
cardscript-to-quasar Produces a template for use with Quasar from some Cardscript. Here Here
cardscript-to-vuelidate Takes in a Cardscript JSON object and attempts to extract validation schema from the widgets. Here Here
cardscript-vue-sdk An SDK for using Cardscript with Vue/Vuetify Here Here
@wmfs/json-schema-to-cardscript Scaffold Cardscript from a JSON-Schema schema Here Here
react-jsonschema-form-to-cardscript Produces Cardscript converted from react-jsonschema-form file. Here Here
@wmfs/tymly-cardscript-sdk Tymly Cardscript SDK Here Here
tymly-cardscript-sdk-doc-generator Produces a README.md file for the tymly-cardscript-sdk package. Here Here
Clone this wiki locally