disabled state + activation animation

This commit is contained in:
Henry Jameson 2025-01-12 16:34:16 +02:00
parent a89a21c3ef
commit 17917932a0
4 changed files with 64 additions and 13 deletions

View file

@ -65,7 +65,6 @@
grid-template-columns: 1fr var(--__line-height); grid-template-columns: 1fr var(--__line-height);
grid-auto-flow: column; grid-auto-flow: column;
grid-auto-columns: auto; grid-auto-columns: auto;
cursor: pointer;
.menu-checkbox { .menu-checkbox {
display: inline-block; display: inline-block;
@ -102,4 +101,18 @@
.dropdown-item-icon:not(button, a) > a:first-child { .dropdown-item-icon:not(button, a) > a:first-child {
grid-template-columns: var(--__line-height) 1fr; grid-template-columns: var(--__line-height) 1fr;
} }
a.dropdown-item:not(.disabled),
button.dropdown:not(.disabled),
.dropdown-item:not(.disabled, button, a) > button:first-child,
.dropdown-item:not(.disabled, button, a) > a:first-child {
cursor: pointer;
}
a.dropdown-item.disabled,
button.dropdown.disabled,
.dropdown-item.disabled:not(button, a) > button:first-child,
.dropdown-item.disabled:not(button, a) > a:first-child {
cursor: not-allowed;
}
} }

View file

