ToggleButton ​
A ToggleButton is a button that can be toggled on and off.
<cdx-toggle-button v-model="buttonValue">Button text</cdx-toggle-button>| Name | Value |
|---|---|
| Props | |
disabled | |
quiet | |
size | |
| Slots | |
default | |
| View | |
Reading direction | |
Overview ​
When to use ToggleButton ​
Use the ToggleButton component for options that require state persistence and are longer or more involved than a typical button click action. Avoid using ToggleButton if you need to trigger an immediate action; in this case use a Button instead.
There are two types of ToggleButtons: normal and quiet. Only use quiet ToggleButton for an easily recognizable action that does not detract focus from the content. There is no ToggleButton variant designed for progressive or destructive actions.
About ToggleButton ​
ToggleButton includes the following elements.
Label ​
Labels should be as short as possible, with text that clearly states what state is changed when toggling the ToggleButton (eg. show/hide).
ToggleButton label should ideally be fewer than 38 characters in English, as translations average 42 characters. Logographic and Arabic-script languages are generally shorter, while Romance, some Germanic, Slavic, Austronesian, and others like Greek and Finnish tend to be longer, averaging 45–53 characters.
Use the same text and icon in both off and on states.
Use descriptive, accessible verbs to encourage action. Concise & Accessible
Write in sentence case, capitalising only the first word. Consistent
Avoid using similar words for different ToggleButtons. Clear
Avoid verbs that imply visual or sensory abilities such as "see", or are idiomatic or vague. Accessible & Translatable
Icon (optional) ​
Icons simplify user recognition and provide the ability to shorten labels to a minimum. For icon-only ToggleButtons, the label will be visually hidden while still available to screen reader users.
- Ensure that icons used in ToggleButtons are relevant and easily recognizable.
- Avoid using icons that are difficult to recognize or do not clearly convey their purpose.
Examples ​
Basic usage ​
ToggleButtons should always have a static label. This helps indicate to the user (including users of assistive technology) what it means for the ToggleButton to be on or off. If you want a button with a label that changes when it is pressed, use the Button component instead.
Press the ToggleButton to check the value change.
<template>
<cdx-toggle-button
v-model="buttonValue"
@update:model-value="onUpdate"
>
Toggle
</cdx-toggle-button>
</template>
<script>
import { defineComponent, ref } from 'vue';
import { CdxToggleButton } from '@wikimedia/codex';
export default defineComponent( {
name: 'SingleButton',
components: { CdxToggleButton },
setup() {
const buttonValue = ref( false );
const onUpdate = function ( value ) {
// eslint-disable-next-line no-console
console.log( 'update:modelValue event emitted with value: ' + value );
};
return {
buttonValue,
onUpdate
};
}
} );
</script><template>
<cdx-toggle-button
v-model="buttonValue"
@update:model-value="onUpdate"
>
Toggle
</cdx-toggle-button>
</template>
<script>
const { defineComponent, ref } = require( 'vue' );
const { CdxToggleButton } = require( '@wikimedia/codex' );
module.exports = defineComponent( {
name: 'SingleButton',
components: { CdxToggleButton },
setup() {
const buttonValue = ref( false );
const onUpdate = function ( value ) {
// eslint-disable-next-line no-console
console.log( 'update:modelValue event emitted with value: ' + value );
};
return {
buttonValue,
onUpdate
};
}
} );
</script>Developer notes
Open up the console to check emitted events.
Button sizes ​
Buttons can be small, medium (default) or large size.
- Small
Use the small size only when space is tight: for example, inline with text or in compact layouts.
- Use lowercase letters to make the button fit better with surrounding text.
- Avoid using small buttons on touchable screens.
- Medium
Use medium as the standard button size. - Large
Use the large size to support accessibility on touchscreens by increasing the touch area.
By default, the width of a Button with text is determined by the width of the text until reaching a max-width. However, on mobile, Buttons should span the full-width of the container, except for icon-only Buttons, which will maintain their fixed square proportions.
| Size | Min-size | Text button | Icon-only button |
|---|---|---|---|
| Small | 24px | ||
| Medium | 32px | ||
| Large | 44px |
<template>
<table class="cdx-demo-button-sizes">
<caption>
Button size examples for all supported <code>size</code> values.
</caption>
<thead>
<tr>
<th>Size</th>
<th>Min-size</th>
<th>Text button</th>
<th>Icon-only button</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span>Small</span>
</td>
<td>
<span>24px</span>
</td>
<td>
<cdx-toggle-button
v-model="smallButtonValue"
size="small"
@click="onClick">
small button
</cdx-toggle-button>
</td>
<td>
<cdx-toggle-button
v-model="smallButtonIconValue"
aria-label="Small button example"
size="small"
@click="onClick">
<cdx-icon size="small" :icon="cdxIconBell" />
</cdx-toggle-button>
</td>
</tr>
<tr>
<td>
<span>Medium</span>
</td>
<td>
<span>32px</span>
</td>
<td>
<cdx-toggle-button v-model="mediumButtonValue" @click="onClick">
Medium button
</cdx-toggle-button>
</td>
<td>
<cdx-toggle-button
v-model="mediumButtonIconValue"
aria-label="Medium button example"
@click="onClick">
<cdx-icon :icon="cdxIconBell" />
</cdx-toggle-button>
</td>
</tr>
<tr>
<td>
<span>Large</span>
</td>
<td>
<span>44px</span>
</td>
<td>
<cdx-toggle-button
v-model="largeButtonValue"
size="large"
@click="onClick">
Large button
</cdx-toggle-button>
</td>
<td>
<cdx-toggle-button
v-model="largeButtonIconValue"
aria-label="Large button example"
size="large"
@click="onClick">
<cdx-icon :icon="cdxIconBell" />
</cdx-toggle-button>
</td>
</tr>
</tbody>
</table>
</template>
<script>
import { defineComponent, ref } from 'vue';
import { CdxToggleButton, CdxIcon } from '@wikimedia/codex';
import { cdxIconBell } from '@wikimedia/codex-icons';
export default defineComponent( {
name: 'ButtonSizes',
components: { CdxToggleButton, CdxIcon },
setup() {
function onClick() {
// eslint-disable-next-line no-console
console.log( 'click event emitted' );
}
return {
smallButtonValue: ref( false ),
smallButtonIconValue: ref( false ),
mediumButtonValue: ref( false ),
mediumButtonIconValue: ref( false ),
largeButtonValue: ref( false ),
largeButtonIconValue: ref( false ),
cdxIconBell,
onClick
};
}
} );
</script>
<style lang="less">
@import ( reference ) '@wikimedia/codex-design-tokens/theme-wikimedia-ui.less';
.cdx-demo-button-sizes {
table {
width: @size-full;
}
caption {
margin-top: @spacing-25;
text-align: left;
caption-side: bottom;
}
}
</style><template>
<table class="cdx-demo-button-sizes">
<caption>
Button size examples for all supported <code>size</code> values.
</caption>
<thead>
<tr>
<th>Size</th>
<th>Min-size</th>
<th>Text button</th>
<th>Icon-only button</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span>Small</span>
</td>
<td>
<span>24px</span>
</td>
<td>
<cdx-toggle-button
v-model="smallButtonValue"
size="small"
@click="onClick">
small button
</cdx-toggle-button>
</td>
<td>
<cdx-toggle-button
v-model="smallButtonIconValue"
aria-label="Small button example"
size="small"
@click="onClick">
<cdx-icon size="small" :icon="cdxIconBell"></cdx-icon>
</cdx-toggle-button>
</td>
</tr>
<tr>
<td>
<span>Medium</span>
</td>
<td>
<span>32px</span>
</td>
<td>
<cdx-toggle-button v-model="mediumButtonValue" @click="onClick">
Medium button
</cdx-toggle-button>
</td>
<td>
<cdx-toggle-button
v-model="mediumButtonIconValue"
aria-label="Medium button example"
@click="onClick">
<cdx-icon :icon="cdxIconBell"></cdx-icon>
</cdx-toggle-button>
</td>
</tr>
<tr>
<td>
<span>Large</span>
</td>
<td>
<span>44px</span>
</td>
<td>
<cdx-toggle-button
v-model="largeButtonValue"
size="large"
@click="onClick">
Large button
</cdx-toggle-button>
</td>
<td>
<cdx-toggle-button
v-model="largeButtonIconValue"
aria-label="Large button example"
size="large"
@click="onClick">
<cdx-icon :icon="cdxIconBell"></cdx-icon>
</cdx-toggle-button>
</td>
</tr>
</tbody>
</table>
</template>
<script>
const { defineComponent, ref } = require( 'vue' );
const { CdxToggleButton, CdxIcon } = require( '@wikimedia/codex' );
const { cdxIconBell } = require( './icons.json' );
module.exports = defineComponent( {
name: 'ButtonSizes',
components: { CdxToggleButton, CdxIcon },
setup() {
function onClick() {
// eslint-disable-next-line no-console
console.log( 'click event emitted' );
}
return {
smallButtonValue: ref( false ),
smallButtonIconValue: ref( false ),
mediumButtonValue: ref( false ),
mediumButtonIconValue: ref( false ),
largeButtonValue: ref( false ),
largeButtonIconValue: ref( false ),
cdxIconBell,
onClick
};
}
} );
</script>
<style lang="less">
@import 'mediawiki.skin.variables.less';
.cdx-demo-button-sizes {
table {
width: @size-full;
}
caption {
margin-top: @spacing-25;
text-align: left;
caption-side: bottom;
}
}
</style>Developer notes
Set min-width manually on Buttons with extremely short labels. Buttons with text labels of only 1-2 characters in length may fall below size of the target area described above. In these cases, set a minimum width of @min-size-interactive-pointer in your own CSS.
With icon ​
Use an icon with the ToggleButton label when you need to convey meaning through both textual and visual elements.
<template>
<cdx-toggle-button
v-model="buttonValue"
@update:model-value="onUpdate"
>
<cdx-icon :icon="cdxIconPlay" />
Play
</cdx-toggle-button>
</template>
<script>
import { defineComponent, ref } from 'vue';
import { CdxToggleButton, CdxIcon } from '@wikimedia/codex';
import { cdxIconPlay } from '@wikimedia/codex-icons';
export default defineComponent( {
name: 'SingleButton',
components: { CdxToggleButton, CdxIcon },
setup() {
const buttonValue = ref( false );
const onUpdate = function ( value ) {
// eslint-disable-next-line no-console
console.log( 'update:modelValue event emitted with value: ' + value );
};
return {
buttonValue,
onUpdate,
cdxIconPlay
};
}
} );
</script><template>
<cdx-toggle-button
v-model="buttonValue"
@update:model-value="onUpdate"
>
<cdx-icon :icon="cdxIconPlay"></cdx-icon>
Play
</cdx-toggle-button>
</template>
<script>
const { defineComponent, ref } = require( 'vue' );
const { CdxToggleButton, CdxIcon } = require( '@wikimedia/codex' );
const { cdxIconPlay } = require( './icons.json' );
module.exports = defineComponent( {
name: 'SingleButton',
components: { CdxToggleButton, CdxIcon },
setup() {
const buttonValue = ref( false );
const onUpdate = function ( value ) {
// eslint-disable-next-line no-console
console.log( 'update:modelValue event emitted with value: ' + value );
};
return {
buttonValue,
onUpdate,
cdxIconPlay
};
}
} );
</script>Icon-only ​
When the ToggleButton includes only an icon and no text, add an aria-label to the ToggleButton to ensure the action is understandable to those using assistive technology.
<template>
<cdx-toggle-button
v-model="buttonValue"
aria-label="Edit"
>
<cdx-icon :icon="cdxIconEdit" />
</cdx-toggle-button>
</template>
<script>
import { defineComponent, ref } from 'vue';
import { CdxToggleButton, CdxIcon } from '@wikimedia/codex';
import { cdxIconEdit } from '@wikimedia/codex-icons';
export default defineComponent( {
name: 'IconOnlyButton',
components: { CdxToggleButton, CdxIcon },
setup() {
const buttonValue = ref( false );
return {
buttonValue,
cdxIconEdit
};
}
} );
</script><template>
<cdx-toggle-button
v-model="buttonValue"
aria-label="Edit"
>
<cdx-icon :icon="cdxIconEdit"></cdx-icon>
</cdx-toggle-button>
</template>
<script>
const { defineComponent, ref } = require( 'vue' );
const { CdxToggleButton, CdxIcon } = require( '@wikimedia/codex' );
const { cdxIconEdit } = require( './icons.json' );
module.exports = defineComponent( {
name: 'IconOnlyButton',
components: { CdxToggleButton, CdxIcon },
setup() {
const buttonValue = ref( false );
return {
buttonValue,
cdxIconEdit
};
}
} );
</script>Technical implementation ​
Vue usage ​
The v-model value will be a boolean, it is true if the ToggleButton is currently toggled ("on") and false otherwise ("off").
Props ​
| Prop name | Description | Type | Values | Default |
|---|---|---|---|---|
modelValue | Whether the ToggleButton should be set to "on" (true) or "off" (false). Provided by v-model binding in the parent component. | boolean | - | false |
disabled | Whether the disabled attribute should be added to the ToggleButton, which prevents it from being clicked. | boolean | - | false |
quiet | Whether the ToggleButton should be "quiet", which renders more minimally. | boolean | - | false |
size | Button size. Medium: Default for most cases. Large: Use rarely, mainly for icon-only buttons on touchscreens. Small: Use in tight spaces or inline with text. Avoid on touchscreens - prefer medium for better accessibility. | ButtonSize | 'small', 'medium', 'large' | 'medium' |
Events ​
| Event name | Properties | Description |
|---|---|---|
update:modelValue | modelValue boolean - The new model value | Emitted when modelValue changes (i.e. when the state is toggled) |
Slots ​
| Name | Description | Bindings |
|---|---|---|
| default | ToggleButton content |
Keyboard navigation ​
| Key | Function |
|---|---|
| Tab | It moves the focus to the next interactive element. |
| Shift + Tab | It moves the focus to the previous interactive element. |
| Enter / Space | If the focus is placed on the button, it toggles the ToggleButton on and off. |