Implemented ToggleButton

pull/7319/merge
Cagatay Civici 2025-03-01 23:47:05 +03:00
parent ee0e002e26
commit fbce6895bb
10 changed files with 277 additions and 1 deletions

View File

@ -42,6 +42,10 @@
"name": "Timeline",
"to": "/timeline"
},
{
"name": "ToggleButton",
"to": "/togglebutton"
},
{
"name": "ToggleSwitch",
"to": "/toggleswitch"

View File

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

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Icons and Labels can be customized using <i>onLabel</i>, <i>offLabel</i>, <i>onIcon</i> and <i>offIcon</i> properties.</p>
</DocSectionText>
<div class="card flex justify-center">
<ToggleButton v-model="checked" onLabel="Locked" offLabel="Unlocked" onIcon="pi pi-lock" offIcon="pi pi-lock-open" class="w-36" aria-label="Do you confirm" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleButton v-model="checked" onLabel="Locked" offLabel="Unlocked" onIcon="pi pi-lock" offIcon="pi pi-lock-open" class="w-36" aria-label="Do you confirm" />
</div>
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
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">
<ToggleButton v-model="checked" disabled onIcon="pi pi-check" offIcon="pi pi-times" class="w-full sm:w-40" aria-label="Confirmation" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleButton v-model="checked" disabled onIcon="pi pi-check" offIcon="pi pi-times" class="w-full sm:w-40" aria-label="Confirmation" />
</div>
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
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 ToggleButton from '@/plex/togglebutton';
`
};
}
};
</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">
<ToggleButton v-model="checked" onIcon="pi pi-check" offIcon="pi pi-times" :invalid="!checked" class="w-full sm:w-40" aria-label="Confirmation" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<ToggleButton v-model="checked" onIcon="pi pi-check" offIcon="pi pi-times" :invalid="!checked" class="w-full sm:w-40" aria-label="Confirmation" />
</div>
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,39 @@
<template>
<DocSectionText v-bind="$attrs">
<p>ToggleButton provides <i>small</i> and <i>large</i> sizes as alternatives to the base.</p>
</DocSectionText>
<div class="card flex flex-col items-center gap-4">
<ToggleButton v-model="checked1" onLabel="On" offLabel="Off" size="small" class="min-w-16" />
<ToggleButton v-model="checked2" onLabel="On" offLabel="Off" class="min-w-20" />
<ToggleButton v-model="checked3" onLabel="On" offLabel="Off" size="large" class="min-w-24" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
import { ref } from 'vue';
const checked1 = ref(false);
const checked2 = ref(false);
const checked3 = ref(false);
const code = ref(`
<template>
<div class="card flex flex-col items-center gap-4">
<ToggleButton v-model="value1" onLabel="On" offLabel="Off" size="small" class="min-w-16" />
<ToggleButton v-model="value2" onLabel="On" offLabel="Off" class="min-w-20" />
<ToggleButton v-model="value3" onLabel="On" offLabel="Off" size="large" class="min-w-24" />
</div>
</template>
<script setup>
import ToggleButton from '@/plex/togglebutton';
import { ref } from 'vue';
const checked1 = ref(false);
const checked2 = ref(false);
const checked3 = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,51 @@
<template>
<DocComponent title="Vue ToggleButton Component" header="ToggleButton" description="ToggleButton is used to select a boolean value using a button." :componentDocs="docs" />
</template>
<script>
import BasicDoc from '@/doc/togglebutton/BasicDoc.vue';
import CustomizedDoc from '@/doc/togglebutton/CustomizedDoc.vue';
import DisabledDoc from '@/doc/togglebutton/DisabledDoc.vue';
import ImportDoc from '@/doc/togglebutton/ImportDoc.vue';
import InvalidDoc from '@/doc/togglebutton/InvalidDoc.vue';
import SizesDoc from '@/doc/togglebutton/SizesDoc.vue';
export default {
data() {
return {
docs: [
{
id: 'import',
label: 'Import',
component: ImportDoc
},
{
id: 'basic',
label: 'Basic',
component: BasicDoc
},
{
id: 'customized',
label: 'Customized',
component: CustomizedDoc
},
{
id: 'sizes',
label: 'Sizes',
component: SizesDoc
},
{
id: 'invalid',
label: 'Invalid',
component: InvalidDoc
},
{
id: 'disabled',
label: 'Disabled',
component: DisabledDoc
}
]
};
}
};
</script>

View File

@ -0,0 +1,33 @@
<template>
<ToggleButton unstyled :pt="theme">
<template v-for="(_, slotName) in $slots" v-slot:[slotName]="slotProps">
<slot :name="slotName" v-bind="slotProps ?? {}" />
</template>
</ToggleButton>
</template>
<script setup>
import { ref } from 'vue';
const theme = ref({
root: `inline-flex items-center justify-center overflow-hidden relative cursor-pointer select-none
border border-surface-100 dark:border-surface-950 rounded-md
bg-surface-100 dark:bg-surface-950
text-surface-500 dark:text-surface-400
p-checked:text-surface-700 dark:p-checked:text-surface-0
text-base font-medium
focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
disabled:cursor-default
disabled:bg-surface-200 disabled:border-surface-200 disabled:text-surface-500
disabled:dark:bg-surface-700 disabled:dark:border-surface-700 disabled:dark:text-surface-400
p-invalid:border-red-400 dark:p-invalid:border-red-300
transition-colors duration-200
p-1 p-small:text-sm p-large:text-lg
`,
content: `relative flex-auto inline-flex items-center justify-center gap-2 py-1 px-3
rounded-md transition-colors duration-200
p-checked:bg-surface-0 dark:p-checked:bg-surface-800 p-checked:shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02),0px_1px_2px_0px_rgba(0,0,0,0.04)]`,
icon: ``,
label: ``
});
</script>

View File

@ -13,8 +13,9 @@
:aria-labelledby="ariaLabelledby"
:data-p-checked="active"
:data-p-disabled="disabled"
:data-p="dataP"
>
<span :class="cx('content')" v-bind="getPTOptions('content')">
<span :class="cx('content')" v-bind="getPTOptions('content')" :data-p="dataP">
<slot>
<slot name="icon" :value="d_value" :class="cx('icon')">
<span v-if="onIcon || offIcon" :class="[cx('icon'), d_value ? onIcon : offIcon]" v-bind="getPTOptions('icon')" />
@ -26,6 +27,7 @@
</template>
<script>
import { cn } from '@primeuix/utils';
import { isNotEmpty } from '@primeuix/utils/object';
import Ripple from 'primevue/ripple';
import BaseToggleButton from './BaseToggleButton.vue';
@ -65,6 +67,13 @@ export default {
},
label() {
return this.hasLabel ? (this.d_value ? this.onLabel : this.offLabel) : '\u00A0';
},
dataP() {
return cn({
checked: this.active,
invalid: this.$invalid,
[this.size]: this.size
});
}
},
directives: {