Bugcrowd design system: Forms

When building forms:

  • Provide a heading and/or <legend> (even if visually-hidden)
  • Label all form fields (even if visually-hidden)
  • Avoid asking users for unnecessary data:
    • Do not visually demarcate required fields (eg no asterisk) — by default all fields are required;
    • Optional fields should be limited and marked by appending “(optional)” to the <label>
  • Maintain alignment of reading flow/process logic between:
    1. Source/markup order
    2. Visual display order (the sequential logic of the graphical layout)
    3. Tab/keyboard focus order
  • As necessary, provide hints or special instructions as descriptive text
  • Provide meaningful, programmatically-associated error messages.

When building larger forms — eg a stepped configuration — consider adding:

  • A summary of the details required later in the process
  • A navigation to move back or even jump steps
  • The ability to save progress and return later.

Form

Guidance last updated: Jan 9, 2019

Container class for <form> and wrapper classes for grouping form elements.

Use on the <form> tag, or in proximity if not possible. Possible also to be chained with Fieldsets if wrapping them is not feasible.

This wrapper class primarily sets vertical interspacing between child form elements.

  • Use the .bc-form__group class to group labels, descriptive text and their form fields.
  • Use .bc-form__footer for final form actions (eg save, submit).

This wrapper class is compatible with the BS3 grid system.

Rendered example of Form

Only your display name is visible to researchers.

Haml markup example of Form

.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-hunter2'}
      Display name
    %span.bc-hint{id: 'textin-hunter2-hint'}
      Only your display name is visible to researchers.
    %input.bc-text-input.bc-text-input--block{name: 'textin-hint-inside', id: 'textin-hunter2', type: 'text', value: 'hunter2', 'aria-describedby': 'textin-hunter2-hint' }

  .row
    .bc-form__group.col-lg-6
      %label.bc-label{for: 'textin'}
        Account email address
      %input.bc-text-input.bc-text-input--block{name: 'textin', id: 'textin', type: 'email', placeholder: '[email protected]'}

    .bc-form__group.col-lg-6
      %label.bc-label{for: 'textin-password'}
        Password
      %input.bc-text-input.bc-text-input--block{name: 'textin-password', id: 'textin-password', type: 'password', value: 'super secret password'}

  .bc-form__group
    %label.bc-label{for: 'textin-url'}
      Enter a URL
    %input.bc-text-input.bc-text-input--block{name: 'textin-url', id: 'textin-url', type: 'url', value: '', placeholder: 'http://example.com'}

Fieldsets

Guidance last updated: Jan 9, 2019

Wrappers for related form elements.

Theme support: This feature doesn’t yet have color theme support.

Default styling: The default fieldset style has no visual container styles. It also sets the <legend> as visually hidden (while accessible to assistive technologies, eg screen readers).

Fieldset use cases

Use a <fieldset> to group and give context to related form elements, including:

  • Radio buttons
  • Checkboxes
  • Related input fields (eg username and password).

Using <legend>

Each fieldset must have a <legend>. The legend should give a brief and clear context for the grouped form elements. The legend must be the immediate first child of the <fieldset>.

For example, a boolean on/off radio button group should be wrapped by a fieldset and given a <legend> to describe what is being turned on/off, since the ‘On’ and ‘Off’ strings are the respective <label>s for the radio buttons.

Do not use the <legend> as a replacement for each input’s individual <label>.

Avoid nesting fieldsets.

Alternative: grouping form elements with ARIA

If a fieldset and legend are in no way viable ARIA markup can be used to achieve the same effect.

Rendered example of Fieldsets

The legend describes its fieldset’s form elements

Haml markup example of Fieldsets

%fieldset.bc-fieldset
  %legend.bc-fieldset__legend
    The legend describes its fieldset’s form elements

Variants

--visible variant

Rendered example of Fieldsets
The legend describes its fieldset’s form elements
Haml markup example of Fieldsets --visible
%fieldset.bc-fieldset.bc-fieldset--visible
  %legend.bc-fieldset__legend
    The legend describes its fieldset’s form elements

--unbordered variant

Rendered example of Fieldsets
The legend describes its fieldset’s form elements
Haml markup example of Fieldsets --unbordered
%fieldset.bc-fieldset.bc-fieldset--visible.bc-fieldset--unbordered
  %legend.bc-fieldset__legend
    The legend describes its fieldset’s form elements

Error handling

Guidance last updated: May 24, 2019

Error messages identify and describe the issue(s) associated with form fields.

Wrap error messages in .bc-form__error.

Use the --error Icon component variant for the error message.

Error message code examples

General error handling guidance

There are three approaches to presenting error messages:

  1. Static on-submit, with errors raised after a page load
  2. Dynamically, on-the-fly as a user completes each field, with errors raised immediately
  3. Dynamically, on-submit, with errors raised without a page load.
  • Do use the --error variant of the Page alert component for error messages
  • Use and toggle the boolean aria-invalid attribute when an error occurs
  • Do not use aria-errormessage as it is not well supported.

Static on-submit

Begin by providing the error variant Page alert. This should:

  1. Provide a heading with an id noting that an error has occured; give a count if there are numerous errors
  2. Label the summary region using aria-labelledby, referencing the summary’s heading via its id
  3. Set role="alert" on the summary region to relay to assitive technologies that important content has appeared
  4. Ensure users can move keyboard focus to the page alert by giving it tabindex="0"
  5. List the labels for the fields with errors and give a short summary of each error.

Implicit aria-live value for alert role: the alert role has an implicit aria-live value of assertive which immediately calls out the region, irrespective of what a user was doing or where they had focus. Therefore it should only be applied to the form’s page alert error summary.

The list of errors should be given in the order in which they occur in the form.

Each list item label must link to the offending form field via its id.

Each affected form field should provide a descriptive message to help users fill in the field correctly. To do this:

  1. Place the detailed error message directly beneath the offending form field
  2. Add an id to the error message
  3. Add the aria-describedby attribute to the offending form field and reference the id of its associated error message.

Adding error messages to Control inputs: When errors occur in a checkbox or radio button group it is recommended to link each option to the group’s error message by setting aria-describedby and linking the id of the error message. Do this for each <input> in the group; not just the single, currently selected option.

