Bugcrowd design system: Forms

This version of the documentation is locked from receiving updates. We’re improving it as part of a wider site restructure. Please check back soon.

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 a meaningful reading order across breakpoints 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: Sep 1, 2023

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: 'foo@bar.com'}

    .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: Sep 1, 2023

Wrappers for related form elements.

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: Sep 12, 2023

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 occurred; 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 assistive 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 proximity 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:
  <div className='bc-page-alert bc-page-alert--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>
  </div>

  // [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: Sep 12, 2023

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 themselves 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.

Labelling optional and required fields

Mark optional fields by appending “(optional)” in a subdued text style in the label text.

Do not mark required fields with an asterisk (*).

Optional vs required label marking rationale

When building forms we seek to minimize optional questions as much as possible. We then reduce visual clutter of small, repetitive markers on labels by marking the few if any optional fields directly.

Required fields are semantically marked using the required attribute (or equivalent aria-required).

For visual users we deemed this to be an improvement, so long as optional form elements are the exception.

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
      %span.bc-hint.bc-helper-inlineblock.bc-m-0
        (optional)
    .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-required': 'true', '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: Sep 1, 2023

Buttons for all occasions.

Use button styles 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).

Button styles and their purpose

Buttons test file

There are three core button styles:

Type Purpose
Use for the strongest, single action in user flow, page, or feature. A primary button should only appear once per page (not including modal actions).
Use for all other actions other than the primary button. Used in the Inline control group pattern.
Use the tertiary button as a tertiary variant, for an even more subdued style.

This 3-tier structure can be extended sparingly by:

Other variants Purpose
Use to denote an action that is highly encouraged of the user. To be treated like a primary action per page or modal. Use sparingly.
Use to denote actions that are highly discouraged of the user, destructive or undoable. Use on the final confirmation of a irreversible destructive action.
Reserved for marketing purposes. Use sparingly and avoid combining with the --small variant; only WCAG 2 A compliant.
Use for actions that require the button to be styled as inline text. Do not style anchors as link buttons — simply use an anchor and its styles.

Buttons vs links

“Button” styles are often applied to <button>s and sometimes <a> anchors.

If technically necessary, we can apply them to <span> and <div> tags too.

Note however that anchors and button tags have intrinsic differences in purpose and function.

For more in-depth info check out Marcy Sutton’s Links vs. Buttons in Modern Web Applications.

Buttons:

  • 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.

Links (<a>):

  • Create hypertext links — a network of online resources
  • Register a click with the Enter key
  • Navigate the user to a new page or view
  • Change the user agent URL
  • Can 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
  • 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.

Buttons and links: Dos & Don’ts

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).

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.

Grouping buttons

On alignment and ordering:

  • Buttons should be left-aligned by default, with the primary button coming first
  • Buttons in modals are right-aligned, with primary button on the right
  • Edit buttons placed near a heading for that section should be right-aligned from the heading

When separating features and sub-features:

  • Use secondary and tertiary styles to distinguish order of importance
  • Use the small size to further differentiate nested or tertiary functionality

Correct button grouping examples

Correct usage examples Notes
Secondary style when grouped with a primary button
Secondary style when grouped with positive and negative buttons
Secondary style for related actions
Tertiary style for more subdued or unrelated actions

Incorrect button grouping examples

Incorrect usage examples Problem
Uses more than one primary button
Uses strong, opposing button styles together
Uses primary, negative, and/or positive button styles together

Using classes for complex state management

Due to limitations with HTML–CSS or in custom JavaScript components sometimes it isn’t possible to provide the correct state styles for :focus, :hover, and :active, eg. when transposing :focus from an input[type=radio] to a sibling span, all nested inside a <label> (see Control inputs).

For this reason the states are exposed as BEM variant classes, auto-styled to match the buttons style they’re appended to:

  • :focus: .bc-btn--focus
  • :hover: .bc-btn--hover
  • :active: .bc-btn--active

