Skip to content

Commit 846ccd4

Browse files
authored
Merge pull request #8047 from nextcloud-libraries/backport/8045/stable8
[stable8] fix: animate toggle switch icon
2 parents 253e2ee + f227c7b commit 846ccd4

File tree

4 files changed

+80
-25
lines changed

4 files changed

+80
-25
lines changed

src/components/NcCheckboxRadioSwitch/NcCheckboxContent.vue

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
:checked="isChecked"
3333
:loading="loading">
3434
<NcLoadingIcon v-if="loading" />
35+
<NcIconToggleSwitch
36+
v-else-if="isSwitchType"
37+
:checked="isChecked"
38+
:size="iconSize"
39+
inline />
3540
<component
3641
:is="checkboxRadioIconElement"
3742
v-else-if="!buttonVariant"
@@ -61,8 +66,7 @@ import CheckboxMarked from 'vue-material-design-icons/CheckboxMarked.vue'
6166
import MinusBox from 'vue-material-design-icons/MinusBox.vue'
6267
import RadioboxBlank from 'vue-material-design-icons/RadioboxBlank.vue'
6368
import RadioboxMarked from 'vue-material-design-icons/RadioboxMarked.vue'
64-
import ToggleSwitch from 'vue-material-design-icons/ToggleSwitch.vue'
65-
import ToggleSwitchOff from 'vue-material-design-icons/ToggleSwitchOff.vue'
69+
import NcIconToggleSwitch from '../NcIconToggleSwitch/NcIconToggleSwitch.vue'
6670
import NcLoadingIcon from '../NcLoadingIcon/index.js'
6771
6872
export const TYPE_CHECKBOX = 'checkbox'
@@ -75,6 +79,7 @@ export default {
7579
7680
components: {
7781
NcLoadingIcon,
82+
NcIconToggleSwitch,
7883
},
7984
8085
props: {
@@ -175,6 +180,10 @@ export default {
175180
return this.type === TYPE_BUTTON
176181
},
177182
183+
isSwitchType() {
184+
return this.type === TYPE_SWITCH
185+
},
186+
178187
/**
179188
* Returns the proper Material icon depending on the select case
180189
*
@@ -188,14 +197,6 @@ export default {
188197
return RadioboxBlank
189198
}
190199
191-
// Switch
192-
if (this.type === TYPE_SWITCH) {
193-
if (this.isChecked) {
194-
return ToggleSwitch
195-
}
196-
return ToggleSwitchOff
197-
}
198-
199200
// Checkbox
200201
if (this.indeterminate) {
201202
return MinusBox
@@ -240,6 +241,7 @@ export default {
240241
&-radio:not(&--button-variant) &__icon,
241242
&-switch:not(&--button-variant) &__icon {
242243
margin-block: calc((var(--default-clickable-area) - 2 * var(--default-grid-baseline) - var(--icon-height)) / 2) auto;
244+
line-height: 0;
243245
}
244246
245247
&-checkbox:not(&--button-variant) &__icon--has-description,

src/components/NcFormBoxSwitch/NcFormBoxSwitch.vue

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@ export default {
1313
</script>
1414

1515
<script setup lang="ts">
16-
import { mdiToggleSwitch, mdiToggleSwitchOff } from '@mdi/js'
1716
import { useVModel } from '@vueuse/core'
1817
import { watch } from 'vue'
1918
import NcFormBoxItem from '../NcFormBox/NcFormBoxItem.vue'
20-
import NcIconSvgWrapper from '../NcIconSvgWrapper/NcIconSvgWrapper.vue'
19+
import NcIconToggleSwitch from '../NcIconToggleSwitch/NcIconToggleSwitch.vue'
2120
import { createElementId } from '../../utils/createElementId.ts'
2221
2322
const props = withDefaults(defineProps<{
@@ -85,11 +84,7 @@ watch(model, () => {
8584
role="switch"
8685
:aria-describedby="descriptionId"
8786
:disabled="disabled">
88-
<NcIconSvgWrapper
89-
:path="model ? mdiToggleSwitch : mdiToggleSwitchOff"
90-
:class="$style.formBoxSwitch__icon"
91-
:size="34 /* --default-clickable-area */"
92-
inline />
87+
<NcIconToggleSwitch :checked="modelValue" inline />
9388
</template>
9489
</NcFormBoxItem>
9590
</template>
@@ -108,14 +103,6 @@ input.formBoxSwitch__input {
108103
height: auto;
109104
cursor: inherit;
110105
}
111-
112-
.formBoxSwitch__icon {
113-
color: var(--color-text-maxcontrast);
114-
}
115-
116-
input:checked + .formBoxSwitch__icon {
117-
color: var(--color-primary-element);
118-
}
119106
</style>
120107

121108
<docs>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
6+
<script lang="ts">
7+
const svg = `<svg
8+
xmlns="http://www.w3.org/2000/svg"
9+
viewBox="0 0 24 12">
10+
<path d="M17,1H7A5,5 0 0,0 2,6 5,5 0 0,0 7,11H17A5,5 0 0,0 22,6 5,5 0 0,0 17,1Z" />
11+
<circle
12+
cy="6"
13+
r="3"
14+
fill="var(--color-main-background)" />
15+
</svg>`
16+
</script>
17+
18+
<script setup lang="ts">
19+
import { computed } from 'vue'
20+
import NcIconSvgWrapper from '../NcIconSvgWrapper/NcIconSvgWrapper.vue'
21+
22+
const props = withDefaults(defineProps<{
23+
/** Whether the toggle switch is checked */
24+
checked: boolean
25+
/** Size of the icon */
26+
size?: number
27+
/** NcIconSvgWrapper's inline prop */
28+
inline?: boolean
29+
}>(), {
30+
size: 34,
31+
inline: false,
32+
})
33+
34+
const color = computed(() => props.checked ? 'var(--color-primary-element)' : 'var(--color-text-maxcontrast)')
35+
const cx = computed(() => props.checked ? 'calc(17 / 24 * 100%)' : 'calc(7 / 24 * 100%)')
36+
</script>
37+
38+
<template>
39+
<NcIconSvgWrapper
40+
:class="$style.iconToggleSwitch"
41+
:svg="svg"
42+
:size="size"
43+
:inline="inline" />
44+
</template>
45+
46+
<style module lang="scss">
47+
.iconToggleSwitch {
48+
color: v-bind(color);
49+
transition: color var(--animation-quick) ease;
50+
51+
svg {
52+
/* Unlike other icons, this icon is not a square */
53+
height: auto !important;
54+
}
55+
56+
circle {
57+
cx: v-bind(cx);
58+
transition: cx var(--animation-quick) ease;
59+
}
60+
}
61+
</style>
62+
63+
<docs>
64+
Private component
65+
</docs>

styleguide.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ module.exports = async () => {
211211
'src/components/NcTextArea/*.vue',
212212
'src/components/NcPopover/NcPopoverTriggerProvider.vue',
213213
'src/components/NcFormBox/NcFormBoxItem.vue',
214+
'src/components/NcIconToggleSwitch/NcIconToggleSwitch.vue',
214215
],
215216
sections: [
216217
{

0 commit comments

Comments
 (0)