Buttons

Buttons are arguably a design system’s most important component. They offer a simple label in a defined area you can press. They are prime representations of a design system’s basic attributes— color, typography, and iconography.

Element

You can create buttons by using either of these elements:

  • <button>
  • <a>
  • <input type="button|reset|submit">

This is a regular HTML <button>-tag styled to look like a link, using the kx-btn--skin-link-modifier.

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-link kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">I'm actually a button</span>
    </span>
</button>

Similarly, we can take a regular HTML-link, and style it like av button. In this example, a primary button using the kx-btn--skin-primary-modifier.

<!-- LINK AS BUTTON Component -->
<a class="kx-btn kx-btn--skin-primary kx-btn--size-large" href="http://www.example.com">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">I'm actually a link</span>
    </span>
</a>

You might wonder why we have a button-skin named link? Why not use a normal link (<a href="...">...</a>) instead of a button (<button>...</button>)?

No doubt a valid question. But sometimes you’d like an actual button element to look like a link, but the behavior might be to trigger an action instead of pointing to another URL. Let’s imagine two scenarios:

The user performs an action that triggers a modal window. The modal contains some information along with two actionable elements:

If you’d like to aid the user to make the desirable option “Confirm”, this button can be styled as a primary or secondary button. The “Cancel”-button is preferably toned down in comparison, using the link-style.

OK - again, why not use a normal link here?

The reason is simple. The “Cancel” operation just triggers an event to close the modal window, not redirecting the user to another URL. So in this case, using an actual <a>...</a>-element would be semantically wrong, and misleading to the user.

Scenario 2: <a> as a button

In a promotional element, you’d like the user to start a flow by clicking a prominent call-to-action, a primary button:

Sign up Today!

The start of this flow might be a different URL, so using an <a>...</a>-tag with a href="..."-attribute would be the best choice. To make the element more prominent, we still style it visually as a primary button.

Scenario 3: <input> as a button

In HTML, you can also use input-elements as buttons. You then need to specify a type-attribute. Available input types for buttons, are:

  • input type=button
  • input type=reset
  • input type=submit

These input types are closely related to forms, and are usually wrapped inside a <form>-tag. The <input type="reset"/> is used to clean a form, the <input type="submit"/> is used to submit the data, and a regular <input type="button"/> can be hooked to a custom event.

Due to the self-closing syntax for <input/>, buttons made this way cannot contain icons. You can still apply the regular classes and modifiers that apply to buttons.

In modern web applications, the regular <button>-element is usually sufficient.

Skin

Skin controls the look and feel of the button regardless of element type( <a>, <button>, or <input>). This includes background-color, text-color, borders, shadows etc. Skins do not impact layout features like spacing and dimensions.

Buttons come in three skins:

  • primary
  • secondary
  • flat
  • link
<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-primary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Primary Button</span>
    </span>
</button>

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Secondary Button</span>
    </span>
</button>

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-flat kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Flat Button</span>
    </span>
</button>

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-link kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Link Button</span>
    </span>
</button>

Size

Buttons come in three sizes:

  • tiny
  • base
  • large
<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-tiny">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Tiny Button</span>
    </span>
</button>

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-base">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Base Button</span>
    </span>
</button>

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Large Button</span>
    </span>
</button>

Disabled

Even if we provide a disabled state for buttons, we should be aware that this might not be the best UX-pattern for users. A disabled button is usually harder to notice due to low contrast. It’s often better to not show the button at all, if it is not clickable.

When the conditions are met, e.g. the user checks a checkbox that enables the button, it’s often better to just show it.

<button class=”kx-btn kx-btn–skin-primary kx-btn–size-large”disabled=”disabled”> Primary Button <button class=”kx-btn kx-btn–skin-secondary kx-btn–size-large”disabled=”disabled”> Secondary Button <button class=”kx-btn kx-btn–skin-flat kx-btn–size-large”disabled=”disabled”> Flat Button <button class=”kx-btn kx-btn–skin-link kx-btn–size-large”disabled=”disabled”> Link Button

Icon Buttons

Buttons can contain icons as well as text. Icons can appear before the text, after the text, or with hidden text. Due to accessibility reasons, one shouldn’t make buttons without text. A better option is to hide the text visually if you would a button to display only the icon.

Icon before text