Adding an icon to a button

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.

Rendered example of Buttons

Haml markup example of Buttons

%button.bc-btn Primary action

Variants

--disabled variant

Rendered example of Buttons
Haml markup example of Buttons --disabled
%button.bc-btn.bc-btn--disabled(disabled) Primary action (disabled)

--secondary variant

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

--tertiary variant

Rendered example of Buttons
Haml markup example of Buttons --tertiary
%button.bc-btn.bc-btn--tertiary Tertiary action

--brand variant

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

--positive variant

Rendered example of Buttons
Haml markup example of Buttons --positive
%button.bc-btn.bc-btn--positive Create record action

--negative variant

Rendered example of Buttons
Haml markup example of Buttons --negative
%button.bc-btn.bc-btn--negative Delete record action

--link variant

--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


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.bc-btn--icon-hidden-text{'aria-label': 'Visually-hidden text button'}
  %span Visually-hiden text icon button

%hr

%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--icon.bc-btn--add{'aria-label': 'Add username'}
  %span Add username

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--add{'aria-label': 'Add username'}
  %span Add username

%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

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--search{'aria-label': 'Search'}
  %span Search

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

%button.bc-btn.bc-btn--icon.bc-btn--dropdown{'aria-label': 'Primary dropdown'}
  %span Dropdown

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--dropdown{'aria-label': 'Open this thing'}
  %span Dropdown

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--dropdown-open{'aria-label': 'Close this dropdown thing'}
  %span Dropdown

%button.bc-btn.bc-btn--icon.bc-btn--next{'aria-label': 'Next'}
  %span Next

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--next{'aria-label': 'Next'}
  %span Next

%button.bc-btn.bc-btn--secondary.bc-btn--icon.bc-btn--prev{'aria-label': 'Previous'}
  %span Previous

%hr

%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--add{'aria-label': 'Add username'}
  %span Add username

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

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

%button.bc-btn.bc-btn--tertiary.bc-btn--icon-hidden-text.bc-btn--drag{'aria-label': 'Drag and drop'}
  %span Drag

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

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

--block variant

Rendered example of Buttons
Haml markup example of Buttons --block
%button.bc-btn.bc-btn--block Primary action
%button.bc-btn.bc-btn--block.bc-btn--positive Create record action
%button.bc-btn.bc-btn--block.bc-btn--secondary Secondary action
%button.bc-btn.bc-btn--block.bc-btn--negative Delete record/access action

File input

Guidance last updated: Sep 1, 2023

A simple file upload form input element.

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.

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-btn.bc-btn--secondary
    Upload a single file

Variants

--disabled variant

Rendered example of File input
Haml markup example of File input --disabled
%label.bc-file-input.bc-file-input--disabled
  %input.bc-file-input__input(disabled){name: 'file-input-eg--disabled', type: 'file', multiple: 'true'}
  %span.bc-btn.bc-btn--secondary
    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-btn.bc-btn--secondary
    %span Upload a single file
Guidance last updated: Sep 1, 2023

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

--invalid variant

Rendered example of Dropdowns
Haml markup example of Dropdowns --invalid
.bc-form
  .bc-form__group
    %label.bc-label{for: 'select-fruit'}
      Select a fruit
    .bc-dropdown.bc-dropdown--invalid
      %select{id: 'select-fruit', class: 'bc-dropdown__select'}
        %option{value: ''}
          Please select
        %option{value: '1'}
          Apple
        %option{value: '2'}
          Banana
        %option{value: '3'}
          Mango

Control input

Guidance last updated: Sep 12, 2023

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.

‘Card’ control input variant

This checkbox and radio variant adds a large panel as a clickable area for the entire card. It can contain:

  • label text (Required)
  • hint text
  • and images.

Use only for simplified forms that involve multiple steps to complete, for example, onboarding steps or wizards.

Use grid system to specify card widths in different screen sizes.

Grouping cards horizontally

Group cards with .bc-control-input--cards to arrange cards horizontally in a row.