@ -86,7 +86,7 @@ const BUTTONS = [{
active: ({ status }) => status.repeated, active: ({ status }) => status.repeated,
counter: ({ status }) => status.repeat_num, counter: ({ status }) => status.repeat_num,
anonLink: true, anonLink: true,
interactive: ({ status }) => !PRIVATE_SCOPES.has(status.visibility), interactive: ({ status, loggedIn }) => loggedIn && !PRIVATE_SCOPES.has(status.visibility),
toggleable: true, toggleable: true,
confirm: ({ status, getters }) => !status.repeated && getters.mergedConfig.modalOnRepeat, confirm: ({ status, getters }) => !status.repeated && getters.mergedConfig.modalOnRepeat,
confirmStrings: { confirmStrings: {
@ -284,6 +284,10 @@ const StatusActionButtons = {
emits: ['toggleReplying'], emits: ['toggleReplying'],
data () { data () {
return { return {
animationState: {
retweet: false,
favorite: false
},
showPin: false, showPin: false,
showingConfirmDialog: false, showingConfirmDialog: false,
currentConfirmTitle: '', currentConfirmTitle: '',
@ -353,9 +357,11 @@ const StatusActionButtons = {
} }
}, },
doActionReal (button) { doActionReal (button) {
this.animationState[button.name] = true
button.action(this.funcArg) button.action(this.funcArg)
.then(() => this.$emit('onSuccess')) .then(() => this.$emit('onSuccess'))
.catch(err => this.$emit('onError', err.error.error)) .catch(err => this.$emit('onError', err.error.error))
.finally(() => setTimeout(() => { this.animationState[button.name] = false }))
}, },
isPinned (button) { isPinned (button) {
console.log(this.pinnedItems, button.name) console.log(this.pinnedItems, button.name)
@ -381,10 +387,10 @@ const StatusActionButtons = {
getClass (button) { getClass (button) {
return { return {
[button.name + '-button']: true, [button.name + '-button']: true,
disabled: button.interactive ? !button.interactive(this.funcArg) : false,
'-pin-edit': this.showPin, '-pin-edit': this.showPin,
'-dropdown': button.dropdown?.(), '-dropdown': button.dropdown?.(),
'-active': button.active?.(this.funcArg), '-active': button.active?.(this.funcArg)
'-interactive': !!this.$store.state.users.currentUser
} }
}, },
getRemoteInteractionLink () { getRemoteInteractionLink () {

View file

@ -18,6 +18,10 @@
grid-template-columns: max-content auto; grid-template-columns: max-content auto;
grid-gap: 1em; grid-gap: 1em;
align-items: center; align-items: center;
&.disabled {
cursor: not-allowed;
}
} }
&.-pin { &.-pin {
@ -32,7 +36,7 @@
grid-template-columns: 1fr max-content; grid-template-columns: 1fr max-content;
} }
.reply-button { .reply-button:not(.disabled) {
&:hover, &:hover,
&.-active { &.-active {
.svg-inline--fa { .svg-inline--fa {
@ -41,7 +45,7 @@
} }
} }
.retweet-button { .retweet-button:not(.disabled) {
&:hover, &:hover,
&.-active { &.-active {
.svg-inline--fa { .svg-inline--fa {
@ -50,7 +54,7 @@
} }
} }
.favorite-button { .favorite-button:not(.disabled) {
&:hover, &:hover,
&.-active { &.-active {
.svg-inline--fa { .svg-inline--fa {
@ -103,7 +107,30 @@
} }
} }
.reply-button { > a,
> button {
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include focused-style {
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
.reply-button:not(.disabled) {
&:hover, &:hover,
&.-active { &.-active {
.svg-inline--fa { .svg-inline--fa {
@ -112,7 +139,7 @@
} }
} }
.retweet-button { .retweet-button:not(.disabled) {
&:hover, &:hover,
&.-active { &.-active {
.svg-inline--fa { .svg-inline--fa {
@ -121,7 +148,7 @@
} }
} }
.favorite-button { .favorite-button:not(.disabled) {
&:hover, &:hover,
&.-active { &.-active {
.svg-inline--fa { .svg-inline--fa {

View file

@ -11,6 +11,7 @@
:is="component(button)" :is="component(button)"
class="button-unstyled action-button" class="button-unstyled action-button"
:class="getClass(button)" :class="getClass(button)"
:disabled="getClass(button).disabled"
role="button" role="button"
:tabindex="0" :tabindex="0"
:title="$t(button.label(funcArg))" :title="$t(button.label(funcArg))"
@ -22,7 +23,7 @@
class="fa-scale-110" class="fa-scale-110"
:icon="button.icon(funcArg)" :icon="button.icon(funcArg)"
/> />
<template v-if="button.toggleable?.(funcArg) && button.active"> <template v-if="!getClass(button).disabled && button.toggleable?.(funcArg) && button.active">
<FAIcon <FAIcon
v-if="button.active(funcArg)" v-if="button.active(funcArg)"
class="active-marker" class="active-marker"
@ -107,6 +108,8 @@
v-for="button in extraButtons" v-for="button in extraButtons"
:key="button.name" :key="button.name"
class="menu-item dropdown-item extra-action dropdown-item-icon" class="menu-item dropdown-item extra-action dropdown-item-icon"
:disabled="getClass(button).disabled"
:class="{ disabled: getClass(button).disabled }"
> >
<component <component
:is="component(button)" :is="component(button)"
@ -114,6 +117,7 @@
role="menuitem" role="menuitem"
:class="getClass(button)" :class="getClass(button)"
:tabindex="0" :tabindex="0"
:disabled="getClass(button).disabled"
@click.stop="component(button) === 'button' && doAction(button)" @click.stop="component(button) === 'button' && doAction(button)"
@click="close" @click="close"
:href="component(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined" :href="component(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined"
@ -122,9 +126,10 @@
<FAIcon <FAIcon
class="fa-scale-110" class="fa-scale-110"
:icon="button.icon(funcArg)" :icon="button.icon(funcArg)"
:spin="button.animated?.() && animationState[button.name]"
fixed-width fixed-width
/> />
<template v-if="button.toggleable?.(funcArg) && button.active"> <template v-if="!getClass(button).disabled && button.toggleable?.(funcArg) && button.active">
<FAIcon <FAIcon
v-if="button.active(funcArg)" v-if="button.active(funcArg)"
class="active-marker" class="active-marker"
@ -150,7 +155,7 @@
v-if="showPin && currentUser" v-if="showPin && currentUser"
type="button" type="button"
class="button-unstyled pin-action-button" class="button-unstyled pin-action-button"
:title="$t('general.pin' )" :title="$t('general.pin')"
:aria-pressed="false" :aria-pressed="false"
@click.stop.prevent="pin(button)" @click.stop.prevent="pin(button)"
> >