Note: The icon, represented by the <i class="kx-icon...">...</i>-tag comes before the text <span class="kx-btn__txt">...</span>.

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <!-- ICON Component -->
<i class="kx-icon kx-icon--size-base">
    <svg focusable="false">
        <use xlink:href="../../assets/img/icons/sprites/icons.svg#pin"></use>
    </svg>
</i>
        <span class="kx-btn__txt">Pin to dashboard</span>
    </span>
</button>

Icon after text

Note: The text, represented by the <span class="kx-btn__txt">...</span>-tag comes before the icon <i class="kx-icon...">...</i>.

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Continue</span>
        <!-- ICON Component -->
<i class="kx-icon kx-icon--size-base">
    <svg focusable="false">
        <use xlink:href="../../assets/img/icons/sprites/icons.svg#angle-right"></use>
    </svg>
</i>
    </span>
</button>

Icon only - hidden text

Buttons should always have a text that makes them accessible for screen readers. Visually, the buttons may show only the icon.

In this case, use the utility-class kx-is-vishidden on the text inside the button:

<!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large kx-btn--icon" aria-label="This text is visually hidden, but still accessible through screen readers">
    <span class="kx-btn__inner">
        <!-- ICON Component -->
<i class="kx-icon kx-icon--size-moderate">
    <svg focusable="false">
        <use xlink:href="../../assets/img/icons/sprites/icons.svg#attachment"></use>
    </svg>
</i>
        <span class="kx-btn__txt kx-is-vishidden">This text is visually hidden, but still accessible through screen readers</span>
    </span>
</button>

Since icons can have many different shapes, we provide the flexibility to render a button in a specific size with an icon in a different size.

State

A variant of the icon button, is a button with a state. A button can be processing. This means it goes into a processing state after the user has clicked it.

This will provide a loader as icon.

If the button is not clickable during processing, it’s recommended to disable the button as well. This helps communicate that the button is performing an operation:

<button class=”kx-btn kx-btn–skin-primary kx-btn–size-large kx-ui kx-is-processing”disabled=”disabled”> Please wait

Fluid

If you like the button to fill the available width of the containing element, use the kx-btn--fluid class.

Button Groups

By wrapping buttons inside a button group, they become related - both visually and semantically. A button group uses the attribute role="group" to tie the buttons together.

<!-- BUTTON-GROUP Component -->
<div class="kx-btngroup kx-flex kx-flex-wrap" role="group" aria-label="A button group"><!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">First</span>
    </span>
</button>
        <!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Second</span>
    </span>
</button>
        <!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Third</span>
    </span>
</button>
        </div>

You can also apply a “tight” fit to the group, removing space between the buttons: kx-btngroup--fit-tight.

Or make the group stretch the width of the containing: kx-btngroup--fit-stretch.

Or maybe both kx-btngroup--fit-tight and kx-btngroup--fit-stretch together:

Button Toolbars

By wrapping and combining several button groups, you can create a button toolbar.

<!-- BUTTON-TOOLBAR Component -->
<div class="kx-btntoolbar kx-flex kx-flex-wrap" role="toolbar" aria-label="A toolbar with 3 button groups">
    <!-- BUTTON-GROUP Component -->
<div class="kx-btngroup kx-flex kx-flex-wrap kx-btngroup--fit-tight" role="group" aria-label="First group"><!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 1A</span>
    </span>
</button>
        <!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 1B</span>
    </span>
</button>
        </div>
    <!-- BUTTON-GROUP Component -->
<div class="kx-btngroup kx-flex kx-flex-wrap kx-btngroup--fit-tight" role="group" aria-label="Second group"><!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 2A</span>
    </span>
</button>
        <!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 2B</span>
    </span>
</button>
        </div>
    <!-- BUTTON-GROUP Component -->
<div class="kx-btngroup kx-flex kx-flex-wrap kx-btngroup--fit-tight" role="group" aria-label="Third group"><!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 3A</span>
    </span>
</button>
        <!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 3B</span>
    </span>
</button>
        <!-- BUTTON Component -->
<button class="kx-btn kx-btn--skin-secondary kx-btn--size-large">
    <span class="kx-btn__inner">
        <span class="kx-btn__txt">Button 3B</span>
    </span>
</button>
        </div>
    </div>