Adding hint text and images to card variant

Add a descriptive string to your <label> (Preferably with the same content nested inside the <label>) with aria-label. This will ensure that the screen reader reads out the entire content instead of hinting that there are other items.

Further reading

Rendered example of Control input

Select all devices you own
Pick a fruit for lunch

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 Pick a fruit for lunch

    %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(disabled){name: 'radio-example', type: 'radio'}
      %span.bc-control-input__label-text
        Pineapple
        %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
        Passionfruit

    %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.
Pick a fruit for lunch

Errors:

  1. Please select an option.
  2. Passionfruit are out of stock — please pick a different fruit this time.
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', 'aria-describedby': 'radio-example-error-tos'}
      %span.bc-control-input__label-text
        I agree to the Terms &amp; Conditions and the Standard Disclosure Terms
    .bc-form__error{id: 'radio-example-error-tos'}
      %span.bc-icon.bc-icon--error
        %strong Error:
        You must agree to the
        %a{href: 'https://www.bugcrowd.com/resource/standard-disclosure-terms/'}
          Terms &amp; Conditions
        and the
        %a{href: 'https://www.bugcrowd.com/resource/standard-disclosure-terms/'}
          Standard Disclosure
        Terms in order to create an account.


.bc-form
  .bc-form__group
    %fieldset.bc-fieldset.bc-fieldset--visible
      %legend.bc-fieldset__legend Pick a fruit for lunch

      %label.bc-control-input
        %input.bc-control-input__input{name: 'radio-example-invalid', type: 'radio', 'aria-describedby': 'radio-example-error-fruit'}
        %span.bc-control-input__label-text
          Mango

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

      %label.bc-control-input.bc-control-input--invalid
        %input.bc-control-input__input(checked disabled){name: 'radio-example-invalid', type: 'radio', 'aria-describedby': 'radio-example-error-fruit'}
        %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-invalid', type: 'radio', 'aria-describedby': 'radio-example-error-fruit'}
        %span.bc-control-input__label-text
          Grapefruit

      .bc-form__group
        .bc-form__error{id: 'radio-example-error-fruit'}
          .bc-icon.bc-icon--error
            %p
              %strong
                Errors:
            %ol
              %li Please select an option.
              %li Passionfruit are out of stock — please pick a different fruit this time.

--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

--card variant

Rendered example of Control input
Select your interest
Choose your sauce
Which is better?
Are you still there?
Haml markup example of Control input --card
.bc-form
  %fieldset.bc-fieldset
    %legend.bc-fieldset__legend Select your interest

    .bc-control-input--cards.row
      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input{name: 'checkbox-finserv', type: 'checkbox'}
        %span.bc-control-input__label-text
          Financial services

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input(checked){name: 'checkbox-healthcare', type: 'checkbox'}
        %span.bc-control-input__label-text
          Healthcare

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input{name: 'checkbox-retail', type: 'checkbox'}
        %span.bc-control-input__label-text
          Retail

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input(checked){name: 'checkbox-auto', type: 'checkbox'}
        %span.bc-control-input__label-text
          Automotive

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input{name: 'checkbox-gov', type: 'checkbox'}
        %span.bc-control-input__label-text
          Government

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input{name: 'checkbox-secuirt', type: 'checkbox'}
        %span.bc-control-input__label-text
          Security

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input(checked){name: 'checkbox-marketplace', type: 'checkbox'}
        %span.bc-control-input__label-text
          Marketplace apps

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input{name: 'checkbox-tech', type: 'checkbox'}
        %span.bc-control-input__label-text
          Technology