Dynamic validation of user input

On-the-fly validation as a user completes each field

Validation is done as a user moves focus away from a field they have just interacted with.

When an error occurs Javascript is used to inject an appropriate message immediately in direct proxmity to the offending field. To do this properly the browser needs to be informed that region of the page has new content, and that this content is related to a form field.

To add an on-the-fly error message to a form field:

  1. Place the error message directly beneath the offending form field
  2. Add aria-live="polite" to the error message
  3. Add an id to the error message
  4. Add the aria-describedby attribute to the offending form field and reference the id of its associated error message.

Avoid shouting at users: do not use aria-live="assertive" for dynamically-added inline error messages, irrespective of the following approaches.

For example, suppose a user entered an invalid email address:

<div className="bc-form__group">
  <label for="account-email">Account email address</label>
  <input
    id="account-email"
    type="email"
    aria-invalid="true"
    aria-describedby="account-email-error-msg"
  />
  <div
    className="bc-form__error"
    id="account-email-error-msg"
    aria-live="true"
  >
    <span className="bc-icon bc-icon--error">
      The account email must be a valid email address.
    </span>
    </div>
  </div>
</div>

Note: the Page alert React component implements aria-live via the liveRegion prop.

Dynamic validation on-submit

Validation is done dynamically, en masse on-submit.

Because the validation is performed on all form fields at once, both a summary and the individual error messages must be given.

This method simply mixes the Static on-submit and On-the-fly methods. Follow the instructions for each of these.

For example, suppose a user submitted two errors in a user registration form that asks for a username, an email address, a password, and agreement to terms of service.

<form className="bc-form">
  <h2>User registration</h2>

  // The summary:
  <PageAlert
    id="summary-error-msg"
    variant="error"
    role="alert"
    tabindex="0"
    aria-labelledby="summary-error-msg-heading"
  >
    <h3 id="summary-error-msg-heading">
      2 errors have occured
    </h3>
    <ol>
      <li>
        <a href="#account-email">Account email address</a> is invalid
      </li>
      <li>
        <a href="#terms-of-service-agreement">Terms of Service</a> was not agreed to
      </li>
    </ol>
  </PageAlert>

  // [Valid user name label and text field]

  // Invalid user email field:
  <div className="bc-form__group">
    <label for="account-email">Account email address</label>
    <input
      id="account-email"
      type="email"
      aria-invalid="true"
      aria-describedby="account-email-error-msg"
    />
    <div
      className="bc-form__error"
      id="account-email-error-msg"
      aria-live="true"
    >
      <span className="bc-icon bc-icon--error">
        Your account email must be a valid email address.
      </span>
    </div>
  </div>

  // [Valid user password label and text field]

  // Invalid ToS checkbox:
  <div className="bc-form__group">
    <label for="account-email">
      <input
        id="terms-of-service-agreement"
        type="checkbox"
        aria-invalid="true"
        aria-describedby="tos-error-msg"
      />
      <span>I agree to the Terms of Service</span>
    </label>
    <div
      className="bc-form__error"
      id="tos-error-msg"
      aria-live="true"
    >
      <span className="bc-icon bc-icon--error">
        You must agree to the Terms of Service to register.
      </span>
    </div>
  </div>
</form>

Labels

Guidance last updated: Jan 9, 2019

Labels name and identify form fields.

All form fields must be labelled.

Label text should:

  • Be short and clear
  • Make sense within the context of its wrapping form or <fieldset>.

Placeholder text caution: A field’s default value or placeholder is not a substitute for a label.

Note: display: block is applied.

Note: Some form elements below have different <label> classes (eg Control inputs).

Building labels

There are three different ways to programmatically associate a label to a form field:

  1. <label>
  2. aria-label
  3. aria-labelledby

Standard [visual] labels

When possible, use <label>.

The <label> tag is associated with a given form field via its for attribute. This value is the id of the associated form field. When a <label> has a valid for attribute users can click on the label and bring focus to its form field.

<label> can wrap an <input>. This creates an implicit label; whilst using for/id creates an explicit label. With the exception of Control inputs, our convention is to keep <label> and <input> separate, label first.

If <label> is not viable in the markup, use aria-labelledby:

  1. Set an id on your faux label
  2. Set that id as the value for aria-labelledby, on the associated form field.

This establishes a relationship from the interactive element to the faux label.

Visually-hidden labels

Sometimes in a design form fields may be intuitive by themsleves and can forego a visual label (eg paired username & password fields). Such fields must still be given human-understandable labels.

To add a visually-hidden label to a form field use the aria-label attribute. Simply give it the human-understandable string as the value.

Labels and helper text

A well-labelled form field may benefit from additional instructions or helper text.

Avoid nesting this additional text within the label.

Use the Hint component to style additional descriptive text.

Use aria-describedby to reference additional descriptive text, eg:

  1. To markup an overall summary of the <form>
  2. To associate the sizing information chart with a form field asking a user’s t-shirt size.

This attribute works via an id identically to how aria-labelledby functions, as described above.

Note this attribute can take multiple values. Use this to associate additional error messages by appending them after any associated descriptive text for form field.

Rendered example of Labels

Select a technical severity The Vulnerability Rating Taxonomy is the baseline guide used for classifying technical severity. The severity rating suggested by the VRT is not guaranteed to be the severity rating applied to your submission.

Haml markup example of Labels

.bc-form
  .bc-form__group
    %label.bc-label{for: 'select-color2'}
      Select a color
    .bc-dropdown
      %select{id: 'select-color2', class: 'bc-dropdown__select'}
        %option{value: ''}
          Please select
        %option{value: '1'}
          MintCream
        %option{value: '2'}
          NavajoWhite
        %option{value: '3'}
          Whitesmoke
  .bc-form__group
    %span.bc-label{id: 'aria-label-eg'}
      Select a technical severity
    %span{id: 'aria-desc-eg'}
      %span.bc-hint
        The
        %a{href: 'https://bugcrowd.com/vulnerability-rating-taxonomy'}
          Vulnerability Rating Taxonomy
        is the baseline guide used for classifying technical severity.
      %span.bc-hint
        %span.bc-icon.bc-icon--info
          The severity rating suggested by the VRT is not guaranteed to be the severity rating applied to your submission.
    .bc-dropdown
      %button.bc-dropdown__select{type: 'button', 'aria-labelledby': 'aria-label-eg', 'aria-describedby': 'aria-desc-eg', 'aria-haspopup': 'true', 'aria-owns':'vrt-nonexistant-combobox', 'aria-controls': 'vrt-nonexistant-combobox', 'aria-expanded': 'false'}
        %span.bc-badge.bc-badge--p1.bc-badge--unconfirmed{'aria-live':'polite', role: 'region'}
          P1
        %span.bc-badge-label
          Sensitive Data Exposure > Critically Sensitive Data > Private API Keys

Buttons

Guidance last updated: Jun 26, 2019

Buttons for all occasions.

Button–link terminology

Anchors and buttons often share similar styles, despite their different functions.

  • ‘Anchors’ or ‘links’ refer to the <a> element
  • ‘Buttons’ refer to the <button> element.

Button styles

Default buttons are blue while secondary buttons are gray.

Other button styles are available and currently named by their aesthetic or their function.

The --cancel and --text variants are identical in style.

Button text should be set in sentence case — only the first word and proper nouns should be capitalized. Avoid uppercased button text due to the reduced legibility of fully-capitalized text strings (word shapes become uniform when capitalized).

Marked for refactor: We intend to refactor and simplify our button styles.

Theme support: This feature doesn’t yet have color theme support.

Using buttons

Use <button> for actions that:

  • Save state (write, delete)
  • Do something (eg copy to the clipboard)
  • Spawns a new entity/object on the page (eg a modal).

Avoid:

  • Re-implementing your own button on a <div> for a custom component when a custom-styled <button> does the job.
  • Custom tabindexes (unless absolutely necessary or intentional within a given context).

Implicit functions of <button>s

  • Receive keyboard focus by default
  • “Click” with the Space key
  • Submit form data to a server
  • Reset a form
  • Be disabled with the disabled attribute
  • Instruct a screen reader with the implicit button role
  • Show :focus, :hover, :active, :disabled.

Using anchors

You can use anchors styled as buttons for ‘actions’ that:

  • Cancel a process and don’t change state
  • Link to a resource with a user-defined or generated URL parameter.

Avoid:

  • Styling anchors that link to a resource
  • Custom tabindexes (unless absolutely necessary or intentional within a given context).
  • Not setting a href — an anchor without a href is removed from the tab order and not otherwise accessible to assistive technologies.

Implicit functions of anchors (<a>)

  • Create hypertext, a network of online resources
  • Navigate the user to a new page or view
  • Change the URL
  • Cause a browser redraw/refresh
  • Support page jumps with internal href attributes
  • Deep-link client-rendered applications
  • Are focusable by default with the href attribute
  • Register a click with the Enter key
  • Have the implicit link role
  • Can’t be disabled like buttons but can be made inert with tabindex="-1" and aria-hidden="true"
  • Allow opening in new windows
  • Show :link, :visited, :focus, :hover, & :active.

Adding icons to buttons

Icons can be added to our buttons in two ways:

  1. By using a mixin, and providing the SVG as a background-image
  2. By using a class (that implements the mixin’s defaults) and providing the SVG as a background-image.

For more information see the SassDoc bc-btn--icon() mixin documentation.


Entry info adapted from Marcy Sutton’s Links vs. Buttons in Modern Web Applications.

Rendered example of Buttons

Haml markup example of Buttons

%button.bc-btn Primary

%button.bc-btn(disabled) Disabled

Variants

--secondary variant

Rendered example of Buttons
Haml markup example of Buttons --secondary
%button.bc-btn.bc-btn--secondary Secondary

%button.bc-btn.bc-btn--secondary(disabled) Disabled

--brand variant

Rendered example of Buttons
Haml markup example of Buttons --brand
%button.bc-btn.bc-btn--brand Brand

%button.bc-btn.bc-btn--brand(disabled) Disabled

--caution variant

Rendered example of Buttons
Haml markup example of Buttons --caution
%button.bc-btn.bc-btn--caution Caution

%button.bc-btn.bc-btn--caution(disabled) Disabled

--cancel variant

Rendered example of Buttons
Haml markup example of Buttons --cancel
%button.bc-btn.bc-btn--cancel Cancel

%button.bc-btn.bc-btn--cancel(disabled) Disabled

--text variant

Rendered example of Buttons
Haml markup example of Buttons --text
%button.bc-btn.bc-btn--text Text

%button.bc-btn.bc-btn--caution.bc-btn--text Delete action

%button.bc-btn.bc-btn--text(disabled) Disabled

--link variant

--transparent variant

Rendered example of Buttons
Haml markup example of Buttons --transparent
%button.bc-btn.bc-btn--transparent Transparent

%button.bc-btn.bc-btn--transparent(disabled) Disabled

--thin variant

Rendered example of Buttons
Haml markup example of Buttons --thin
%button.bc-btn.bc-btn--thin Thin

--small variant

Rendered example of Buttons
Haml markup example of Buttons --small
%button.bc-btn.bc-btn--small Small

--large variant

Rendered example of Buttons
Haml markup example of Buttons --large
%button.bc-btn.bc-btn--large Large

--icon variant

Rendered example of Buttons

Button icons with text


Button icons with visibly hidden text

Haml markup example of Buttons --icon
%button.bc-btn.bc-btn--secondary.bc-btn--icon
  %span Icon button

%button.bc-btn.bc-btn--secondary.bc-btn--icon(disabled)
  %span Disabled icon button

%button.bc-btn.bc-btn--icon.bc-btn--icon--hidden-text{'aria-label': 'Visually-hidden text button'}
  %span Visually-hiden text icon button

%hr

%p Button icons with text

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--download{'aria-label': 'Download this thing'}
  %span Download

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--attach{'aria-label': 'Upload and attach files'}
  %span Attach file(s)

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--edit{'aria-label': 'Edit this thing'}
  %span Edit

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--edit(disabled){'aria-label': 'Edit this thing'}
  %span Edit

%hr

