commit: 17917932a032e1feb2798738b69a846069dcf826
parent a89a21c3ef3bd3cfb68d5810f416cacb02dff4d6
Author: Henry Jameson <me@hjkos.com>
Date: Sun, 12 Jan 2025 16:34:16 +0200
disabled state + activation animation
Diffstat:
4 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/src/components/popover/popover.scss b/src/components/popover/popover.scss
@@ -65,7 +65,6 @@
grid-template-columns: 1fr var(--__line-height);
grid-auto-flow: column;
grid-auto-columns: auto;
- cursor: pointer;
.menu-checkbox {
display: inline-block;
@@ -102,4 +101,18 @@
.dropdown-item-icon:not(button, a) > a:first-child {
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;
+ }
}
diff --git a/src/components/status_action_buttons/status_action_buttons.js b/src/components/status_action_buttons/status_action_buttons.js
@@ -86,7 +86,7 @@ const BUTTONS = [{
active: ({ status }) => status.repeated,
counter: ({ status }) => status.repeat_num,
anonLink: true,
- interactive: ({ status }) => !PRIVATE_SCOPES.has(status.visibility),
+ interactive: ({ status, loggedIn }) => loggedIn && !PRIVATE_SCOPES.has(status.visibility),
toggleable: true,
confirm: ({ status, getters }) => !status.repeated && getters.mergedConfig.modalOnRepeat,
confirmStrings: {
@@ -284,6 +284,10 @@ const StatusActionButtons = {
emits: ['toggleReplying'],
data () {
return {
+ animationState: {
+ retweet: false,
+ favorite: false
+ },
showPin: false,
showingConfirmDialog: false,
currentConfirmTitle: '',
@@ -353,9 +357,11 @@ const StatusActionButtons = {
}
},
doActionReal (button) {
+ this.animationState[button.name] = true
button.action(this.funcArg)
.then(() => this.$emit('onSuccess'))
.catch(err => this.$emit('onError', err.error.error))
+ .finally(() => setTimeout(() => { this.animationState[button.name] = false }))
},
isPinned (button) {
console.log(this.pinnedItems, button.name)
@@ -381,10 +387,10 @@ const StatusActionButtons = {
getClass (button) {
return {
[button.name + '-button']: true,
+ disabled: button.interactive ? !button.interactive(this.funcArg) : false,
'-pin-edit': this.showPin,
'-dropdown': button.dropdown?.(),
- '-active': button.active?.(this.funcArg),
- '-interactive': !!this.$store.state.users.currentUser
+ '-active': button.active?.(this.funcArg)
}
},
getRemoteInteractionLink () {
diff --git a/src/components/status_action_buttons/status_action_buttons.scss b/src/components/status_action_buttons/status_action_buttons.scss
@@ -18,6 +18,10 @@
grid-template-columns: max-content auto;
grid-gap: 1em;
align-items: center;
+
+ &.disabled {
+ cursor: not-allowed;
+ }
}
&.-pin {
@@ -32,7 +36,7 @@
grid-template-columns: 1fr max-content;
}
- .reply-button {
+ .reply-button:not(.disabled) {
&:hover,
&.-active {
.svg-inline--fa {
@@ -41,7 +45,7 @@
}
}
- .retweet-button {
+ .retweet-button:not(.disabled) {
&:hover,
&.-active {
.svg-inline--fa {
@@ -50,7 +54,7 @@
}
}
- .favorite-button {
+ .favorite-button:not(.disabled) {
&:hover,
&.-active {
.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,
&.-active {
.svg-inline--fa {
@@ -112,7 +139,7 @@
}
}
- .retweet-button {
+ .retweet-button:not(.disabled) {
&:hover,
&.-active {
.svg-inline--fa {
@@ -121,7 +148,7 @@
}
}
- .favorite-button {
+ .favorite-button:not(.disabled) {
&:hover,
&.-active {
.svg-inline--fa {
diff --git a/src/components/status_action_buttons/status_action_buttons.vue b/src/components/status_action_buttons/status_action_buttons.vue
@@ -11,6 +11,7 @@
:is="component(button)"
class="button-unstyled action-button"
:class="getClass(button)"
+ :disabled="getClass(button).disabled"
role="button"
:tabindex="0"
:title="$t(button.label(funcArg))"
@@ -22,7 +23,7 @@
class="fa-scale-110"
:icon="button.icon(funcArg)"
/>
- <template v-if="button.toggleable?.(funcArg) && button.active">
+ <template v-if="!getClass(button).disabled && button.toggleable?.(funcArg) && button.active">
<FAIcon
v-if="button.active(funcArg)"
class="active-marker"
@@ -107,6 +108,8 @@
v-for="button in extraButtons"
:key="button.name"
class="menu-item dropdown-item extra-action dropdown-item-icon"
+ :disabled="getClass(button).disabled"
+ :class="{ disabled: getClass(button).disabled }"
>
<component
:is="component(button)"
@@ -114,6 +117,7 @@
role="menuitem"
:class="getClass(button)"
:tabindex="0"
+ :disabled="getClass(button).disabled"
@click.stop="component(button) === 'button' && doAction(button)"
@click="close"
:href="component(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined"
@@ -122,9 +126,10 @@
<FAIcon
class="fa-scale-110"
:icon="button.icon(funcArg)"
+ :spin="button.animated?.() && animationState[button.name]"
fixed-width
/>
- <template v-if="button.toggleable?.(funcArg) && button.active">
+ <template v-if="!getClass(button).disabled && button.toggleable?.(funcArg) && button.active">
<FAIcon
v-if="button.active(funcArg)"
class="active-marker"
@@ -150,7 +155,7 @@
v-if="showPin && currentUser"
type="button"
class="button-unstyled pin-action-button"
- :title="$t('general.pin' )"
+ :title="$t('general.pin')"
:aria-pressed="false"
@click.stop.prevent="pin(button)"
>