.bc-form
  %fieldset.bc-fieldset
    %legend.bc-fieldset__legend Choose your sauce

    .bc-control-input--cards.row
      %label.bc-control-input.bc-control-input--card.col-md-4{'aria-label': 'Mayo, Mayonnaise, informally mayo, is a thick cold sauce or dressing.'}
        %input.bc-control-input__input{name: 'choose-sauce', type: 'radio'}
        %span.bc-control-input__label-text
          %img.bc-control-input--card-image{src: '/assets/profile-tmp.png', alt: 'Avatar image', role: 'presentation'}
          %p.bc-helper-nomargin
            Mayo
            %span.bc-control-input__hint
              Mayonnaise, informally mayo, is a thick cold sauce or dressing.

      %label.bc-control-input.bc-control-input--card.col-md-4{'aria-label': 'Ketchup, Ketchup is a sweet and tangy tomato based table sauce.'}
        %input.bc-control-input__input(checked){name: 'choose-sauce', type: 'radio'}
        %span.bc-control-input__label-text
          %img.bc-control-input--card-image{src: '/assets/profile-tmp.png', alt: 'Avatar image', role: 'presentation'}
          %p.bc-helper-nomargin
            Ketchup
            %span.bc-control-input__hint
              Ketchup is a sweet and tangy tomato based table sauce.


.bc-form
  %fieldset.bc-fieldset
    %legend.bc-fieldset__legend Which is better?

    .bc-control-input--cards.row
      %label.bc-control-input.bc-control-input--card.col-md-6{'aria-label': 'Coke, Coca-Cola, or Coke, is a carbonated soft drink manufactured by The Coca-Cola Company.'}
        %input.bc-control-input__input{name: 'which-is-better', type: 'radio'}
        %span.bc-control-input__label-text
          %p.bc-helper-nomargin
            Coke
            %span.bc-control-input__hint
              Coca-Cola, or Coke, is a carbonated soft drink manufactured by The Coca-Cola Company.

      %label.bc-control-input.bc-control-input--card.col-md-6{'aria-label': 'Pepsi, Pepsi is a carbonated soft drink manufactured by PepsiCo.'}
        %input.bc-control-input__input(checked){name: 'which-is-better', type: 'radio'}
        %span.bc-control-input__label-text
          %p.bc-helper-nomargin
            Pepsi
            %span.bc-control-input__hint
              Pepsi is a carbonated soft drink manufactured by PepsiCo.

.bc-form
  %fieldset.bc-fieldset
    %legend.bc-fieldset__legend Are you still there?

    .bc-control-input--cards.row
      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input(checked){name: 'answer-example', type: 'radio'}
        %span.bc-control-input__label-text
          Yes

      %label.bc-control-input.bc-control-input--card.col-md-3
        %input.bc-control-input__input{name: 'answer-example', type: 'radio'}
        %span.bc-control-input__label-text
          No

Segmented control

Guidance last updated: Sep 1, 2023

A sliding toggle control for a mutually exclusive set of options.

Use for live toggling between a set of up to 3 mutually exclusive but related choices.

Segmented control usage

  • Ensure the selection takes immediate effect (i.e. does not require a form Save submit button). See radio Control inputs.
  • Use radio <input> sets for configuration form contexts.
  • Use <button> sets for toggling interaction states, eg. “Write” and “Preview” in an editor.
  • When using <button> sets:
    • Dynamically toggle the active styling using the aria-selected boolean
    • Use aria-controls to associate the state toggles with their controlled content.
  • Use short and meaningful labels for the choices to maintain a roughly equal visual balance between each choice.
  • Do not truncate or wrap label text.
  • Do not use for binary (eg. “On”/“Off”) choices — see Switch inputs instead.
  • Do not use for add/remove actions.
  • Do not use Badge counters within this component.

Segmented control width

Segmented controls are 100% container width at <xs media query breakpoint.

At ≥xs the component uses CSS intrinsic sizing (min-content). Note IE11 does not support this, remaining stretched to 100% of the parent container width.

The --block variant retains the 100% width at all breakpoints. Use this for precise sizing within a column of a grid system.

Rendered example of Segmented control

Toggle Description Markdown field preview
Toggle index layout

Haml markup example of Segmented control