%p Button icons with visibly hidden text

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--brief{'aria-label': 'View program brief'}
  %span View program brief

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--edit{'aria-label': 'Edit this thing'}
  %span Edit

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--delete{'aria-label': 'Delete this thing'}
  %span Delete

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--follow{'aria-label': 'Follow this program'}
  %span Follow

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--follow.bc-btn--follow--active{'aria-label': 'Unfollow this program'}
  %span Unfollow

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--follow(disabled){'aria-label': 'Follow this program'}
  %span Follow

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--visible{'aria-label': 'Make visible'}
  %span Make visible

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--invisible{'aria-label': 'Make invisible'}
  %span Make invisible

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--more{'aria-label': 'Show more options'}
  %span Show more options

%button.bc-btn.bc-btn--secondary.bc-btn--icon--hidden-text.bc-btn--cross{'aria-label': 'Close this dialogue'}
  %span Close dialogue

--block variant

Rendered example of Buttons
Haml markup example of Buttons --block
%button.bc-btn.bc-btn--block Continue
%button.bc-btn.bc-btn--block.bc-btn--secondary Save
%button.bc-btn.bc-btn--block.bc-btn--cancel Cancel
%button.bc-btn.bc-btn--block.bc-btn--caution Delete

File input

Guidance last updated: May 10, 2019

A simple file upload form input element.

Theme support: This feature doesn’t yet have color theme support. It will receive it when Buttons’ color setup is refactored.

No file listing: This DS feature doesn’t yet have show a list of the selected file(s) — it only provides replacement button styling for the <input type='file'> element.

File input markup

The UI of the file input element is difficult to style, due to limited CSS selectors.

To achieve consistency between various native OS implementations of this UI component we visually hide the <input>. Instead a sibling <span> is styled as a button, and everything is wrapped in the <label> so it is natively clickable.

File input button

If possible inform users if the file input feature is configured for either single or multiple file uploads. This can be done via:

  • Button text, eg Attach a file and Attach file(s)
  • Accompanying hint text.

The button styles are provided automatically by the .bc-file-input__label-text class.

IE11 icon known issue: the icon does not align properly when used on a --block button.

Rendered example of File input

Haml markup example of File input

%label.bc-file-input
  %input.bc-file-input__input{name: 'file-input-eg', type: 'file'}
  %span.bc-file-input__label-text
    Upload a single file

Variants

--disabled variant

Rendered example of File input
Haml markup example of File input --disabled
%label.bc-file-input
  %input.bc-file-input__input(disabled){name: 'file-input-eg--disabled', type: 'file', multiple: 'true'}
  %span.bc-file-input__label-text
    Add attachments

--block variant

Rendered example of File input
Haml markup example of File input --block
%label.bc-file-input.bc-file-input--block
  %input.bc-file-input__input{name: 'file-input-eg', type: 'file'}
  %span.bc-file-input__label-text
    Upload a single file
Guidance last updated: Jan 9, 2019

Select inputs, aka ‘dropdowns’.

Use <select> dropdowns to give users the ability to make a single selection from a group of options.

Unlike radio buttons select dropdowns can allow users to revert a selection by selecting the first (zero value) option, if an initial zero-value option is provided.

Using dropdowns

  • Keep the number of options low and ensure they are clear and concise
  • Avoid long options. Preventing overflow is difficult — be mindful of this, especially at small viewports.
  • Avoid any ambiguity between any of the options. Related options can be grouped via an <optgroup>.

Javascript-powered dropdowns

If you customize your own dropdown, eg if the <select> element is insufficient or incapable in meeting design needs, ensure the element is accessible by making use of ARIA attributes.

Rendered example of Dropdowns

Haml markup example of Dropdowns

.bc-form
  .bc-form__group
    %label.bc-label{for: 'select-color'}
      Select a color
    .bc-dropdown
      %select{id: 'select-color', class: 'bc-dropdown__select'}
        %option{value: ''}
          Please select
        %option{value: '1'}
          RebeccaPurple
        %option{value: '2'}
          FloralWhite
        %option{value: '3'}
          FireBrick

Variants

--block variant

Rendered example of Dropdowns
Haml markup example of Dropdowns --block
.bc-form
  .bc-form__group
    %label.bc-label{for: 'select-cute-animal'}
      Which of these cute animals is your favorite
    .bc-dropdown.bc-dropdown--block
      %select{id: 'select-cute-animal', class: 'bc-dropdown__select'}
        %option{value: ''}
          Please select
        %option{value: '1'}
          Capybara
        %option{value: '2'}
          Pangolin
        %option{value: '3'}
          Quokka

--disabled variant

Rendered example of Dropdowns
Haml markup example of Dropdowns --disabled
.bc-form
  .bc-form__group
    %label.bc-label{for: 'select-disabled-eg'}
      Choose a president:
    .bc-dropdown
      %select(disabled){id: 'select-disabled-eg', class: 'bc-dropdown__select'}
        %option{value: '1'}
          Mango Mussolini
        %option{value: '2'}
          Investment banker advocate

Control input

Guidance last updated: May 24, 2019

Checkboxes and radio buttons for all occasions.

  • Use checkboxes to allow users to select multiple options
  • Use radio buttons to allow users to select a single option from a group.

Usage of radio buttons

Grouped radio buttons need to share the same name value.

Generally, use radio buttons over <select> dropdowns. If it’s important to retain the option of an unselected state consider using a select dropdown since it is difficult for users to revert all radio buttons in a group to their unselected state.

For this reason — when using radio buttons — consider marking the most popular option in a button group as already ‘pre-selected’ (viz., checked).

Wrapping checkboxes and radio buttons

Wrap both checkboxes or radio buttons:

  1. In a <fieldset> to associate them, and provide a brief but clear <legend>
  2. Wrap the <label> around the <input> — this ensures a user can select an option by clicking on the <input>, the <label> text, or the whitespace between them.

Exceptions: Single checkboxes or a duo of radio buttons only if the options [labels] provide enough context by themselves. For example, a single checkbox to confirm reading and agreeing to a Submission non-disclosure agreement.

‘Unlabelled’ control input variant

This variant visually hides the associated label text, with the expectation that:

  1. Visual proximity to associated data (eg a table row) signifies what the selection is
  2. A replacement label is provided instead through aria-label, onto the <input>.

For technical reasons we still require a nested <span> with the .bc-control-input__label-text class inside the <input>. Note that this span needs to entirely empty.

