mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Fixed Skill Layout (#12776)
* Fixed Skill Layout * Fixed skill layout reponsiveness * Fixed collapsing of drawer container * Fixed skill card disabled state, extra white border and hover sstate * Fixed task / member selection style * Fixed few changes * Fixed extra padding and box shadow * Fixed box shadow and added popover component * Fixed disabled state issue * Fixed styles and skill card issues * Fixed style issues * Fixed style issue * Fixed lint error * Fixed space between drawer class * Fixed border issue * Fixed round border issue * Fixed Mage issue * auto eslint fixes * use translated string and computed property, reorganize css * perf: reduce calculated classes, throttle mouse moved event Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
This commit is contained in:
@@ -104,9 +104,9 @@
|
||||
:variant="'success'"
|
||||
>
|
||||
<b-dropdown-item
|
||||
class="selectListItem"
|
||||
v-for="type in columns"
|
||||
:key="type"
|
||||
class="selectListItem"
|
||||
@click="createTask(type)"
|
||||
>{{ $t(type) }}</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
|
||||
@@ -43,23 +43,32 @@
|
||||
>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select-list :items="sortOptions"
|
||||
@select="changeSortOption($event)"
|
||||
<select-list
|
||||
:items="sortOptions"
|
||||
:value="optionEntryBySelectedValue"
|
||||
key-prop="value">
|
||||
key-prop="value"
|
||||
@select="changeSortOption($event)"
|
||||
>
|
||||
<template v-slot:item="{ item }">
|
||||
<span class="label" v-if="item">{{ item.text }}</span>
|
||||
<span
|
||||
v-if="item"
|
||||
class="label"
|
||||
>{{ item.text }}</span>
|
||||
</template>
|
||||
</select-list>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
|
||||
<select-list :items="sortDirections"
|
||||
@select="changeSortDirection($event)"
|
||||
<select-list
|
||||
:items="sortDirections"
|
||||
:value="directionEntryBySelectedValue"
|
||||
key-prop="value">
|
||||
key-prop="value"
|
||||
@select="changeSortDirection($event)"
|
||||
>
|
||||
<template v-slot:item="{ item }">
|
||||
<span class="label" v-if="item">{{ item.text }}</span>
|
||||
<span
|
||||
v-if="item"
|
||||
class="label"
|
||||
>{{ item.text }}</span>
|
||||
</template>
|
||||
</select-list>
|
||||
</div>
|
||||
|
||||
@@ -5,60 +5,108 @@
|
||||
ref="clickPotionInfo"
|
||||
class="dragInfo mouse"
|
||||
>
|
||||
<div class="spell col-12 row">
|
||||
<div class="col-8 details">
|
||||
<p class="title">
|
||||
{{ spell.text() }}
|
||||
</p>
|
||||
<p class="notes">
|
||||
{{ `Click on a ${spell.target} to cast!` }}
|
||||
</p>
|
||||
<!-- @TODO make that translatable-->
|
||||
</div>
|
||||
<div class="col-4 mana">
|
||||
<div class="spell">
|
||||
<div class="spell-border">
|
||||
<div class="mana">
|
||||
<div
|
||||
class="img"
|
||||
:class="`shop_${spell.key} shop-sprite item-img`"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="details">
|
||||
<!-- @TODO make that translatable-->
|
||||
<p class="notes">
|
||||
{{ `Select a ${spell.target}` }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="drawer-wrapper d-flex justify-content-center">
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer-wrapper">
|
||||
<drawer
|
||||
v-if="user.stats.class && !user.preferences.disableClasses"
|
||||
v-mousePosition="30"
|
||||
:title="$t('skillsTitle')"
|
||||
:title="drawerTitle"
|
||||
:open-status="openStatus"
|
||||
@mouseMoved="mouseMoved($event)"
|
||||
@toggled="drawerToggled"
|
||||
>
|
||||
<div slot="drawer-slider">
|
||||
<div class="container spell-container">
|
||||
<div class="row">
|
||||
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
|
||||
<div class="spell-container">
|
||||
<div
|
||||
v-for="(skill, key) in spells[user.stats.class]"
|
||||
v-if="user.stats.lvl >= skill.lvl"
|
||||
:id="`spell_${skill.key}`"
|
||||
:key="key"
|
||||
v-b-popover.hover.auto="skillNotes(skill)"
|
||||
class="col-12 col-md-3"
|
||||
@click="!spellDisabled(key) ? castStart(skill) : null"
|
||||
>
|
||||
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
|
||||
<div
|
||||
class="spell col-12 row"
|
||||
:class="{'disabled': spellDisabled(key)}"
|
||||
<b-popover
|
||||
:target="`spell_${skill.key}`"
|
||||
triggers="hover"
|
||||
placement="top"
|
||||
custom-class="popover-class"
|
||||
>
|
||||
<div class="col-8 details">
|
||||
<div class="popover-wrapper">
|
||||
<div class="popover-title">
|
||||
<div class="popover-title-text">
|
||||
{{ skill.text() }}
|
||||
</div>
|
||||
<div class="popover-mana">
|
||||
<div
|
||||
v-once
|
||||
class="popover-svg-icon"
|
||||
v-html="icons.mana"
|
||||
></div>
|
||||
<div class="popover-mana-count">
|
||||
{{ skill.mana }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popover-description">
|
||||
{{ skillNotes(skill) }}
|
||||
</div>
|
||||
</div>
|
||||
</b-popover>
|
||||
<div
|
||||
class="spell-border"
|
||||
:class="{ disabled: spellDisabled(key) || user.stats.lvl < skill.lvl }"
|
||||
>
|
||||
<div
|
||||
class="spell"
|
||||
>
|
||||
<div class="details">
|
||||
<div
|
||||
class="img"
|
||||
:class="`shop_${skill.key} shop-sprite item-img`"
|
||||
></div>
|
||||
<span class="title">{{ skill.text() }}</span>
|
||||
</div>
|
||||
<div class="col-4 mana">
|
||||
<div
|
||||
v-if="user.stats.lvl < skill.lvl"
|
||||
class="mana"
|
||||
>
|
||||
<div class="mana-text level">
|
||||
<div>Level {{ skill.lvl }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="spellDisabled(key) === true"
|
||||
class="mana"
|
||||
>
|
||||
<div class="mana-text">
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon"
|
||||
v-html="icons.mana"
|
||||
></div>
|
||||
<div>{{ skill.mana }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="mana"
|
||||
>
|
||||
<div class="mana-text">
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon"
|
||||
v-html="icons.mana"
|
||||
></div>
|
||||
@@ -76,68 +124,132 @@
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.drawer-wrapper {
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.drawer-wrapper {
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 19;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.drawer-container {
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
min-width: 60%;
|
||||
min-width: 25.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-class {
|
||||
.popover-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1em;
|
||||
|
||||
.popover-description {
|
||||
text-align: left;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.drawer-slider {
|
||||
margin-top: 1em;
|
||||
.popover-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 0.5em;
|
||||
|
||||
.popover-title-text {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.spell-container {
|
||||
margin-top: .5em;
|
||||
.popover-mana {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.popover-svg-icon {
|
||||
width: 1.3em;
|
||||
}
|
||||
|
||||
.popover-mana-count {
|
||||
font-weight: bold;
|
||||
color: $blue-100;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spell-container {
|
||||
white-space: initial;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
margin-left: -2rem;
|
||||
margin-right: -1.5rem;
|
||||
margin-top: -0.14rem;
|
||||
box-sizing: content-box;
|
||||
|
||||
.spell-border {
|
||||
padding: 2px;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&:hover:not(.disabled) {
|
||||
background-color: $purple-400;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 4px 0 rgba(26, 24, 29, 0.16),
|
||||
0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
}
|
||||
|
||||
.spell:hover:not(.disabled) {
|
||||
cursor: pointer;
|
||||
border: solid 2px #50b5e9;
|
||||
&.disabled {
|
||||
.spell {
|
||||
background-color: $gray-10;
|
||||
box-shadow: none !important;
|
||||
|
||||
.mana {
|
||||
background-color: rgba(26, 24, 29, 0.5);
|
||||
}
|
||||
|
||||
.level {
|
||||
color: $white;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spell {
|
||||
background: #ffffff;
|
||||
border: solid 2px transparent;
|
||||
margin-bottom: 1em;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
border-radius: 1000px;
|
||||
color: #4e4a57;
|
||||
background: $white;
|
||||
border-radius: 4px;
|
||||
color: $gray-50;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
overflow: hidden;
|
||||
width: 4.5rem;
|
||||
height: 4.6rem;
|
||||
box-shadow: 0 1px 3px 0 rgba(26, 24, 29, 0.12),
|
||||
0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
&:hover {
|
||||
box-shadow: 0 3px 6px 0 rgba(26, 24, 29, 0.16),
|
||||
0 3px 6px 0 rgba(26, 24, 29, 0.24);
|
||||
}
|
||||
|
||||
.details {
|
||||
text-align: left;
|
||||
padding-top: .5em;
|
||||
padding-right: .1em;
|
||||
text-align: center;
|
||||
height: 3.1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.img {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
padding-bottom: .7em;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.notes {
|
||||
font-weight: normal;
|
||||
color: #686274;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,69 +258,141 @@
|
||||
}
|
||||
|
||||
.mana-text {
|
||||
margin-bottom: .2em;
|
||||
padding-top: 1.1em;
|
||||
|
||||
div {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
text-align: center;
|
||||
color: $blue-1;
|
||||
|
||||
.svg-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: .2em;
|
||||
}
|
||||
}
|
||||
|
||||
.mana {
|
||||
padding: .2em;
|
||||
background-color: rgba(70, 167, 217, 0.24);
|
||||
color: #2995cd;
|
||||
background-color: rgba(70, 167, 217, 0.15);
|
||||
color: $blue-10;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
height: 1.5rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dragInfo {
|
||||
.spell-container-row {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
gap: 2em;
|
||||
margin-right: -1em;
|
||||
margin-left: -1em;
|
||||
}
|
||||
|
||||
.spell-skills {
|
||||
flex: 0 0 auto;
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.dragInfo {
|
||||
position: absolute;
|
||||
left: -500px;
|
||||
z-index: 1080;
|
||||
color: $gray-500;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
box-shadow: transparent;
|
||||
|
||||
.spell {
|
||||
border-radius: 1000px;
|
||||
min-width: 224px;
|
||||
height: 52px;
|
||||
font-size: 12px;
|
||||
padding-left: .5em;
|
||||
width: 5.9rem;
|
||||
height: 8rem;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
}
|
||||
.spell-border {
|
||||
width: 59px;
|
||||
height: 62px;
|
||||
background: $blue-50;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
transform: rotate(45deg);
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.mana {
|
||||
border-radius: 0 1000px 1000px 0;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
background-color: $gray-700;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
|
||||
.img {
|
||||
background-color: $gray-700;
|
||||
display: block;
|
||||
text-align: center;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(52, 49, 58, 0.96);
|
||||
|
||||
.notes {
|
||||
font-size: 13px;
|
||||
color: $white;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.mouse {
|
||||
position: fixed;
|
||||
pointer-events: none
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.potion-icon {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.popover {
|
||||
position: inherit;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import spells, { stealthBuffsToAdd } from '@/../../common/script/content/spells';
|
||||
import throttle from 'lodash/throttle';
|
||||
|
||||
import spells, {
|
||||
stealthBuffsToAdd,
|
||||
} from '@/../../common/script/content/spells';
|
||||
import { mapState, mapGetters } from '@/libs/store';
|
||||
import notifications from '@/mixins/notifications';
|
||||
import spellsMixin from '@/mixins/spells';
|
||||
@@ -216,7 +400,11 @@ import Drawer from '@/components/ui/drawer';
|
||||
import MouseMoveDirective from '@/directives/mouseposition.directive';
|
||||
|
||||
import mana from '@/assets/svg/mana.svg';
|
||||
import { CONSTANTS, setLocalSetting, getLocalSetting } from '@/libs/userlocalManager';
|
||||
import {
|
||||
CONSTANTS,
|
||||
setLocalSetting,
|
||||
getLocalSetting,
|
||||
} from '@/libs/userlocalManager';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -246,6 +434,10 @@ export default {
|
||||
openStatus () {
|
||||
return this.$store.state.spellOptions.spellDrawOpen ? 1 : 0;
|
||||
},
|
||||
drawerTitle () {
|
||||
const classStr = this.$t(this.user.stats.class);
|
||||
return this.$t('skillsTitle', { classStr });
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
// @TODO: should we abstract the drawer state/local
|
||||
@@ -260,10 +452,8 @@ export default {
|
||||
this.$store.state.spellOptions.spellDrawOpen = newState;
|
||||
|
||||
if (newState) {
|
||||
setLocalSetting(
|
||||
CONSTANTS.keyConstants.SPELL_DRAWER_STATE,
|
||||
CONSTANTS.drawerStateValues.DRAWER_OPEN,
|
||||
);
|
||||
setLocalSetting(CONSTANTS.keyConstants.SPELL_DRAWER_STATE,
|
||||
CONSTANTS.drawerStateValues.DRAWER_OPEN);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,9 +463,18 @@ export default {
|
||||
);
|
||||
},
|
||||
spellDisabled (skill) {
|
||||
const incompleteDailiesDue = this.getUnfilteredTaskList('daily').filter(daily => !daily.completed && daily.isDue).length;
|
||||
if (skill === 'frost' && this.user.stats.buffs.streaks) return true;
|
||||
if (skill === 'stealth' && this.user.stats.buffs.stealth >= incompleteDailiesDue) return true;
|
||||
const incompleteDailiesDue = this
|
||||
.getUnfilteredTaskList('daily')
|
||||
.filter(daily => !daily.completed && daily.isDue)
|
||||
.length;
|
||||
|
||||
if (skill === 'frost' && this.user.stats.buffs.streaks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skill === 'stealth' && this.user.stats.buffs.stealth >= incompleteDailiesDue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
@@ -296,15 +495,14 @@ export default {
|
||||
return notes;
|
||||
},
|
||||
// @TODO: Move to mouse move component??
|
||||
mouseMoved ($event) {
|
||||
// @TODO: throttle
|
||||
mouseMoved: throttle(function mouseMoved ($event) {
|
||||
if (this.potionClickMode) {
|
||||
this.$refs.clickPotionInfo.style.left = `${$event.x + 20}px`;
|
||||
this.$refs.clickPotionInfo.style.top = `${$event.y + 20}px`;
|
||||
} else {
|
||||
this.lastMouseMoveEvent = $event;
|
||||
}
|
||||
},
|
||||
}, 10),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
"classGearText": "Congratulations on choosing a class! I've added your new basic weapon to your inventory. Take a look below to equip it!",
|
||||
"autoAllocate": "Auto Allocate",
|
||||
"spells": "Skills",
|
||||
"skillsTitle": "Skills",
|
||||
"skillsTitle": "<%= classStr %> Skills",
|
||||
"toDo": "To Do",
|
||||
"tourStatsPage": "This is your Stats page! Earn achievements by completing the listed tasks.",
|
||||
"tourTavernPage": "Welcome to the Tavern, an all-ages chat room! You can keep your Dailies from hurting you in case of illness or travel by clicking \"Pause Damage\". Come say hi!",
|
||||
|
||||
Reference in New Issue
Block a user