.bc-fieldset
  .bc-fieldset__legend
    Toggle Description Markdown field preview
  .bc-segmented-control{role: 'tablist'}
    %button.bc-segmented-control__btn(aria-selected="true"){role: 'tab'}
      Write
    %button.bc-segmented-control__btn(aria-selected="false"){role: 'tab'}
      Preview

.bc-fieldset
  .bc-fieldset__legend
    Toggle index layout
  .bc-segmented-control
    %input.bc-segmented-control__input{id: 'sgmntctrl-layout-grid', name: 'sgmntctrl-layout', type: 'radio'}
    %label.bc-segmented-control__label{for: 'sgmntctrl-layout-grid'}
      Grid
    %input.bc-segmented-control__input(checked){id: 'sgmntctrl-layout-list', name: 'sgmntctrl-layout', type: 'radio'}
    %label.bc-segmented-control__label{for: 'sgmntctrl-layout-list'}
      List

Variants

--trio variant

Rendered example of Segmented control
Filter date range
Haml markup example of Segmented control --trio
.bc-fieldset
  .bc-fieldset__legend
    Filter date range
  .bc-segmented-control.bc-segmented-control--trio
    %input.bc-segmented-control__input{id: 'sgmntctrl-eg-trio-monthly', name: 'sgmntctrl-eg-trio', type: 'radio'}
    %label.bc-segmented-control__label{for: 'sgmntctrl-eg-trio-monthly'}
      Monthly
    %input.bc-segmented-control__input(checked){id: 'sgmntctrl-eg-trio-seasonal', name: 'sgmntctrl-eg-trio', type: 'radio'}
    %label.bc-segmented-control__label{for: 'sgmntctrl-eg-trio-seasonal'}
      Seasonal
    %input.bc-segmented-control__input{id: 'sgmntctrl-eg-trio-annual', name: 'sgmntctrl-eg-trio', type: 'radio'}
    %label.bc-segmented-control__label{for: 'sgmntctrl-eg-trio-annual'}
      Annual

--block variant

Rendered example of Segmented control
Haml markup example of Segmented control --block
.bc-segmented-control.bc-segmented-control--block{role: 'tablist'}
  %button.bc-segmented-control__btn(aria-selected="false"){role: 'tab'}
    Write
  %button.bc-segmented-control__btn(aria-selected="true"){role: 'tab'}
    Preview

Switch input

Guidance last updated: Sep 12, 2023

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

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

Switch input React component

There is a BcSwitchInput component in @bugcrowd/bc-elements.

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-switch-input__label-text.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

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-switch-input__label-text.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

--disabled variant

Rendered example of Switch input
Haml markup example of Switch input --disabled
.bc-switch-input.bc-switch-input--disabled
  %label.bc-switch-input__inline-label{for: 'switch-disabled-eg1'}
    %span.bc-switch-input__label-text.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.bc-switch-input--disabled
  %label.bc-switch-input__inline-label{for: 'switch-disabled-eg2'}
    %span.bc-switch-input__label-text.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.bc-switch-input--disabled
  %label.bc-switch-input__inline-label{for: 'switch-disabled-eg3'}
    %span.bc-switch-input__label-text.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

Text input

Guidance last updated: Sep 12, 2023

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).

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.

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 sanitization.

Text input style guidance

Add the .bc-text-input--number variant for input[type='number'].

Add the .bc-text-input--textarea variant for <textarea>.

Add the .bc-text-input--code variant for monospaced font styles, when alphanumeric text input content benefits from differentiating characters. Do not chain with .bc-text-input--number.

Add the .bc-text-input--private variant for inputs that have content visible only between 2 users.

Add the .bc-text-input--bugcrowd-internal variant for inputs that have content visible only to the Bugcrowd team.

: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 (.bc-text-input--valid and .bc-text-input--invalid).

‘readonly’ disabled usage

Apply the .bc-text-input--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 .bc-text-input--readonly variant inputs that a user can directly interact with.

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: 'foo@bar.com'}

  .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: 'foo@domain', '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'}