The <label> continues to wrap the <input> in this variant.

Further reading

Rendered example of Control input

Select all devices you own:
Which one out of the following would you like?

Haml markup example of Control input

.bc-form
  %fieldset.bc-fieldset.bc-fieldset--visible
    %legend.bc-fieldset__legend Select all devices you own:

    %label.bc-control-input
      %input.bc-control-input__input{name: 'checkbox-tamagotchi', type: 'checkbox'}
      %span.bc-control-input__label-text
        Tamagotchi
        %span.bc-control-input__hint
          A handheld digital pet, created in Japan by Akihiro Yokoi

    %label.bc-control-input
      %input.bc-control-input__input(checked disabled){name: 'checkbox-phone', type: 'checkbox'}
      %span.bc-control-input__label-text
        Phone

    %label.bc-control-input
      %input.bc-control-input__input(disabled){name: 'checkbox-zune', type: 'checkbox'}
      %span.bc-control-input__label-text
        Zune

    %label.bc-control-input
      %input.bc-control-input__input{name: 'checkbox-tablet', type: 'checkbox'}
      %span.bc-control-input__label-text
        Tablet

    %label.bc-control-input
      %input.bc-control-input__input(checked){name: 'checkbox-laptop', type: 'checkbox'}
      %span.bc-control-input__label-text
        Laptop

    %label.bc-control-input
      %input.bc-control-input__input{name: 'checkbox-desktop', type: 'checkbox'}
      %span.bc-control-input__label-text
        Desktop

.bc-form
  %fieldset.bc-fieldset.bc-fieldset--visible
    %legend.bc-fieldset__legend Which one out of the following would you like?

    %label.bc-control-input
      %input.bc-control-input__input(checked){name: 'radio-example', type: 'radio'}
      %span.bc-control-input__label-text
        Mango

    %label.bc-control-input
      %input.bc-control-input__input{name: 'radio-example', type: 'radio'}
      %span.bc-control-input__label-text
        Pineapple

    %label.bc-control-input
      %input.bc-control-input__input(disabled){name: 'radio-example', type: 'radio'}
      %span.bc-control-input__label-text
        Passionfruit
        %span.bc-control-input__hint
          (out of stock)

    %label.bc-control-input
      %input.bc-control-input__input{name: 'radio-example', type: 'radio'}
      %span.bc-control-input__label-text
        Grapefruit

Variants

--invalid variant

Rendered example of Control input
Error: You must agree to the Terms & Conditions and the Standard Disclosure Terms in order to create an account.
Haml markup example of Control input --invalid
.bc-form
  .bc-form__group
    %label.bc-control-input.bc-control-input--invalid
      %input.bc-control-input__input{name: 'checkbox-tos', type: 'checkbox'}
      %span.bc-control-input__label-text
        I agree to the
        %a{href: 'https://www.bugcrowd.com/terms-and-conditions/'}
          Terms &amp; Conditions
        and the
        %a{href: 'https://www.bugcrowd.com/standard-disclosure-terms/'}
          Standard Disclosure Terms
    .bc-form__error
      %span.bc-icon.bc-icon--error
        %strong Error:
        You must agree to the
        Terms &amp; Conditions and the
        Standard Disclosure Terms
        in order to create an account.

--unlabelled variant

Rendered example of Control input
Researcher Amount ($) Status
Andy 33,000 Completed
codesoda 31,000 Completed
caseyjohnellis 29,500 Completed
mongo 28,900 Completed
Haml markup example of Control input --unlabelled
.bc-table.bc-table--hover
  %table
    %thead
      %tr
        %th
          %label.bc-control-input.bc-control-input--unlabelled
            %input.bc-control-input__input(checked){name: 'select-all', id: 'select-all', type: 'checkbox', 'aria-label': 'Select/unselect all'}
              %span.bc-control-input__label-text
        %th Researcher
        %th.bc-table__th-right Amount ($)
        %th Status
    %tbody
      %tr
        %td{data: { label: 'Selected' }}
          %label.bc-control-input.bc-control-input--unlabelled
            %input.bc-control-input__input(checked){name: 'andy', id: 'andy', type: 'checkbox', 'aria-label': 'Andy'}
              %span.bc-control-input__label-text
        %td{data: { label: 'researcher' }}
          Andy
        %td.bc-table__th-right{data: { label: 'amount' }} 33,000
        %td{data: { label: 'status' }} Completed
      %tr
        %td.bc-table__th-abbr{data: { label: 'Selected' }}
          %label.bc-control-input.bc-control-input--unlabelled
            %input.bc-control-input__input(checked){name: 'codesoda', id: 'codesoda', type: 'checkbox', 'aria-label': 'codesoda'}
              %span.bc-control-input__label-text
        %td{data: { label: 'researcher' }} codesoda
        %td.bc-table__th-right{data: { label: 'amount' }} 31,000
        %td{data: { label: 'status' }} Completed
      %tr
        %td.bc-table__th-abbr{data: { label: 'Selected' }}
          %label.bc-control-input.bc-control-input--unlabelled
            %input.bc-control-input__input(checked){name: 'caseyjohnellis', id: 'caseyjohnellis', type: 'checkbox', 'aria-label': 'caseyjohnellis'}
              %span.bc-control-input__label-text
        %td{data: { label: 'researcher' }} caseyjohnellis
        %td.bc-table__th-right{data: { label: 'amount' }} 29,500
        %td{data: { label: 'status' }} Completed
      %tr
        %td.bc-table__th-abbr{data: { label: 'Selected' }}
          %label.bc-control-input.bc-control-input--unlabelled
            %input.bc-control-input__input(checked){name: 'mongo', id: 'mongo', type: 'checkbox', 'aria-label': 'mongo'}
              %span.bc-control-input__label-text
        %td{data: { label: 'researcher' }} mongo
        %td.bc-table__th-right{data: { label: 'amount' }} 28,900
        %td{data: { label: 'status' }} Completed

Switch input

Guidance last updated: Apr 4, 2019

Binary switch/toggle inputs (actually a checkbox).

Only use switch inputs for boolean options.

Switch input labels

Note that switch inputs are nested inside their associated <label>. This ensures that a user can select an option by clicking on the <input>, the nested label text, or the whitespace between them.

The ON/OFF text is hidden from assistive technology users (eg screen readers) via aria-hidden="true" since the state of the component is already communicated to the user via its checked state.

Grouping switch inputs

Organise a list of switch input options (or other options, eg checkboxes) into a Settings list.

Switch input React component

There is a SwitchInput React component. It takes the following properties:

Prop Type Default(s) Description
label node N/A A clear, human-readable string that labels the boolean choice available to the user (ie., the <label> content).
id string uuid4() An auto-generated ID (using uuidv4) or a developer-supplied string.
hideOnOff boolean false Whether or not to display the ON/OFF text inside the switch.

The label prop is required.

Rendered example of Switch input

Haml markup example of Switch input

.bc-switch-input
  %label.bc-switch-input__inline-label{for: 'switch-eg1'}
    %span.bc-label Allow others to view your profile
    .bc-switch-input__toggle
      %input.bc-switch-input__switch(checked){name: 'switch', type: 'checkbox', id: 'switch-eg1'}
      %span.bc-switch-input__switch-text
        %span.bc-switch-input__on{'aria-hidden': 'true'} On
        %span.bc-switch-input__off{'aria-hidden': 'true'} Off

%div{'data-react-class': 'SwitchInput', 'data-react-props': '{"label": "Allow others to view your profile", "hideOnOff": true}'}

Variants

--justify variant

Rendered example of Switch input
Haml markup example of Switch input --justify
.bc-switch-input.bc-switch-input--justify
  %label.bc-switch-input__inline-label{for: 'switch-block-eg1'}
    %span.bc-label Allow others to view your profile
    .bc-switch-input__toggle
      %input.bc-switch-input__switch(checked){name: 'switch', type: 'checkbox', id: 'switch-block-eg1'}
      %span.bc-switch-input__switch-text
        %span.bc-switch-input__on{'aria-hidden': 'true'} On
        %span.bc-switch-input__off{'aria-hidden': 'true'} Off

%div{'data-react-class': 'SwitchInput', 'data-react-props': '{"label": "Allow others to view your profile", "hideOnOff": true, "justify": true}'}

--disabled variant

Rendered example of Switch input
Haml markup example of Switch input --disabled
.bc-switch-input
  %label.bc-switch-input__inline-label{for: 'switch-disabled-eg1'}
    %span.bc-label Turn this setting
    .bc-switch-input__toggle
      %input.bc-switch-input__switch(checked disabled){name: 'switch', type: 'checkbox', id: 'switch-disabled-eg1'}
      %span.bc-switch-input__switch-text
        %span.bc-switch-input__on{'aria-hidden': 'true'} On
        %span.bc-switch-input__off{'aria-hidden': 'true'} Off

.bc-switch-input
  %label.bc-switch-input__inline-label{for: 'switch-disabled-eg2'}
    %span.bc-label Turn this setting
    .bc-switch-input__toggle
      %input.bc-switch-input__switch(disabled){name: 'switch', type: 'checkbox', id: 'switch-disabled-eg2'}
      %span.bc-switch-input__switch-text
        %span.bc-switch-input__on{'aria-hidden': 'true'} On
        %span.bc-switch-input__off{'aria-hidden': 'true'} Off

.bc-switch-input
  %label.bc-switch-input__inline-label{for: 'switch-disabled-eg3'}
    %span.bc-label Turn this setting
    .bc-switch-input__toggle
      %input.bc-switch-input__switch(checked disabled){name: 'switch', type: 'checkbox', id: 'switch-disabled-eg3'}
      %span.bc-switch-input__switch-text.bc-switch-input__switch-text--hidden
        %span.bc-switch-input__on{'aria-hidden': 'true'} On
        %span.bc-switch-input__off{'aria-hidden': 'true'} Off

%div{'data-react-class': 'SwitchInput', 'data-react-props': '{"label": "Turn this setting", "disabled": true}'}

Text input

Guidance last updated: Feb 20, 2019

Text inputs provide styles for many text-based <input> types.

For ideal styling, group a <label> and its <input> together within a parent .bc-form__group.

Use for these types:

  • text
  • number
  • tel
  • email
  • password
  • url
  • and the <textarea> element.

Using the correct input type

Use the correct <input> type if there is one, eg

  • password for password fields
  • tel for phone numbers

Use <textarea> for addresses when not using a Javascript library (eg Google Places autocomplete address form).

Input form validation

Usage of the correct type will allow for client-side form validation without requiring Javascript.

For example, when an invalid email address is entered as the value into an input with a type of email, the :invalid attribute is applied.

Client-side HTML5 form validation is not a replacement for server-side input sanitisation.

Unsupported input types

Input types in HTML5 have been expanded, but due to poor and inconsistent browser support avoid using:

  • time
  • date and datetime-local
  • week and month

When IE11 support is expanded or our browser support matrix is updated these may become viable.

Note that datetime is obsolete.

:valid and :invalid styling

Styles for valid/invalid inputs are currently not applied to inputs with the :valid/:invalid attributes. Instead, they are available as BEM class variants (--valid and --invalid).

‘readonly’ disabled usage

Apply the --readonly variant on:

  • Text input fields that could shortly become editable (eg via an edit mode button)
  • Block-level user-defined data points being referenced at later stages in a form

Do not use the –readonly variant inputs that a user can interact with.

‘Prefaced’ text input variant

Marked for refactor: The --prefaced variant violates our BEM conventions. It will be refactored in the future.

--prefaced is a wrapper class placed around the input and the span. This variant should be used for inputs that require a specific information type that when written is normally prefaced by a symbol, eg ‘$’ for monetary values or ‘@’ for Twitter handles.

Rendered example of Text input

Lost password?

Haml markup example of Text input

.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-hint-inside'}
      Display name
      %span.bc-hint
        Only your display name is visible to researchers.
    %input.bc-text-input{name: 'textin-hint-inside', id: 'textin-hint-inside', type: 'text', value: 'hunter2'}

  .bc-form__group
    %label.bc-label{for: 'textin'}
      Please enter your email address
    %input.bc-text-input{name: 'textin', id: 'textin', type: 'email', placeholder: '[email protected]'}

  .bc-form__group
    %label.bc-label{for: 'textin-password'}
      Please enter your password
    %input.bc-text-input{name: 'textin-password', id: 'textin-password', type: 'password', value: 'super secret password'}
    %a.bc-hint{href: '#'}
      Lost password?

  .bc-form__group
    %label.bc-label{for: 'textin-url'}
      Enter a URL
    %input.bc-text-input{name: 'textin-url', id: 'textin-url', type: 'url', value: '', placeholder: 'http://example.com'}

