even more clean up but now it's very pretty
parent
a7ba4ac043
commit
48a904e932
@ -1 +1,146 @@
|
||||
["MINUS","ZEROS","ROUND","THIRD","PROOF","EVENT","MATHS","CUBIC","MONAD","GAUSS","AXIOM","PRISM","CHORD","ANGLE","LITRE","MILES","VALUE","TABLE","HALVE","EXACT","LOCUS","QUART","ARRAY","SOLID","KITES","TRIAL","EMPTY","FIFTH","NINTH","DEPTH","BOOLE","FACES","TENTH","SLOPE","SIXTH","DELTA","SIGMA","LINES","EULER","FIFTY","SCALE","RULER","INDEX","OUNCE","FIRST","SPACE","MONIC","POINT","RIGHT","DIGIT","VALID","TIMES","KLEIN","TWICE","SIXES","METRE","STONE","BAYES","SEVEN","PLANE","CLOCK","THREE","CHAOS","ACUTE","UNITS","HARDY","COUNT","FORTY","TORUS","WIDTH","LOGIC","WILES","POWER","EIGHT","RANGE","PRIME","MODAL","TREND","THETA","CURVE","SIXTY","ERROR","TALLY","PLATO","UNION","KILOS","GRAPH","RATIO","CUBES","DOZEN","EQUAL","ALPHA","NODES","GROUP","ERDOS","KAPPA","LIMIT","ADDED","HERTZ","LATEX","CONIC","RINGS","BOUND","ROOTS","BOREL","ALEPH","SURDS","HELIX","APPEL","EDGES","GAMMA","POLAR","GODEL","FIELD","TUPLE","POLYA","BASIS","UPPER","LEMMA","PROVE","ORDER","SIDES","HASSE","SMALL","BRACE","KNUTH","AREAS","IDEAL","SPACE","DENSE","MODEL","LOWER","OVALS","NOISE","SOLVE","BAIRE","CHAIN","JULIA","FOCUS","KNOTS","DIRAC","HOLES","NORMS","REALS"]
|
||||
[
|
||||
"MINUS",
|
||||
"ZEROS",
|
||||
"ROUND",
|
||||
"THIRD",
|
||||
"PROOF",
|
||||
"EVENT",
|
||||
"MATHS",
|
||||
"CUBIC",
|
||||
"MONAD",
|
||||
"GAUSS",
|
||||
"AXIOM",
|
||||
"PRISM",
|
||||
"CHORD",
|
||||
"ANGLE",
|
||||
"LITRE",
|
||||
"MILES",
|
||||
"VALUE",
|
||||
"TABLE",
|
||||
"HALVE",
|
||||
"EXACT",
|
||||
"LOCUS",
|
||||
"QUART",
|
||||
"ARRAY",
|
||||
"SOLID",
|
||||
"KITES",
|
||||
"TRIAL",
|
||||
"EMPTY",
|
||||
"FIFTH",
|
||||
"NINTH",
|
||||
"DEPTH",
|
||||
"BOOLE",
|
||||
"FACES",
|
||||
"TENTH",
|
||||
"SLOPE",
|
||||
"SIXTH",
|
||||
"DELTA",
|
||||
"SIGMA",
|
||||
"LINES",
|
||||
"EULER",
|
||||
"FIFTY",
|
||||
"SCALE",
|
||||
"RULER",
|
||||
"INDEX",
|
||||
"OUNCE",
|
||||
"FIRST",
|
||||
"SPACE",
|
||||
"MONIC",
|
||||
"POINT",
|
||||
"RIGHT",
|
||||
"DIGIT",
|
||||
"VALID",
|
||||
"TIMES",
|
||||
"KLEIN",
|
||||
"TWICE",
|
||||
"SIXES",
|
||||
"METRE",
|
||||
"STONE",
|
||||
"BAYES",
|
||||
"SEVEN",
|
||||
"PLANE",
|
||||
"CLOCK",
|
||||
"THREE",
|
||||
"CHAOS",
|
||||
"ACUTE",
|
||||
"UNITS",
|
||||
"HARDY",
|
||||
"COUNT",
|
||||
"FORTY",
|
||||
"TORUS",
|
||||
"WIDTH",
|
||||
"LOGIC",
|
||||
"WILES",
|
||||
"POWER",
|
||||
"EIGHT",
|
||||
"RANGE",
|
||||
"PRIME",
|
||||
"MODAL",
|
||||
"TREND",
|
||||
"THETA",
|
||||
"CURVE",
|
||||
"SIXTY",
|
||||
"ERROR",
|
||||
"TALLY",
|
||||
"PLATO",
|
||||
"UNION",
|
||||
"KILOS",
|
||||
"GRAPH",
|
||||
"RATIO",
|
||||
"CUBES",
|
||||
"DOZEN",
|
||||
"EQUAL",
|
||||
"ALPHA",
|
||||
"NODES",
|
||||
"GROUP",
|
||||
"ERDOS",
|
||||
"KAPPA",
|
||||
"LIMIT",
|
||||
"ADDED",
|
||||
"HERTZ",
|
||||
"LATEX",
|
||||
"CONIC",
|
||||
"RINGS",
|
||||
"BOUND",
|
||||
"ROOTS",
|
||||
"BOREL",
|
||||
"ALEPH",
|
||||
"SURDS",
|
||||
"HELIX",
|
||||
"APPEL",
|
||||
"EDGES",
|
||||
"GAMMA",
|
||||
"POLAR",
|
||||
"GODEL",
|
||||
"FIELD",
|
||||
"TUPLE",
|
||||
"POLYA",
|
||||
"BASIS",
|
||||
"UPPER",
|
||||
"LEMMA",
|
||||
"PROVE",
|
||||
"ORDER",
|
||||
"SIDES",
|
||||
"HASSE",
|
||||
"SMALL",
|
||||
"BRACE",
|
||||
"KNUTH",
|
||||
"AREAS",
|
||||
"IDEAL",
|
||||
"SPACE",
|
||||
"DENSE",
|
||||
"MODEL",
|
||||
"LOWER",
|
||||
"OVALS",
|
||||
"NOISE",
|
||||
"SOLVE",
|
||||
"BAIRE",
|
||||
"CHAIN",
|
||||
"JULIA",
|
||||
"FOCUS",
|
||||
"KNOTS",
|
||||
"DIRAC",
|
||||
"HOLES",
|
||||
"NORMS",
|
||||
"REALS"
|
||||
]
|
||||
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
Before Width: | Height: | Size: 496 B |
@ -1,46 +0,0 @@
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
props: ["message"],
|
||||
methods: {
|
||||
stateToSymbol(state) {
|
||||
if(state === 'correct-full') {
|
||||
return '🟩';
|
||||
} else if(state === 'correct-half') {
|
||||
return '🟢';
|
||||
} else if (state === 'misplaced-full') {
|
||||
return '🟨';
|
||||
} else if (state === 'misplaced-half') {
|
||||
return '🟡';
|
||||
} else {
|
||||
return '⬜';
|
||||
}
|
||||
},
|
||||
share() {
|
||||
let output = "PHC/Qwordle";
|
||||
output += " " + (this.won ? this.lastAttempt : "X") + "/6\n";
|
||||
for(let i = 0; i < this.lastAttempt; i++) {
|
||||
for(let j = 0; j < 5; j++) {
|
||||
output += this.stateToSymbol(this.state[i][j].state);
|
||||
}
|
||||
output += '\n';
|
||||
}
|
||||
navigator.clipboard.writeText(output).then(() => {
|
||||
this.$emit('copied', null);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="popup">
|
||||
{{message}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
createApp(App).use(router).mount('#app')
|
||||
|
@ -0,0 +1,31 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Game from '../views/Game.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/:id',
|
||||
name: 'Game',
|
||||
component: Game
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: to => {
|
||||
|
||||
let id = '';
|
||||
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let charactersLength = characters.length;
|
||||
for ( let i = 0; i < 8; i++ ) {
|
||||
id += characters.charAt(Math.floor(Math.random() *
|
||||
charactersLength));
|
||||
}
|
||||
return { path: `/${id}` }
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
@ -0,0 +1,376 @@
|
||||
<script>
|
||||
import GuessGrid from '../components/GuessGrid.vue'
|
||||
import Keyboard from '../components/Keyboard.vue';
|
||||
import Overlay from '../components/Overlay.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// Constants
|
||||
LETTER_ANIMATION_DURATION: 0.3,
|
||||
SHAKE_ANIMATION_DURATION: 0.3,
|
||||
|
||||
// Variables
|
||||
words: [],
|
||||
pairs: [],
|
||||
|
||||
listen: true,
|
||||
|
||||
gridState: null,
|
||||
rowsAnimations: null,
|
||||
keyboardMask: null,
|
||||
|
||||
currentAttempt: 0,
|
||||
currentIndex: 0,
|
||||
|
||||
secretWords: null,
|
||||
|
||||
gameOver: false,
|
||||
won: false,
|
||||
overlayVisible: false,
|
||||
|
||||
popups: {}
|
||||
}
|
||||
},
|
||||
|
||||
async created() {
|
||||
window.addEventListener('keyup', (e) => {
|
||||
if (e.key === 'Backspace') {
|
||||
this.keyPress('Delete');
|
||||
} else if (e.key === 'Delete' || e.key === 'Enter') {
|
||||
this.keyPress(e.key);
|
||||
} else if (e.key.match(/^[a-zA-Z]$/)) {
|
||||
this.keyPress(e.key.toUpperCase())
|
||||
}
|
||||
});
|
||||
|
||||
let req = await fetch('./math-words.json');
|
||||
this.words = await req.json();
|
||||
req = await fetch('./math-pairs.json');
|
||||
this.pairs = await req.json();
|
||||
|
||||
this.setupGame();
|
||||
},
|
||||
components: {
|
||||
GuessGrid,
|
||||
Keyboard,
|
||||
Overlay,
|
||||
},
|
||||
methods: {
|
||||
setupGame() {
|
||||
this.gridState = Array.from({length: 6}, () => {
|
||||
return Array.from({length: 5}, () => {
|
||||
return {
|
||||
letter: '',
|
||||
state: 'unset'
|
||||
};
|
||||
});
|
||||
});
|
||||
this.rowsAnimations = new Array(6).fill(false);
|
||||
|
||||
this.keyboardMask = Object.fromEntries(
|
||||
Array.from({length: 26}, (v, i) => [
|
||||
String.fromCharCode(i + 65), 'unused'
|
||||
])
|
||||
);
|
||||
this.keyboardMask['Enter'] = 'unused';
|
||||
this.keyboardMask['Delete'] = 'unused';
|
||||
console.log(this.keyboardMask);
|
||||
|
||||
this.currentAttempt = 0;
|
||||
this.currentIndex = 0;
|
||||
|
||||
let gameId = 0;
|
||||
for(let i = 0; i < this.$route.params.id.length; i++) {
|
||||
let mod = this.$route.params.id.charCodeAt(i);
|
||||
gameId += mod * mod * mod * mod;
|
||||
}
|
||||
this.secretWords = this.pairs[gameId % this.pairs.length];
|
||||
console.log(this.secretWords);
|
||||
console.log(this.secretWords[0]);
|
||||
console.log(this.secretWords[1]);
|
||||
|
||||
this.gameOver = false;
|
||||
this.won = false;
|
||||
this.overlayVisible = false;
|
||||
},
|
||||
async newGame() {
|
||||
let newId = this.randomId(8);
|
||||
await this.$router.replace({params: {id: newId}});
|
||||
this.setupGame();
|
||||
},
|
||||
randomId(length) {
|
||||
let result = '';
|
||||
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let charactersLength = characters.length;
|
||||
for ( let i = 0; i < length; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() *
|
||||
charactersLength));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
addPopUp(message) {
|
||||
let id = this.randomId(16);
|
||||
this.popups[id] = message;
|
||||
setTimeout(() => delete this.popups[id], 10*1000);
|
||||
},
|
||||
checkWin(matches, oneWordMatch) {
|
||||
if (!oneWordMatch) {
|
||||
return false;
|
||||
}
|
||||
for(let i = 0; i < 5; i++) {
|
||||
if (matches[i][0] === -1 || !matches[i][1]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
resolveGame(won) {
|
||||
this.won = won;
|
||||
this.gameOver = true;
|
||||
this.overlayVisible = true;
|
||||
},
|
||||
keyPress(event) {
|
||||
if (!this.listen) {
|
||||
return;
|
||||
}
|
||||
if (event === "Delete") {
|
||||
if(this.currentIndex > 0) {
|
||||
this.currentIndex -= 1;
|
||||
this.gridState[this.currentAttempt][this.currentIndex].letter = '';
|
||||
this.gridState[this.currentAttempt][this.currentIndex].state = 'unset';
|
||||
}
|
||||
} else if (event == "Enter") {
|
||||
if(this.currentIndex === 5) {
|
||||
|
||||
// Validate Word
|
||||
let currentWord = "";
|
||||
for(let i = 0; i < 5; i++) {
|
||||
currentWord += this.gridState[this.currentAttempt][i].letter;
|
||||
}
|
||||
if(!this.words.includes(currentWord)) {
|
||||
// Invalid attempt, signal error
|
||||
this.listen = false;
|
||||
this.rowsAnimations[this.currentAttempt] = true;
|
||||
|
||||
setTimeout(() => {
|
||||
this.listen = true;
|
||||
this.rowsAnimations[this.currentAttempt] = false;
|
||||
}, this.SHAKE_ANIMATION_DURATION * 1000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate result
|
||||
let wordsFlags = [ this.secretWords[0].split(''), this.secretWords[1].split('') ];
|
||||
let matches = [ [-1,false], [-1,false], [-1,false], [-1,false], [-1,false] ];
|
||||
|
||||
for(let i = 0; i < 5; i++) {
|
||||
let letter = this.gridState[this.currentAttempt][i].letter;
|
||||
for(let j = 0; j < 2; j++) {
|
||||
if (wordsFlags[j][i] === letter) {
|
||||
wordsFlags[j][i] = null;
|
||||
matches[i] = [j, true];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(let i = 0; i < 5; i++) {
|
||||
let letter = this.gridState[this.currentAttempt][i].letter;
|
||||
for(let j = 0; j < 2; j++) {
|
||||
for(let k = 0; k < 5; k++) {
|
||||
if(wordsFlags[j][k] === letter) {
|
||||
wordsFlags[j][k] = null;
|
||||
matches[i] = [j, false];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let oneWordMatch = true;
|
||||
for(let i = 0; i < 5; i++) {
|
||||
for(let j = 0; j < 5; j++) {
|
||||
if (matches[i][0] == 0 && matches[j][0] == 1) {
|
||||
oneWordMatch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update grid to tease result
|
||||
for(let i = 0; i < 5; i++) {
|
||||
if (matches[i][0] !== -1 && matches[i][1]) {
|
||||
this.gridState[this.currentAttempt][i].state = `correct-${oneWordMatch ? 'full' : 'half'}`;
|
||||
} else if (matches[i][0] !== -1 && !matches[i][1]) {
|
||||
this.gridState[this.currentAttempt][i].state = `misplaced-${oneWordMatch ? 'full' : 'half'}`;
|
||||
} else {
|
||||
this.gridState[this.currentAttempt][i].state = 'wrong';
|
||||
}
|
||||
}
|
||||
this.listen = false;
|
||||
|
||||
// Resolve
|
||||
setTimeout(() => {
|
||||
for(let i = 0; i < 5; i++) {
|
||||
if (matches[i][0] !== -1 && matches[i][1]) {
|
||||
if(this.keyboardMask[this.gridState[this.currentAttempt][i].letter] === 'unused' ||
|
||||
this.keyboardMask[this.gridState[this.currentAttempt][i].letter] === 'misplaced') {
|
||||
this.keyboardMask[this.gridState[this.currentAttempt][i].letter] = 'correct';
|
||||
}
|
||||
} else if (matches[i][0] !== -1 && !matches[i][1]) {
|
||||
if(this.keyboardMask[this.gridState[this.currentAttempt][i].letter] === 'unused') {
|
||||
this.keyboardMask[this.gridState[this.currentAttempt][i].letter] = 'misplaced';
|
||||
}
|
||||
} else {
|
||||
if(this.keyboardMask[this.gridState[this.currentAttempt][i].letter] === 'unused') {
|
||||
this.keyboardMask[this.gridState[this.currentAttempt][i].letter] = 'wrong';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.currentAttempt += 1;
|
||||
this.currentIndex = 0;
|
||||
|
||||
|
||||
if (this.checkWin(matches, oneWordMatch)) {
|
||||
this.resolveGame(true);
|
||||
} else if (this.currentAttempt === 6) {
|
||||
this.resolveGame(false);
|
||||
}
|
||||
|
||||
this.listen = true;
|
||||
}, this.LETTER_ANIMATION_DURATION * 1000 * 5);
|
||||
}
|
||||
} else {
|
||||
if (this.currentIndex < 5) {
|
||||
this.gridState[this.currentAttempt][this.currentIndex].letter = event;
|
||||
this.gridState[this.currentAttempt][this.currentIndex].state = 'set';
|
||||
this.currentIndex += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page"
|
||||
:style="`--letter-animation-duration: ${LETTER_ANIMATION_DURATION}s; --shake-animation-duration: ${SHAKE_ANIMATION_DURATION}s`"
|
||||
>
|
||||
<div class="toolbar">
|
||||
<div class="logo">
|
||||
<img src="logo-circuit-board.svg" alt="logo" />
|
||||
/
|
||||
Math qwordle
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="this.gridState !== null" class="interface">
|
||||
<div class="header">
|
||||
<div>Math qwordle</div>
|
||||
<div class="end">
|
||||
<div class="material-icons-outlined">info</div>
|
||||
<div v-if="gameOver" class="material-icons-outlined" @click="overlayVisible = true">military_tech</div>
|
||||
</div>
|
||||
</div>
|
||||
<GuessGrid :state="gridState" :rows-animations="rowsAnimations"/>
|
||||
<Keyboard :mask="keyboardMask" @add="keyPress($event)" :listen="true"/>
|
||||
</div>
|
||||
<Overlay v-if="overlayVisible"
|
||||
:secret-words="secretWords"
|
||||
:state="gridState"
|
||||
:won="won"
|
||||
:last-attempt="currentAttempt"
|
||||
@close="overlayVisible = false"
|
||||
@reset="newGame()"
|
||||
@share="addPopUp('copied to clipboard!')"
|
||||
/>
|
||||
<div v-for="popup in popups" class="popup">
|
||||
{{popup}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.page {
|
||||
position: relative;
|
||||
|
||||
.toolbar {
|
||||
padding: 1rem .75rem 1rem 1rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
max-height: 2.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.interface {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
|
||||
padding: 4rem;
|
||||
|
||||
.header {
|
||||
width: 18rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
|
||||
.end {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.material-icons, .material-icons-outlined, .button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@keyframes appear {
|
||||
0% {
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
transform: translate(-50%, -3rem);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
transform: translate(-50%, -3rem);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.popup {
|
||||
position: absolute;
|
||||
bottom: 0%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
opacity: 0;
|
||||
|
||||
animation: ease-in-out appear 5s;
|
||||
|
||||
background-color: var(--popup-color);
|
||||
border-radius: 20px;
|
||||
padding: 1rem 3rem;
|
||||
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue