Created smart toggles for limited choice fields

This commit is contained in:
Stefan Zermatten
2023-05-16 19:28:32 +02:00
parent baf99c65b3
commit 2c6cd7d243
8 changed files with 216 additions and 157 deletions

View File

@@ -0,0 +1,70 @@
<template lang="html">
<outlined-input
:name="label"
class="mb-6 pt-1"
>
<v-btn-toggle
v-bind="$attrs"
mandatory
tile
group
:value="safeValue"
color="accent"
style="flex-wrap: wrap;"
>
<v-btn
v-for="(option, i) in options"
:key="`toggle-option-${i}`"
:value="option.value"
:disabled="isDisabled || (clickedValue != option.value && loading)"
:plain="clickedValue != option.value && loading"
:loading="clickedValue == option.value && loading"
height="42"
v-on="(value == option.value) ? {} : { click() { click(option.value) } }"
>
{{ option.name }}
</v-btn>
</v-btn-toggle>
<v-expand-transition>
<div
v-if="errors.length"
class="pa-2 error--text"
>
{{ errors.join('\n\n') }}
</div>
</v-expand-transition>
</outlined-input>
</template>
<script lang="js">
import SmartInput from '/imports/client/ui/components/global/SmartInputMixin.js';
import OutlinedInput from '/imports/client/ui/properties/viewers/shared/OutlinedInput.vue';
export default {
components: {
OutlinedInput,
},
mixins: [SmartInput],
props: {
label: {
type: String,
default: '',
},
options: {
type: Array,
default: () => [],
}
},
data() {
return {
clickedValue: undefined,
};
},
methods: {
click(val) {
this.clickedValue = val;
this.change(val);
},
}
};
</script>

View File

@@ -10,6 +10,7 @@ import SmartBtn from '/imports/client/ui/components/global/SmartBtn.vue';
import SmartCombobox from '/imports/client/ui/components/global/SmartCombobox.vue'; import SmartCombobox from '/imports/client/ui/components/global/SmartCombobox.vue';
import SmartCheckbox from '/imports/client/ui/components/global/SmartCheckbox.vue'; import SmartCheckbox from '/imports/client/ui/components/global/SmartCheckbox.vue';
import SmartSwitch from '/imports/client/ui/components/global/SmartSwitch.vue'; import SmartSwitch from '/imports/client/ui/components/global/SmartSwitch.vue';
import SmartToggle from '/imports/client/ui/components/global/SmartToggle.vue';
import SvgIcon from '/imports/client/ui/components/global/SvgIcon.vue'; import SvgIcon from '/imports/client/ui/components/global/SvgIcon.vue';
import SmartSlider from '/imports/client/ui/components/global/SmartSlider.vue'; import SmartSlider from '/imports/client/ui/components/global/SmartSlider.vue';
@@ -24,4 +25,5 @@ Vue.component('SmartCombobox', SmartCombobox);
Vue.component('SmartCheckbox', SmartCheckbox); Vue.component('SmartCheckbox', SmartCheckbox);
Vue.component('SmartSlider', SmartSlider); Vue.component('SmartSlider', SmartSlider);
Vue.component('SmartSwitch', SmartSwitch); Vue.component('SmartSwitch', SmartSwitch);
Vue.component('SmartToggle', SmartToggle);
Vue.component('SvgIcon', SvgIcon); Vue.component('SvgIcon', SvgIcon);

View File

@@ -63,19 +63,21 @@
/> />
</v-slide-x-transition> </v-slide-x-transition>
<smart-select <smart-toggle
label="Target" label="Target creature"
style="flex-basis: 300px;"
:items="targetOptions"
:value="model.target" :value="model.target"
:options="[
{name: 'Single Target', value: 'singleTarget'},
{name: 'Multiple Targets', value: 'multipleTargets'},
{name: 'Self', value: 'self'},
]"
:error-messages="errors.target" :error-messages="errors.target"
:menu-props="{auto: true, lazy: true}"
@change="change('target', ...arguments)" @change="change('target', ...arguments)"
/> />
<inline-computation-field <inline-computation-field
label="Summary" label="Summary"
hint="This will appear in the action card in the character sheet, summarise what the action does" hint="This will appear in the action card in the character sheet, summarize what the action does"
:model="model.summary" :model="model.summary"
:error-messages="errors.summary" :error-messages="errors.summary"
@change="({path, value, ack}) => @change="({path, value, ack}) =>

View File

@@ -34,11 +34,14 @@
cols="12" cols="12"
md="6" md="6"
> >
<smart-select <smart-toggle
label="Operation" label="Operation"
hint="Should the attribute be damaged by the amount, or set to the amount" hint="Should the attribute be damaged by the amount, or set to the amount"
:items="adjustmentOps"
:value="model.operation" :value="model.operation"
:options="[
{ name: 'Damage', value: 'increment' },
{ name: 'Set', value: 'set' },
]"
:error-messages="errors.operation" :error-messages="errors.operation"
@change="change('operation', ...arguments)" @change="change('operation', ...arguments)"
/> />
@@ -47,14 +50,14 @@
cols="12" cols="12"
md="6" md="6"
> >
<smart-select <smart-toggle
v-if="parentTarget !== 'self'" label="Target creature"
label="Target"
:hint="targetOptionHint"
:items="targetOptions"
:value="model.target" :value="model.target"
:options="[
{name: 'Action Target', value: 'target'},
{name: 'Self', value: 'self'},
]"
:error-messages="errors.target" :error-messages="errors.target"
:menu-props="{auto: true, lazy: true}"
@change="change('target', ...arguments)" @change="change('target', ...arguments)"
/> />
</v-col> </v-col>
@@ -85,58 +88,10 @@ import propertyFormMixin from '/imports/client/ui/properties/forms/shared/proper
export default { export default {
mixins: [propertyFormMixin, attributeListMixin], mixins: [propertyFormMixin, attributeListMixin],
props: {
parentTarget: {
type: String,
default: undefined,
},
},
data() { data() {
return { return {
adjustmentOps: [ damageHint: 'The amount of damage to apply, negative values will heal',
{ text: 'Damage', value: 'increment' }, setHint: 'The value to set the stat to',
{ text: 'Set', value: 'set' },
],
damageHint: 'The amount of damage to apply to the selected stat, can be a calculation or roll. Negative values will restore the selected from previous damage. If the operation is set, this is the final value of the stat instead.',
setHint: 'The value of the stat after applying this adjustment. The stat\'s value can\'t exceed its total',
}
},
computed: {
targetOptions() {
if (this.parentTarget === 'singleTarget') {
return [
{
text: 'Self',
value: 'self',
}, {
text: 'Target',
value: 'every',
},
];
} else {
return [
{
text: 'Self',
value: 'self',
}, {
text: 'Target',
value: 'target',
},
];
}
},
targetOptionHint() {
let hints = {
self: 'The damage will be applied to the character\'s own attribute when taking the action',
target: 'The damage will be applied to the target of the action',
each: 'The damage will be rolled separately for each of the targets of the action',
every: 'The damage will be rolled once and applied to each of the targets of the action',
};
if (this.parentTarget === 'singleTarget') {
hints.each = hints.target;
hints.every = hints.target;
}
return hints[this.model.target];
} }
}, },
} }

View File

@@ -79,90 +79,115 @@
v-if="model.attributeType === 'healthBar'" v-if="model.attributeType === 'healthBar'"
name="Health Bar" name="Health Bar"
> >
<div <div class="d-flex flex-column align-center mb-4">
class="d-flex flex-wrap align-center justify-start" <div class="text-caption mb-4">
> Damaged Colors
<div class="text-subtitle-1">
Damaged Colors:
</div> </div>
<outlined-input <div
name="Half" class="d-flex flex-wrap align-center justify-start"
class="mb-4 ml-2"
> >
<color-picker <outlined-input
:value="model.healthBarColorMid" name="Half"
:width="54" class="mb-4"
:height="54" >
@input="value => $emit('change', {path: ['healthBarColorMid'], value})" <color-picker
/> :value="model.healthBarColorMid"
</outlined-input> :width="54"
<outlined-input :height="54"
name="Empty" @input="value => $emit('change', {path: ['healthBarColorMid'], value})"
class="mb-4 ml-2" />
> </outlined-input>
<color-picker <outlined-input
:value="model.healthBarColorLow" name="Empty"
:width="54" class="mb-4 ml-2"
:height="54" >
@input="value => $emit('change', {path: ['healthBarColorLow'], value})" <color-picker
/> :value="model.healthBarColorLow"
</outlined-input> :width="54"
:height="54"
@input="value => $emit('change', {path: ['healthBarColorLow'], value})"
/>
</outlined-input>
</div>
</div> </div>
<v-layout <v-row dense>
wrap <v-col
class="mt-4" cols="12"
> md="4"
<text-field >
label="Damage order" <text-field
type="number" label="Damage order"
style="max-width: 300px;" type="number"
hint="Lower ordered health bars will take damage before higher ordered ones" hint="Lower ordered health bars will take damage before higher ordered ones"
class="mr-4" :disabled="model.healthBarNoDamage"
:disabled="model.healthBarNoDamage" :value="model.healthBarDamageOrder"
:value="model.healthBarDamageOrder" :error-messages="errors.healthBarDamageOrder"
:error-messages="errors.healthBarDamageOrder" @change="change('healthBarDamageOrder', ...arguments)"
@change="change('healthBarDamageOrder', ...arguments)" />
/> </v-col>
<smart-switch <v-col
label="Ignore damage" cols="12"
class="mr-4" md="4"
:value="model.healthBarNoDamage" sm="6"
:error-messages="errors.healthBarNoDamage" >
@change="change('healthBarNoDamage', ...arguments)" <smart-switch
/> label="Ignore damage"
<smart-switch :value="model.healthBarNoDamage"
label="Prevent damage overflow" :error-messages="errors.healthBarNoDamage"
:value="model.healthBarNoDamageOverflow" @change="change('healthBarNoDamage', ...arguments)"
:error-messages="errors.healthBarNoDamageOverflow" />
@change="change('healthBarNoDamageOverflow', ...arguments)" </v-col>
/> <v-col
</v-layout> cols="12"
<v-layout wrap> md="4"
<text-field sm="6"
label="Healing order" >
type="number" <smart-switch
style="max-width: 300px;" label="Prevent damage overflow"
hint="Lower ordered health bars will take healing before higher ordered ones" :value="model.healthBarNoDamageOverflow"
class="mr-4" :error-messages="errors.healthBarNoDamageOverflow"
:disabled="model.healthBarNoHealing" @change="change('healthBarNoDamageOverflow', ...arguments)"
:value="model.healthBarHealingOrder" />
:error-messages="errors.healthBarHealingOrder" </v-col>
@change="change('healthBarHealingOrder', ...arguments)" <v-col
/> cols="12"
<smart-switch md="4"
label="Ignore healing" >
class="mr-4" <text-field
:value="model.healthBarNoHealing" label="Healing order"
:error-messages="errors.healthBarNoHealing" type="number"
@change="change('healthBarNoHealing', ...arguments)" hint="Lower ordered health bars will take healing before higher ordered ones"
/> :disabled="model.healthBarNoHealing"
<smart-switch :value="model.healthBarHealingOrder"
label="Prevent healing overflow" :error-messages="errors.healthBarHealingOrder"
:value="model.healthBarNoHealingOverflow" @change="change('healthBarHealingOrder', ...arguments)"
:error-messages="errors.healthBarNoHealingOverflow" />
@change="change('healthBarNoHealingOverflow', ...arguments)" </v-col>
/> <v-col
</v-layout> cols="12"
md="4"
sm="6"
>
<smart-switch
label="Ignore healing"
:value="model.healthBarNoHealing"
:error-messages="errors.healthBarNoHealing"
@change="change('healthBarNoHealing', ...arguments)"
/>
</v-col>
<v-col
cols="12"
md="4"
sm="6"
>
<smart-switch
label="Prevent healing overflow"
:value="model.healthBarNoHealingOverflow"
:error-messages="errors.healthBarNoHealingOverflow"
@change="change('healthBarNoHealingOverflow', ...arguments)"
/>
</v-col>
</v-row>
</form-section> </form-section>
</v-expand-transition> </v-expand-transition>
<form-section name="Damage"> <form-section name="Damage">

View File

@@ -18,16 +18,17 @@
$emit('change', {path: ['duration', ...path], value, ack})" $emit('change', {path: ['duration', ...path], value, ack})"
/> />
--> -->
<v-expand-transition> <smart-toggle
<smart-select v-if="!model.applied"
v-if="!model.applied" label="Target creature"
label="Target" :value="model.target"
:items="targetOptions" :options="[
:value="model.target" {name: 'Action Target', value: 'target'},
:error-messages="errors.target" {name: 'Self', value: 'self'},
:menu-props="{auto: true, lazy: true}" ]"
@change="change('target', ...arguments)" :error-messages="errors.target"
/> @change="change('target', ...arguments)"
/>
</v-expand-transition> </v-expand-transition>
<form-sections> <form-sections>
<form-section <form-section

View File

@@ -28,14 +28,12 @@
</template> </template>
<script lang="js"> <script lang="js">
import PropertyIcon from '/imports/client/ui/properties/shared/PropertyIcon.vue';
import ColorPicker from '/imports/client/ui/components/ColorPicker.vue'; import ColorPicker from '/imports/client/ui/components/ColorPicker.vue';
import OutlinedInput from '/imports/client/ui/properties/viewers/shared/OutlinedInput.vue'; import OutlinedInput from '/imports/client/ui/properties/viewers/shared/OutlinedInput.vue';
export default { export default {
components: { components: {
OutlinedInput, OutlinedInput,
PropertyIcon,
ColorPicker, ColorPicker,
}, },
props: { props: {

View File

@@ -49,4 +49,10 @@ export default {
.outlined-input.theme--dark:not(.no-hover):hover { .outlined-input.theme--dark:not(.no-hover):hover {
border-color: #fff; border-color: #fff;
} }
.outlined-input .name {
color: rgba(0,0,0,.6);
}
.outlined-input.theme--dark .name {
color: rgba(255,255,255,.7);
}
</style> </style>