Variants

--invalid variant

Rendered example of Text input
Error: The address you entered is not a valid email address.
Haml markup example of Text input --invalid
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-invalid'}
      Enter a valid email address
    %input.bc-text-input.bc-text-input--invalid.bc-text-input--block{name: 'textin-invalid', id: 'textin-invalid', type: 'email', value: '[email protected]', 'aria-invaid': 'true', 'aria-describedby': 'textin-invalid-error-msg'}
    .bc-form__error{id: 'textin-invalid-error-msg', 'aria-live': 'polite'}
      %span.bc-icon.bc-icon--error
        %strong Error:
        The address you entered is not a valid email address.

--valid variant

Rendered example of Text input
Haml markup example of Text input --valid
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-valid'}
      Label for a valid text input field
    %input.bc-text-input.bc-text-input--valid{name: 'textin-valid', id: 'textin-valid', type: 'text', value: 'Value passed validation'}

--disabled variant

Rendered example of Text input
Haml markup example of Text input --disabled
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-disabled'}
      Label for a disabled text input field
    %input.bc-text-input(disabled){name: 'textin-disabled', id: 'textin-disabled', type: 'text', value: 'ABCZ abcjg liI1 12340'}

--readonly variant

Rendered example of Text input
Haml markup example of Text input --readonly
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-disabled'}
      Label for a readonly-style disabled text input field
    %input.bc-text-input.bc-text-input--readonly(disabled){name: 'textin-disabled-ro', id: 'textin-disabled-ro', type: 'text', value: 'Disabled, read-only variant text input field'}

--number variant

Rendered example of Text input
Haml markup example of Text input --number
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-number'}
      Enter a number
    %input.bc-text-input.bc-text-input--number{name: 'textin-number', id: 'textin-number', type: 'number', value: '0123456789'}

  .bc-form__group
    %label.bc-label{for: 'textin-number-tel'}
      Enter a telephone number
    %input.bc-text-input.bc-text-input--number{name: 'textin-number-tel', id: 'textin-number-tel', type: 'tel', value: '+61 420 123 456'}

--textarea variant

Rendered example of Text input
Haml markup example of Text input --textarea
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-textarea'}
      Enter a shipping address
    %textarea.bc-text-input.bc-text-input--textarea{name: 'textin--textarea', id: 'textin-textarea'}

--block variant

Rendered example of Text input
Haml markup example of Text input --block
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-block'}
      Label for a block text input field
    %input.bc-text-input.bc-text-input--block{name: 'textin-block', id: 'textin-block', type: 'text', value: 'ABCZ abcjg 12340'}

--prefaced variant

Rendered example of Text input
$
@
Haml markup example of Text input --prefaced
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-prefaced-dollars'}
      How many US dollars would you like?
    .bc-text-input--prefaced
      %span.bc-text-input__preface-text
        $
      %input.bc-text-input{name: 'textin-prefaced-dollars', id: 'textin-prefaced-dollars', type: 'number', value: '9000'}

  .bc-form__group
    %label.bc-label{for: 'textin-prefaced-twitter'}
      Twitter handle
    .bc-text-input--prefaced
      %span.bc-text-input__preface-text
        @
      %input.bc-text-input{name: 'textin-prefaced-twitter', id: 'textin-prefaced-twitter', type: 'text', value: 'bugcrowd'}

Setting list

Guidance last updated: Jan 9, 2019

A clean way of listing user options with support for switch toggles and control inputs.

Use to group related user options into a list.

You can apply a border to the list by appending the Panel container class on the <ul> (or <ol>). Therein, the list items receive horizontal padding.

Please curtail the max-width of the Setting list through the Grid system, to ensure the form labels are not too far from their corresponding form controls.

Setting list accessibility

The setting list places all controls inline.

For settings with a single checkbox the text on the left becomes that checkbox’s label.

However, grouped radio buttons and checkboxes require some additional ARIA tags since they are no longer grouped using <fieldset>s within the list.

Use aria-describedby to associate a group of checkboxes or radio buttons with the left-hand descriptor text for said group. For an example see the markup below.

Setting list dependencies

  • Containers
    • Panels (optional)
    • Grid (implied)
  • Components (as required)
    • Control input
    • Switch input

Rendered example of Setting list

Setting list
  • Someone writes a team note or a researcher replies
  • Receive sporadic ponies
Setting list, used alongside the Panel container:
  • Someone writes a team note or a researcher replies
  • Receive sporadic ponies

Haml markup example of Setting list

%span.bc-h5 Setting list