--code variant

Rendered example of Text input
Haml markup example of Text input --code
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-textarea-codeblock'}
      Trace dump / HTTP request
      %span.bc-hint.bc-helper-inline
        (optional)
    %textarea.bc-text-input.bc-text-input--textarea.bc-text-input--code{name: 'textin-textarea-codebloc', id: 'textin-textarea-codeblock'}

--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'}

--private variant

Rendered example of Text input
Haml markup example of Text input --private
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-textarea-private'}
      Write your message
    %textarea.bc-text-input.bc-text-input--textarea.bc-text-input--private{name: 'textin-textarea-private', id: 'textin-textarea-private', placeholder: 'Your private message here...'}

--bugcrowd-internal variant

Rendered example of Text input
Haml markup example of Text input --bugcrowd-internal
.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-textarea-bugcrowd-internal'}
      Write your message
    %textarea.bc-text-input.bc-text-input--textarea.bc-text-input--bugcrowd-internal{name: 'textin-textarea-bugcrowd-internal', id: 'textin-textarea-bugcrowd-internal', placeholder: 'Your team note here...'}

Fixed text input

Guidance last updated: Sep 1, 2023

Text inputs with prepended or appended data points.

The Fixed text input pattern extends Text inputs.

Using Fixed text inputs

Use to further communicate to users what type or format of data is expected.

When building Fixed text inputs:

  • Set the correct <input> type
  • Give an ID to the <label> as well as any prepend or append and reference them on the <input> as aria-labelledby attributes.

Fixed text input variants

When using the --block variant, the nested .bc-text-input also requires its own .bc-text-input--block variant in addition.

Fixed text input rationale

Careful usage of prepended or appended text inputs can aid users in understanding what format data is expected in.

Care must be taken in ensuring the prepends and appends do not look like interactive elements such as a <button>. It is for this reason we apply the disabled form styles to the prepends and appends to ensure these parts of this input pattern do not appear interactive when the text field itself is disabled.

Rendered example of Fixed text input

$ AUD

Haml markup example of Fixed text input

.bc-form
  .bc-form__group
    %label.bc-label{for: 'textin-fixed-dollars', id: 'fixed-textin-dollars-label'}
      How many Dollarydoos would you like?
    .bc-fixed-text-input.bc-fixed-text-input--prepended.bc-fixed-text-input--appended
      %span.bc-fixed-text-input__prepend{id: 'fixed-textin-dollars-prepend'}
        $
      %input.bc-text-input{'aria-labelledby': 'fixed-textin-dollars-label fixed-textin-dollars-prepend fixed-textin-dollars-append', name: 'textin-fixed-dollars', id: 'textin-fixed-dollars', type: 'number', value: '9000'}
      %span.bc-fixed-text-input__append{id: 'fixed-textin-dollars-append'}
        %abbr{title: 'Australian Dollars'}
          AUD

Variants

--readonly variant

Rendered example of Fixed text input
@
Haml markup example of Fixed text input --readonly
.bc-form
  .bc-form__group
    %label.bc-label{for: 'fixed-textin-readonly'}
      Twitter account
      %span.bc-hint.bc-helper-inline (read-only)
    .bc-fixed-text-input.bc-fixed-text-input--readonly
      %span.bc-fixed-text-input__prepend
        @
      %input.bc-text-input.bc-text-input--readonly(disabled){name: 'fixed-textin-readonly', id: 'fixed-textin-readonly', type: 'text', value: 'bugcrowd'}

--disabled variant

Rendered example of Fixed text input
.com
Haml markup example of Fixed text input --disabled
.bc-form
  .bc-form__group
    %label.bc-label{for: 'fixed-textin-disabled', id: 'fixed-textin-disabled-label'}
      Disabled fixed text input
    .bc-fixed-text-input.bc-fixed-text-input--appended.bc-fixed-text-input--disabled
      %input.bc-text-input(disabled){'aria-labelledby': 'fixed-textin-disabled-label fixed-textin-disabled-append', name: 'fixed-textin-disabled', id: 'fixed-textin-disabled', type: 'text', value: 'redamallc'}
      %span.bc-fixed-text-input__append{id: 'fixed-textin-disabled-append'}
        \.com

