diff --git a/src/components/v-checkbox/readme.md b/src/components/v-checkbox/readme.md
index e0bf88df08..d745ae8c57 100644
--- a/src/components/v-checkbox/readme.md
+++ b/src/components/v-checkbox/readme.md
@@ -86,13 +86,17 @@ If you can't, you should listen to the `update:indeterminate` event and respond
```
## Props
-| Prop | Description | Default |
-|-----------------|--------------------------------------------------------------------------|---------|
-| `value` | Value for checkbox. Similar to value attr on checkbox type input in HTML | `--` |
-| `inputValue` | Value that's used with `v-model`. Either boolean or array of values | `false` |
-| `label` | Label for the checkbox | `--` |
-| `disabled` | Disable the checkbox | `false` |
-| `indeterminate` | Show the indeterminate state | `false` |
+| Prop | Description | Default |
+|----------------------|--------------------------------------------------------------------------|---------------------------|
+| `value` | Value for checkbox. Similar to value attr on checkbox type input in HTML | `--` |
+| `inputValue` | Value that's used with `v-model`. Either boolean or array of values | `false` |
+| `label` | Label for the checkbox | `--` |
+| `disabled` | Disable the checkbox | `false` |
+| `indeterminate` | Show the indeterminate state | `false` |
+| `icon-on` | What icon to use for the on state | `check_box` |
+| `icon-off` | What icon to use for the off state | `check_box_outline_blank` |
+| `icon-indeterminate` | What icon to use for the indeterminate state | `indeterminate_check_box` |
+| `block` | Show as styled block. Matches input size | `block` |
## Slots
| Slot | Description |
diff --git a/src/components/v-checkbox/v-checkbox.story.ts b/src/components/v-checkbox/v-checkbox.story.ts
index 3378b7b29b..dacb7a833a 100644
--- a/src/components/v-checkbox/v-checkbox.story.ts
+++ b/src/components/v-checkbox/v-checkbox.story.ts
@@ -1,9 +1,10 @@
-import { withKnobs, color } from '@storybook/addon-knobs';
+import { withKnobs, color, text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import Vue from 'vue';
import VCheckbox from '../v-checkbox';
import markdown from './readme.md';
import withPadding from '../../../.storybook/decorators/with-padding';
+import { defineComponent, ref } from '@vue/composition-api';
Vue.component('v-checkbox', VCheckbox);
@@ -87,9 +88,9 @@ export const colors = () => ({
},
template: `
-
-
-
+
+
+
`,
@@ -136,3 +137,53 @@ export const slots = () => ({
`,
});
+
+export const customIcons = () =>
+ defineComponent({
+ props: {
+ iconOn: {
+ default: text('Icon (On)', 'check'),
+ },
+ iconOff: {
+ default: text('Icon (Off)', 'close'),
+ },
+ iconIndeterminate: {
+ default: text('Icon (Indeterminate)', 'more_horiz'),
+ },
+ },
+ setup() {
+ const checked = ref(false);
+ const indeterminate = ref(false);
+ return { checked, indeterminate };
+ },
+ template: `
+
+
+
+
+ `,
+ });
+
+export const blockStyle = () =>
+ defineComponent({
+ setup() {
+ const checked = ref(false);
+ const indeterminate = ref(false);
+ return { checked, indeterminate };
+ },
+ template: `
+
+ `,
+ });
diff --git a/src/components/v-checkbox/v-checkbox.vue b/src/components/v-checkbox/v-checkbox.vue
index 66560dd1d9..bea6cd1e96 100644
--- a/src/components/v-checkbox/v-checkbox.vue
+++ b/src/components/v-checkbox/v-checkbox.vue
@@ -6,7 +6,7 @@
role="checkbox"
:aria-pressed="isChecked ? 'true' : 'false'"
:disabled="disabled"
- :class="{ checked: isChecked, indeterminate }"
+ :class="{ checked: isChecked, indeterminate, block }"
>
@@ -46,6 +46,22 @@ export default defineComponent({
type: Boolean,
default: false,
},
+ iconOn: {
+ type: String,
+ default: 'check_box',
+ },
+ iconOff: {
+ type: String,
+ default: 'check_box_outline_blank',
+ },
+ iconIndeterminate: {
+ type: String,
+ default: 'indeterminate_check_box',
+ },
+ block: {
+ type: Boolean,
+ default: false,
+ },
},
setup(props, { emit }) {
const isChecked = computed(() => {
@@ -57,8 +73,8 @@ export default defineComponent({
});
const icon = computed(() => {
- if (props.indeterminate === true) return 'indeterminate_check_box';
- return isChecked.value ? 'check_box' : 'check_box_outline_blank';
+ if (props.indeterminate === true) return props.iconIndeterminate;
+ return isChecked.value ? props.iconOn : props.iconOff;
});
return { isChecked, toggleInput, icon };
@@ -90,8 +106,9 @@ export default defineComponent({
@import '@/styles/mixins/no-wrap';
.v-checkbox {
- --v-checkbox-color: var(--foreground-normal);
+ --v-checkbox-color: var(--primary);
+ position: relative;
display: flex;
align-items: center;
font-size: 0;
@@ -129,10 +146,45 @@ export default defineComponent({
}
}
+ &.block {
+ position: relative;
+ width: 100%;
+ height: var(--input-height);
+ padding: 10px; // 14 - 4 (border)
+ background-color: var(--page-background);
+ border: 2px solid var(--background-subdued);
+ border-radius: var(--border-radius);
+
+ &::before {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: -1;
+ width: 100%;
+ height: 100%;
+ background-color: var(--background-subdued);
+ border-radius: var(--border-radius);
+ content: '';
+ }
+ }
+
&:not(:disabled):not(.indeterminate).checked {
.checkbox {
--v-icon-color: var(--v-checkbox-color);
}
+
+ &.block {
+ border-color: var(--v-checkbox-color);
+
+ .label {
+ color: var(--v-checkbox-color);
+ }
+
+ &::before {
+ background-color: var(--v-checkbox-color);
+ opacity: 0.1;
+ }
+ }
}
.prepend,
diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts
index e28af214da..ebed39a18e 100644
--- a/src/interfaces/index.ts
+++ b/src/interfaces/index.ts
@@ -3,6 +3,7 @@ import InterfaceTextarea from './textarea/';
import InterfaceDivider from './divider/';
import InterfaceNumeric from './numeric/';
import InterfaceSlider from './slider/';
+import InterfaceToggle from './toggle/';
export const interfaces = [
InterfaceTextInput,
@@ -10,6 +11,7 @@ export const interfaces = [
InterfaceNumeric,
InterfaceSlider,
InterfaceDivider,
+ InterfaceToggle,
];
export default interfaces;
diff --git a/src/interfaces/toggle/index.ts b/src/interfaces/toggle/index.ts
new file mode 100644
index 0000000000..4a881946bc
--- /dev/null
+++ b/src/interfaces/toggle/index.ts
@@ -0,0 +1,38 @@
+import InterfaceToggle from './toggle.vue';
+import { defineInterface } from '@/interfaces/define';
+
+export default defineInterface(({ i18n }) => ({
+ id: 'toggle',
+ name: i18n.t('toggle'),
+ icon: 'check_box',
+ component: InterfaceToggle,
+ options: [
+ {
+ field: 'iconOff',
+ name: i18n.t('icon_off'),
+ width: 'half',
+ interface: 'icon',
+ default_value: 'check_box_outline_blank',
+ },
+ {
+ field: 'iconOn',
+ name: i18n.t('icon_on'),
+ width: 'half',
+ interface: 'icon',
+ default_value: 'check_box',
+ },
+ {
+ field: 'label',
+ name: i18n.t('label'),
+ width: 'half',
+ interface: 'text-input',
+ },
+ {
+ field: 'color',
+ name: i18n.t('color'),
+ width: 'half',
+ interface: 'color',
+ default_value: 'var(--primary)',
+ },
+ ],
+}));
diff --git a/src/interfaces/toggle/readme.md b/src/interfaces/toggle/readme.md
new file mode 100644
index 0000000000..fa6fb5bd1a
--- /dev/null
+++ b/src/interfaces/toggle/readme.md
@@ -0,0 +1,12 @@
+# Toggle
+
+Simple single styled checkbox
+
+## Options
+
+| Option | Description | Default |
+|------------|----------------------------------------------------|---------------------------|
+| `color` | What color to use for the on state of the checkbox | `var(--primary)` |
+| `label` | What label to show next to the checkbox | `null` |
+| `icon-on` | What icon to show when the checkbox is checked | `check_box` |
+| `icon-off` | What icon to show when the checkbox is unchecked | `check_box_outline_blank` |
diff --git a/src/interfaces/toggle/toggle.story.ts b/src/interfaces/toggle/toggle.story.ts
new file mode 100644
index 0000000000..8f8c867414
--- /dev/null
+++ b/src/interfaces/toggle/toggle.story.ts
@@ -0,0 +1,48 @@
+import { withKnobs, text, color } from '@storybook/addon-knobs';
+import readme from './readme.md';
+import withPadding from '../../../.storybook/decorators/with-padding';
+import { defineComponent, ref } from '@vue/composition-api';
+import RawValue from '../../../.storybook/raw-value.vue';
+
+export default {
+ title: 'Interfaces / Toggle',
+ decorators: [withKnobs, withPadding],
+ parameters: {
+ notes: readme,
+ },
+};
+
+export const basic = () =>
+ defineComponent({
+ components: { RawValue },
+ props: {
+ iconOn: {
+ default: text('Icon (On)', 'check_box'),
+ },
+ iconOff: {
+ default: text('Icon (Off)', 'check_box_outline_blank'),
+ },
+ label: {
+ default: text('Label', 'This is the label'),
+ },
+ color: {
+ default: color('Color', '#2f80ed'),
+ },
+ },
+ setup() {
+ const value = ref(false);
+ return { value };
+ },
+ template: `
+
+
+ {{ value }}
+
+ `,
+ });
diff --git a/src/interfaces/toggle/toggle.test.ts b/src/interfaces/toggle/toggle.test.ts
new file mode 100644
index 0000000000..db2f3d8184
--- /dev/null
+++ b/src/interfaces/toggle/toggle.test.ts
@@ -0,0 +1,20 @@
+import InterfaceToggle from './toggle.vue';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import VueCompositionAPI from '@vue/composition-api';
+import VCheckbox from '@/components/v-checkbox';
+import VIcon from '@/components/v-icon';
+
+const localVue = createLocalVue();
+localVue.use(VueCompositionAPI);
+localVue.component('v-checkbox', VCheckbox);
+localVue.component('v-icon', VIcon);
+
+describe('Interfaces / Toggle', () => {
+ it('Renders a v-checkbox', () => {
+ const component = shallowMount(InterfaceToggle, {
+ localVue,
+ });
+
+ expect(component.find(VCheckbox).exists()).toBe(true);
+ });
+});
diff --git a/src/interfaces/toggle/toggle.vue b/src/interfaces/toggle/toggle.vue
new file mode 100644
index 0000000000..b29f9e391e
--- /dev/null
+++ b/src/interfaces/toggle/toggle.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
diff --git a/src/lang/en-US/index.json b/src/lang/en-US/index.json
index 687f5e71f0..3b396ffe34 100644
--- a/src/lang/en-US/index.json
+++ b/src/lang/en-US/index.json
@@ -280,6 +280,11 @@
"bold": "Bold",
"subdued": "Subdued",
+ "toggle": "Toggle",
+ "icon_on": "Icon (On)",
+ "icon_off": "Icon (Off)",
+ "label": "Label",
+
"about_directus": "About Directus",
"activity_log": "Activity Log",
"add_field_filter": "Add a field filter",