Implemented ToggleSwitch

pull/7319/merge
Cagatay Civici 2025-03-01 19:44:31 +03:00
parent b340affb9a
commit b846d84214
12 changed files with 278 additions and 4 deletions

View File

@ -33,6 +33,10 @@
{ {
"name": "Textarea", "name": "Textarea",
"to": "/textarea" "to": "/textarea"
},
{
"name": "ToggleSwitch",
"to": "/toggleswitch"
} }
] ]
}, },

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>ToggleSwitch is used with the <i>v-model</i> property for two-way value binding.</p>
</DocSectionText>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" />
</div>
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>When <i>disabled</i> is present, the element cannot be edited and focused.</p>
</DocSectionText>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" disabled />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" disabled />
</div>
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,16 @@
<template>
<DocSectionText v-bind="$attrs" />
<DocSectionCode :code="code" lang="script" />
</template>
<script>
export default {
data() {
return {
code: `
import ToggleSwitch from '@/plex/toggleswitch';
`
};
}
};
</script>

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Invalid state is displayed using the <i>invalid</i> prop to indicate a failed validation. You can use this style when integrating with form validation libraries.</p>
</DocSectionText>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" :invalid="!checked" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" :invalid="!checked" />
</div>
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Enabling <i>checked</i> property displays the component as active initially.</p>
</DocSectionText>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(true);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked" />
</div>
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(true);
<\/script>
`);
</script>

View File

@ -0,0 +1,39 @@
<template>
<DocSectionText v-bind="$attrs">
<p>The <i>handle</i> slot is available to display custom content.</p>
</DocSectionText>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked">
<template #handle="{ checked }">
<i :class="['!text-xs pi', { 'pi-check': checked, 'pi-times': !checked }]" />
</template>
</ToggleSwitch>
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleSwitch v-model="checked">
<template #handle="{ checked }">
<i :class="['!text-xs pi', { 'pi-check': checked, 'pi-times': !checked }]" />
</template>
</ToggleSwitch>
</div>
</template>
<script setup>
import ToggleSwitch from '@/plex/toggleswitch';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,46 @@
<template>
<DocComponent title="Vue ToggleSwitch Component" header="ToggleSwitch" description="ToggleSwitch is used to select a boolean value." :componentDocs="docs" />
</template>
<script setup>
import BasicDoc from '@/doc/toggleswitch/BasicDoc.vue';
import DisabledDoc from '@/doc/toggleswitch/DisabledDoc.vue';
import ImportDoc from '@/doc/toggleswitch/ImportDoc.vue';
import InvalidDoc from '@/doc/toggleswitch/InvalidDoc.vue';
import PreselectionDoc from '@/doc/toggleswitch/PreselectionDoc.vue';
import TemplateDoc from '@/doc/toggleswitch/TemplateDoc.vue';
import { ref } from 'vue';
const docs = ref([
{
id: 'import',
label: 'Import',
component: ImportDoc
},
{
id: 'basic',
label: 'Basic',
component: BasicDoc
},
{
id: 'preselection',
label: 'Preselection',
component: PreselectionDoc
},
{
id: 'invalid',
label: 'Invalid',
component: InvalidDoc
},
{
id: 'template',
label: 'Template',
component: TemplateDoc
},
{
id: 'disabled',
label: 'Disabled',
component: DisabledDoc
}
]);
</script>

View File

@ -0,0 +1,34 @@
<template>
<ToggleSwitch unstyled :pt="theme">
<template v-for="(_, slotName) in $slots" v-slot:[slotName]="slotProps">
<slot :name="slotName" v-bind="slotProps ?? {}" />
</template>
</ToggleSwitch>
</template>
<script setup>
import ToggleSwitch from 'primevue/toggleswitch';
import { ref } from 'vue';
const theme = ref({
root: `inline-block w-10 h-6`,
input: `peer cursor-pointer disabled:cursor-default appearance-none absolute top-0 start-0 w-full h-full m-0 p-0 opacity-0 z-10 rounded-[30px]`,
slider: `inline-block w-full h-full rounded-[30px] shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
bg-surface-300 dark:bg-surface-700
border border-transparent
transition-colors duration-200
peer-enabled:peer-hover:bg-surface-400 dark:peer-enabled:peer-hover:bg-surface-600
p-checked:bg-primary peer-enabled:peer-hover:p-checked:bg-primary-emphasis
p-invalid:border-red-400 dark:p-invalid:border-red-300
p-disabled:bg-surface-200 dark:p-disabled:bg-surface-600
peer-focus-visible:outline peer-focus-visible:outline-1 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-primary`,
handle: `absolute top-1/2 flex justify-center items-center
bg-surface-0 dark:bg-surface-400
text-surface-500 dark:text-surface-900
w-4 h-4 start-1 -mt-2 rounded-full
transition-[background,color,left] duration-200
p-checked:bg-surface-0 dark:p-checked:bg-surface-900 p-checked:text-primary p-checked:start-5
p-disabled:bg-surface-700 dark:p-disabled:bg-surface-900
}`
});
</script>

View File

@ -15,6 +15,9 @@ export default {
addVariant('p-filled', '&[data-p~="filled"]'); addVariant('p-filled', '&[data-p~="filled"]');
addVariant('p-horizontal', '&[data-p~="horizontal"]'); addVariant('p-horizontal', '&[data-p~="horizontal"]');
addVariant('p-vertical', '&[data-p~="vertical"]'); addVariant('p-vertical', '&[data-p~="vertical"]');
addVariant('p-checked', '&[data-p~="checked"]');
addVariant('p-disabled', '&[data-p~="disabled"]');
addVariant('p-enabled', '&:not([data-p~="disabled"])');
}) })
], ],
theme: { theme: {

View File

@ -2,7 +2,7 @@
<DocSectionText v-bind="$attrs"> <DocSectionText v-bind="$attrs">
<p>The <i>handle</i> slot is available to display custom content.</p> <p>The <i>handle</i> slot is available to display custom content.</p>
</DocSectionText> </DocSectionText>
<div class="card flex justify-center gap-4"> <div class="card flex justify-center">
<ToggleSwitch v-model="checked"> <ToggleSwitch v-model="checked">
<template #handle="{ checked }"> <template #handle="{ checked }">
<i :class="['!text-xs pi', { 'pi-check': checked, 'pi-times': !checked }]" /> <i :class="['!text-xs pi', { 'pi-check': checked, 'pi-times': !checked }]" />

View File

@ -1,5 +1,5 @@
<template> <template>
<div :class="cx('root')" :style="sx('root')" v-bind="getPTOptions('root')" :data-p-checked="checked" :data-p-disabled="disabled"> <div :class="cx('root')" :style="sx('root')" v-bind="getPTOptions('root')" :data-p-checked="checked" :data-p-disabled="disabled" :data-p="dataP">
<input <input
:id="inputId" :id="inputId"
type="checkbox" type="checkbox"
@ -19,8 +19,8 @@
@change="onChange" @change="onChange"
v-bind="getPTOptions('input')" v-bind="getPTOptions('input')"
/> />
<div :class="cx('slider')" v-bind="getPTOptions('slider')"> <div :class="cx('slider')" v-bind="getPTOptions('slider')" :data-p="dataP">
<div :class="cx('handle')" v-bind="getPTOptions('handle')"> <div :class="cx('handle')" v-bind="getPTOptions('handle')" :data-p="dataP">
<slot name="handle" :checked="checked" /> <slot name="handle" :checked="checked" />
</div> </div>
</div> </div>
@ -28,6 +28,7 @@
</template> </template>
<script> <script>
import { cn } from '@primeuix/utils';
import BaseToggleSwitch from './BaseToggleSwitch.vue'; import BaseToggleSwitch from './BaseToggleSwitch.vue';
export default { export default {
@ -65,6 +66,13 @@ export default {
computed: { computed: {
checked() { checked() {
return this.d_value === this.trueValue; return this.d_value === this.trueValue;
},
dataP() {
return cn({
checked: this.checked,
disabled: this.disabled,
invalid: this.$invalid
});
} }
} }
}; };