--block variant

Rendered example of Fixed text input
https:// .com
Haml markup example of Fixed text input --block
.bc-form
  .bc-form__group
    %label.bc-label{for: 'fixed-textin-block', id: 'fixed-textin-block-label'}
      Block fixed text input
    .bc-fixed-text-input.bc-fixed-text-input--prepended.bc-fixed-text-input--appended.bc-fixed-text-input--block
      %span.bc-fixed-text-input__prepend{id: 'fixed-textin-block-prepend'}
        https://
      %input.bc-text-input.bc-text-input--block{'aria-labelledby': 'fixed-textin-block-label fixed-textin-block-prepend fixed-textin-block-append', name: 'fixed-textin-block', id: 'fixed-textin-block', type: 'text', value: 'redamallc'}
      %span.bc-fixed-text-input__append{id: 'fixed-textin-block-append'}
        \.com

Range slider

Guidance last updated: Sep 12, 2023

A sliding dial that sets a numeric value on a horizontal bar.

Use for numeric values in a range for users to select from.

Use for actions that take immediate effect. For forms that require a submit action to confirm and send data, consider using radio buttons from Control input.

Range slider usage

  • Avoid using where accurate selection is required — consider mobile/touch and keyboard users.
  • Avoid large ranges, especially without stepped intervals.
  • Do not use input[type=range] for representing text values. Instead use the ARIA slider role and aria-valuetext.

Adding ‘stops’ or ‘steps’ to the Range slider

Use the step attribute to add equally-sized intervals limiting the number of selectable options. The default step value is 1.

For example: in a range of 0–100, there are 100 options to select from. Setting step="10" limits the number of options from 100 to 10.

Steps can be visually displayed using the --ticked Range slider variant.

Set the desired number of steps using the data-bc-range-slider-ticks data attribute. It visually supports 3–10 steps.

Extending range sliders and multi-select

The standard HTML range slider is a single-select input for numeric values in a range.

Use ARIA markup and JavaScript to support text values or multi-range selection.

For more information see:

Rendered example of Range slider

Less than 1,000 employees selected

Haml markup example of Range slider

.bc-form__group
  %label.bc-label{for: 'cursor-speed-eg'} Cursor speed
  .bc-range-slider
    %input.bc-range-slider__input{type: 'range', id: 'cursor-speed-eg', name: 'text-speed', min: '1', max: '100'}

.bc-form__group
  %label.bc-label{for: 'staff-slider-eg'} Organization size
  .bc-range-slider
    %input.bc-range-slider__input{type: 'range', id: 'staff-slider-eg', name: 'staff', min: '1', max: '1000', value: '500', step: '499', 'aria-controls': 'staff-slider-eg-output'}
    .bc-range-slider__range{role: 'presentation'}
      %span 1
      %span ≥1000
  %div{id: 'staff-slider-eg-output', role: 'region', 'aria-live': 'polite'}
    %output.bc-hint
      Less than 1,000 employees selected

Variants

--ticked variant

Rendered example of Range slider
Less than 1,000 employees selected
Haml markup example of Range slider --ticked
.bc-form__group
  %label.bc-label{for: 'volume-slider-eg'} Volume
  .bc-range-slider.bc-range-slider--ticked
    %input.bc-range-slider__input{type: 'range', id: 'volume-slider-eg', name: 'volume', min: '0', max: '9', value: '2', 'data-bc-range-slider-ticks': '10'}
    .bc-range-slider__ticks

