From 425da73930da9030f7ab8c17bd53f67882754f75 Mon Sep 17 00:00:00 2001 From: Colin Kallemein <cakallemein@gmail.com> Date: Sat, 6 Jul 2024 20:38:33 +0200 Subject: [PATCH] Convert character screen to Tailwind --- src/screens/Characters.vue | 262 ++++++------------------------------- tailwind.config.js | 7 + 2 files changed, 48 insertions(+), 221 deletions(-) diff --git a/src/screens/Characters.vue b/src/screens/Characters.vue index a22e8db..e4b42ab 100644 --- a/src/screens/Characters.vue +++ b/src/screens/Characters.vue @@ -1,38 +1,40 @@ <template> - <div class="character-select-screen"> - <div class="ui-wrapper"> - <div class="characters-wrapper" v-if="!isLoading"> - <div v-for="character in characters" :key="character.id" class="character" :class="{ active: selected_character == character.id }"> - <input type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" /> - <label :for="character.id">{{ character.name }}</label> + <div class="character-select-screen bg-gray-300 relative"> + <div class="absolute bg-[url('/assets/shapes/select-screen-bg-shape.svg')] bg-no-repeat bg-center w-full h-full"></div> + <div class="ui-wrapper h-dvh flex flex-col justify-center items-center gap-[80px] px-[80px]"> + <div class="filler"></div> + <div class="characters-wrapper flex justify-center flex-wrap gap-[60px] w-full max-h-[650px] overflow-auto" v-if="!isLoading"> + <div v-for="character in characters" :key="character.id" class="character m-[15px] w-[170px] h-[275px] flex flex-col rounded-[20px] relative bg-[url('/assets/shapes/character-select-shape.svg')] bg-no-repeat shadow-character" :class="{ active: selected_character == character.id }"> + <input class="opacity-0 h-full w-full absolute m-0 z-10" type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" /> + <label class="font-bold absolute left-1/2 top-[20px] max-w-[130px] translate-x-[-50%] translate-y-[-50%] text-center text-ellipsis overflow-hidden whitespace-nowrap drop-shadow-text" :for="character.id">{{ character.name }}</label> <!-- @TODO : Add a confirmation dialog --> - <button class="delete" @click="delete_character(character.id)"> + <button class="delete bg-red w-[30px] h-[30px] p-[3px] rounded-full absolute right-[-15px] top-0 translate-y-[-50%] z-10 border-2 border-solid border-white hover:bg-red-100" @click="delete_character(character.id)"> <img draggable="false" src="/assets/icons/trashcan.svg" /> </button> - <div class="sprite-container"> - <img draggable="false" src="/assets/avatar/default/0.png" /> + <div class="sprite-container flex flex-col items-center m-auto"> + <img class="drop-shadow-20" draggable="false" src="/assets/avatar/default/0.png" /> </div> - <span>Lvl. {{ character.level }}</span> + <span class="absolute bottom-[20px] w-full text-center translate-y-1/2 z-10 drop-shadow-text">Lvl. {{ character.level }}</span> + <div class="selected-character absolute max-w-0 w-[65%] h-[3px] bg-white rounded-[3px] left-1/2 bottom-[-15px] translate-x-[-50%] transition-all ease-in-out duration-300"></div> </div> - <div class="character new-character" v-if="characters.length < 4"> - <button @click="isModalOpen = true"> - <img draggable="false" src="/assets/icons/plus-icon.svg" /> - <span>Create new</span> + <div class="character new-character m-[15px] w-[170px] h-[275px] flex flex-col rounded-[20px] relative bg-gray-50 bg-opacity-50 bg-no-repeat shadow-character" v-if="characters.length < 4"> + <button class="h-full w-full py-[40px] flex flex-col justify-between" @click="isModalOpen = true"> + <div class="filler"></div> + <img class="w-[100px] h-[100px] m-auto" draggable="false" src="/assets/icons/plus-icon.svg" /> + <span class="self-center text-base absolute bottom-[20px] w-full text-center translate-y-1/2 z-10 drop-shadow-text">Create new</span> </button> </div> </div> <div v-else> - <div class="loading-spinner"> - <img src="/assets/icons/loading-icon1.svg" /> - </div> + <img class="w-[80px] invert-80" src="/assets/icons/loading-icon1.svg" /> </div> - <div class="button-wrapper" v-if="!isLoading"> - <button class="btn-cyan" :disabled="!selected_character" @click="select_character()"> + <div class="button-wrapper flex gap-[30px]" v-if="!isLoading"> + <button class="btn-cyan py-2 pr-2.5 pl-[30px] min-w-[100px] relative rounded text-xl flex gap-[15px] items-center transition-all ease-in-out duration-200" :disabled="!selected_character" @click="select_character()"> PLAY - <img draggable="false" src="/assets/icons/arrow.svg" /> + <img class="h-[30px] drop-shadow-20" draggable="false" src="/assets/icons/arrow.svg" /> </button> </div> </div> @@ -114,209 +116,27 @@ onBeforeUnmount(() => { </script> <style lang="scss"> -@import '@/assets/scss/main'; - -.character-select-screen { - &::before { - content: ''; - position: absolute; - background-image: url('/assets/shapes/select-screen-bg-shape.svg'); - background-repeat: no-repeat; - background-position: center; - background-size: 100% cover; - width: 100%; - height: 100%; - } - background-color: $dark-gray; - position: relative; - - .ui-wrapper { - height: 100vh; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 80px; - padding: 0 80px; - &::before { - content: ''; - } - - .loading-spinner img { - width: 5rem; - // css color - filter: invert(1); - // white - filter: invert(80%); - } - - .characters-wrapper { - display: flex; - justify-content: center; - flex-wrap: wrap; - gap: 60px; - width: 100%; - max-height: 650px; - overflow: auto; - - .character { - margin: 15px; - width: 170px; - height: 275px; - display: flex; - flex-direction: column; - border-radius: 20px; - position: relative; - background-repeat: no-repeat; - background-image: url('/assets/shapes/character-select-shape.svg'); - box-shadow: 0 4px 30px rgba($black, 0.1); - - &::after { - content: ''; - position: absolute; - max-width: 0; - width: 65%; - height: 3px; - background-color: $white; - border-radius: 3px; - left: 50%; - bottom: -15px; - transform: translateX(-50%); - transition: ease-in-out max-width 0.3s; - } - - &.active::after { - max-width: 170px; - } - - &.new-character { - background-color: rgba($light-gray, 0.5); - background-image: none; - - button { - height: 100%; - width: 100%; - padding: 40px 0; - display: flex; - flex-direction: column; - justify-content: space-between; - &::before { - content: ''; - } - img { - width: 100px; - height: 100px; - margin: auto; - } - - span { - align-self: center; - font-size: 1rem; - } - } - } - - input[type='radio'] { - opacity: 0; - height: 100%; - width: 100%; - position: absolute; - margin: 0; - z-index: 9; - } - - label { - font-weight: bold; - position: absolute; - left: 50%; - top: 20px; - max-width: 130px; - transform: translateY(-50%) translateX(-50%); - text-align: center; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - text-shadow: 1px 1px 5px rgba($black, 0.25); - } - - button.delete { - background-color: $red; - width: 30px; - height: 30px; - padding: 3px; - border-radius: 100%; - position: absolute; - right: -15px; - top: 0; - transform: translateY(-50%); - z-index: 1; - border: 2px solid $white; - - &:hover { - background-color: $dark-red; - } - } - - span { - position: absolute; - bottom: 20px; - width: 100%; - text-align: center; - transform: translateY(50%); - z-index: 1; - text-shadow: 1px 1px 5px rgba($black, 0.25); - } - - .sprite-container { - display: flex; - flex-direction: column; - align-items: center; - margin: auto; - - img { - filter: drop-shadow(0 3px 6px rgba($black, 0.25)); - } - } - } - } - - .button-wrapper { - display: flex; - gap: 30px; - - button { - padding: 8px 10px 8px 30px; - min-width: 100px; - position: relative; - border-radius: 5px; - font-size: 1.25rem; - display: flex; - gap: 15px; - align-items: center; - transition: ease-in-out gap 0.2s; - - span { - margin: auto; - } - - img { - height: 30px; - filter: drop-shadow(0 4px 6px rgba($black, 0.25)); - } - - &:disabled { - background-color: rgba($cyan, 0.5); - cursor: not-allowed; - &:hover { - gap: 15px; - } - } - - &:hover { - gap: 20px; - } +.characters-wrapper { + .character { + &.active { + .selected-character { + @apply max-w-[170px]; } } } } + +.button-wrapper { + button { + &:disabled { + @apply bg-cyan bg-opacity-50 cursor-not-allowed; + &:hover { + @apply gap-[15px]; + } + } + &:hover { + @apply gap-[20px]; + } + } +} </style> diff --git a/tailwind.config.js b/tailwind.config.js index 2053f71..334344e 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -11,10 +11,17 @@ export default { '30px': '30px' }, extend: { + invert: { + 80: '0.80' + }, dropShadow: { 'default': '0 3px 6px rgb(0, 0, 0)', + 'text': '1px 1px 5px rgba(0, 0, 0, 0.25)', '20': '0 3px 6px rgba(0, 0, 0, 0.2)' }, + boxShadow: { + 'character': '0 4px 30px rgba(0, 0, 0, 0.1)', + }, colors: { red: { DEFAULT: '#d50000',