%ul.bc-setting-list
  %li.bc-setting-list__item
    .bc-switch-input
      %label.bc-switch-input__inline-label{for: 'setting-list-switch-block-eg1'}
        %span.bc-label
          Activity on
          %strong subscribed
          submissions
        .bc-switch-input__toggle
          %input.bc-switch-input__switch(checked){name: 'switch', type: 'checkbox', id: 'setting-list-switch-block-eg1'}
          %span.bc-switch-input__switch-text
            Turn this setting
            %span.bc-switch-input__on On
            %span.bc-switch-input__off Off
  %li.bc-setting-list__item
    .bc-switch-input
      %label.bc-switch-input__inline-label{for: 'setting-list-switch-block-eg2'}
        %span.bc-label
          Team members
          %strong @mention
          me
        .bc-switch-input__toggle
          %input.bc-switch-input__switch{name: 'switch', type: 'checkbox', id: 'setting-list-switch-block-eg2'}
          %span.bc-switch-input__switch-text
            Turn this setting
            %span.bc-switch-input__on On
            %span.bc-switch-input__off Off
  %li.bc-setting-list__item
    .bc-switch-input
      %label.bc-switch-input__inline-label{for: 'setting-list-switch-block-eg3'}
        %span.bc-label
          I’m
          %strong assigned
          to a submission
        .bc-switch-input__toggle
          %input.bc-switch-input__switch(checked){name: 'switch', type: 'checkbox', id: 'setting-list-switch-block-eg3'}
          %span.bc-switch-input__switch-text
            Turn this setting
            %span.bc-switch-input__on On
            %span.bc-switch-input__off Off
  %li.bc-setting-list__item
    %label.bc-setting-list__control-input-label{for: 'checkbox-spiders'}
      .bc-setting-list__item__text
        %span.bc-label
          Receive sporadic
          %strong spiders
      .bc-setting-list__item__controls
        %span.bc-control-input.bc-control-input--unlabelled
          %input.bc-control-input__input{name: 'checkbox-spiders', type: 'checkbox', id: 'checkbox-spiders', 'aria-label': 'checkbox-spiders'}
            %span.bc-control-input__label-text
  %li.bc-setting-list__item{role: 'group', 'aria-describedby': 'setting__team-or-researcher-notification-types'}
    .bc-setting-list__item__text{id: 'setting__team-or-researcher-notification-types'}
      %span.bc-label
        Someone writes a
        %strong team note
        or a researcher
        %strong replies
    .bc-setting-list__item__controls
      %label.bc-control-input
        %input.bc-control-input__input(checked){name: 'checkbox-web', type: 'checkbox', 'aria-describedby': 'setting__team-or-researcher-notification-types'}
        %span.bc-control-input__label-text
          Web
      %label.bc-control-input
        %input.bc-control-input__input{name: 'checkbox-email', type: 'checkbox', 'aria-describedby': 'setting__team-or-researcher-notification-types'}
        %span.bc-control-input__label-text
          Email
  %li.bc-setting-list__item{role: 'group', 'aria-describedby': 'setting__ponies'}
    .bc-setting-list__item__text{id: 'setting__ponies'}
      %span.bc-label
        Receive sporadic
        %strong ponies
    .bc-setting-list__item__controls
      %label.bc-control-input
        %input.bc-control-input__input{name: 'sporadic-ponies__off', type: 'radio', 'aria-describedby': 'setting__ponies'}
        %span.bc-control-input__label-text
          Off
      %label.bc-control-input
        %input.bc-control-input__input(checked){name: 'sporadic-ponies__on', type: 'radio', 'aria-describedby': 'setting__ponies'}
        %span.bc-control-input__label-text
          On


%span.bc-h5 Setting list, used alongside the Panel container:

%ul.bc-panel.bc-setting-list
  %li.bc-setting-list__item
    .bc-switch-input
      %label.bc-switch-input__inline-label{for: 'panelised-setting-list-switch-block-eg1'}
        %span.bc-label
          Activity on
          %strong subscribed
          submissions
        .bc-switch-input__toggle
          %input.bc-switch-input__switch(checked){name: 'switch', type: 'checkbox', id: 'panelised-setting-list-switch-block-eg1'}
          %span.bc-switch-input__switch-text
            Turn this setting
            %span.bc-switch-input__on On
            %span.bc-switch-input__off Off
  %li.bc-setting-list__item
    .bc-switch-input
      %label.bc-switch-input__inline-label{for: 'panelised-setting-list-switch-block-eg2'}
        %span.bc-label
          Team members
          %strong @mention
          me
        .bc-switch-input__toggle
          %input.bc-switch-input__switch{name: 'switch', type: 'checkbox', id: 'panelised-setting-list-switch-block-eg2'}
          %span.bc-switch-input__switch-text
            Turn this setting
            %span.bc-switch-input__on On
            %span.bc-switch-input__off Off
  %li.bc-setting-list__item
    .bc-switch-input
      %label.bc-switch-input__inline-label{for: 'panelised-setting-list-switch-block-eg3'}
        %span.bc-label
          I’m
          %strong assigned
          to a submission
        .bc-switch-input__toggle
          %input.bc-switch-input__switch(checked){name: 'switch', type: 'checkbox', id: 'panelised-setting-list-switch-block-eg3'}
          %span.bc-switch-input__switch-text
            Turn this setting
            %span.bc-switch-input__on On
            %span.bc-switch-input__off Off
  %li.bc-setting-list__item
    %label.bc-setting-list__control-input-label{for: 'panelised-checkbox-spiders'}
      .bc-setting-list__item__text
        %span.bc-label
          Receive sporadic
          %strong spiders
      .bc-setting-list__item__controls
        %span.bc-control-input.bc-control-input--unlabelled
          %input.bc-control-input__input{name: 'checkbox-spiders', type: 'checkbox', id: 'panelised-checkbox-spiders', 'aria-label': 'panelised-checkbox-spiders'}
            %span.bc-control-input__label-text
  %li.bc-setting-list__item{role: 'group', 'aria-describedby': 'panelised-setting__team-or-researcher-notification-types'}
    .bc-setting-list__item__text{id: 'panelised-setting__team-or-researcher-notification-types'}
      %span.bc-label
        Someone writes a
        %strong team note
        or a researcher
        %strong replies
    .bc-setting-list__item__controls
      %label.bc-control-input
        %input.bc-control-input__input(checked){name: 'checkbox-web', type: 'checkbox', 'aria-describedby': 'panelised-setting__team-or-researcher-notification-types'}
        %span.bc-control-input__label-text
          Web
      %label.bc-control-input
        %input.bc-control-input__input{name: 'checkbox-email', type: 'checkbox', 'aria-describedby': 'panelised-setting__team-or-researcher-notification-types'}
        %span.bc-control-input__label-text
          Email
  %li.bc-setting-list__item{role: 'group', 'aria-describedby': 'panelised-setting__ponies'}
    .bc-setting-list__item__text{id: 'panelised-setting__ponies'}
      %span.bc-label
        Receive sporadic
        %strong ponies
    .bc-setting-list__item__controls
      %label.bc-control-input
        %input.bc-control-input__input{name: 'sporadic-ponies__off', type: 'radio', 'aria-describedby': 'panelised-setting__ponies'}
        %span.bc-control-input__label-text
          Off
      %label.bc-control-input
        %input.bc-control-input__input(checked){name: 'sporadic-ponies__on', type: 'radio', 'aria-describedby': 'panelised-setting__ponies'}
        %span.bc-control-input__label-text
          On