.bc-form__group
  %label.bc-label{for: 'staff-slider-eg-2'} Organization size
  .bc-range-slider.bc-range-slider--ticked
    %input.bc-range-slider__input{type: 'range', id: 'staff-slider-eg-2', name: 'staff', min: '1', max: '1000', value: '500', step: '499', 'data-bc-range-slider-ticks': '3', 'aria-controls': 'staff-slider-eg-output-2'}
    .bc-range-slider__ticks{role: 'presentation'}
    .bc-range-slider__range{role: 'presentation'}
      %span 1
      %span ≥1000
  %div{id: 'staff-slider-eg-output-2', role: 'region', 'aria-live': 'polite'}
    %output.bc-hint
      Less than 1,000 employees selected

Setting list

Guidance last updated: Sep 1, 2023

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

Date time input

Guidance last updated: Sep 12, 2023

A simple HTML5 date or time input.

Allows users to set dates and times. Combine together for setting ranges.

Defaults

By default a calendar icon is shown.

The --time variant is available to show a clock icon instead.

Usability and accessibility

This component uses native HTML5 date and time inputs.

Its core mouse, touch, keyboard and screen reader support is excellent.

Note: ::placeholder does not exist for this feature.

Note the extended functionality differs slightly — see Known browser differences below.

Known browser differences

In addition to differences between the native menu pickers and spinners, on desktop:

Browser Date field focus Date field click Date button Time field focus Time field click Time button Dirty behavior
Chrome Text Text Picker UI Text Text Picker UI  
Edge Text Text Picker UI Text Text Picker UI  
Safari Text Picker UI   Text Text    
Firefox Text Text Picker UI Text Text    

The component automatically handles mobile support, using their touch-based native spinners.

Dependencies

This component uses Text inputs.

Rationale

Native HTML5 date and time inputs have a good browser support and losing some control over the styles of the open picker menu UI is acceptable given the many benefits gained.

The benefits:

  • HTML5 native date and time inputs have good native support, in many cases exceeding that of third-party JS pickers
  • The usability and accessibility exceeds that of many third-party JS pickers
  • Mobile support is superior to most third-party JS pickers
  • Automatically uses local date and time preferences
  • KISS and don’t re-invent the wheel.

The downsides:

  • Minor browser inconsistencies
  • Lack of control in styling the picker menu
  • No inbuilt range support.

Rendered example of Date time input

Haml markup example of Date time input

.bc-form__group
  %label.bc-label{for: 'date'}
    Pick a date
  .bc-date-time-input
    %input.bc-text-input{name: 'date', id: 'date', type: 'date', value: ''}

Variants

--time variant

Rendered example of Date time input
Haml markup example of Date time input --time
.bc-form__group
  %label.bc-label{for: 'time'}
    Pick a time
  .bc-date-time-input.bc-date-time-input--time
    %input.bc-text-input{name: 'time', id: 'time', type: 'time', value: ''}

--disabled variant

Rendered example of Date time input
Haml markup example of Date time input --disabled
.bc-form__group
  %label.bc-label{for: 'date-disabled'}
    Pick a date
  .bc-date-time-input.bc-date-time-input--disabled
    %input.bc-text-input(disabled){name: 'date-disabled', id: 'date-disabled', type: 'date', value: ''}

.bc-form__group
  %label.bc-label{for: 'time-disabled'}
    Pick a time
  .bc-date-time-input.bc-date-time-input--time.bc-date-time-input--disabled
    %input.bc-text-input(disabled){name: 'time-disabled', id: 'time-disabled', type: 'time', value: ''}

--block variant

Rendered example of Date time input
Haml markup example of Date time input --block
.bc-form__group
  %label.bc-label{for: 'date-block'}
    Pick a date
  .bc-date-time-input.bc-date-time-input--block
    %input.bc-text-input{name: 'date-block', id: 'date-block', type: 'date', value: ''}

.bc-form__group
  %label.bc-label{for: 'time-block'}
    Pick a time
  .bc-date-time-input.bc-date-time-input--time.bc-date-time-input--block
    %input.bc-text-input{name: 'time-block', id: 'time-block', type: 'time', value: ''}