diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/App.vue | 40 | ||||
| -rw-r--r-- | src/components/SettingsModal.vue | 139 | ||||
| -rw-r--r-- | src/components/SettingsPane.vue | 136 |
3 files changed, 152 insertions, 163 deletions
diff --git a/src/App.vue b/src/App.vue index e26de01..4a5efe8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,8 +5,8 @@ import Tile from './components/Tile.vue'; import AncestryBar from './components/AncestryBar.vue'; import TileInfoModal from './components/TileInfoModal.vue'; import HelpModal from './components/HelpModal.vue'; +import SettingsModal from './components/SettingsModal.vue'; import SearchModal from './components/SearchModal.vue'; -import SettingsPane from './components/SettingsPane.vue'; // Icons import HelpIcon from './components/icon/HelpIcon.vue'; import SearchIcon from './components/icon/SearchIcon.vue'; @@ -104,6 +104,7 @@ export default defineComponent({ helpOpen: false, searchOpen: false, settingsOpen: false, + tutorialOpen: true, // For search and auto-mode modeRunning: false, lastFocused: null as LayoutNode | null, @@ -604,8 +605,8 @@ export default defineComponent({ }, components: { Tile, AncestryBar, - HelpIcon, SearchIcon, PlayIcon, SettingsIcon, - TileInfoModal, HelpModal, SearchModal, SettingsPane, + HelpIcon, SettingsIcon, SearchIcon, PlayIcon, + TileInfoModal, HelpModal, SearchModal, SettingsModal, }, }); </script> @@ -624,13 +625,16 @@ export default defineComponent({ @detached-ancestor-click="onDetachedAncestorClick" @info-icon-click="onInfoIconClick"/> <!-- Icons --> <help-icon @click="onHelpIconClick" - class="absolute bottom-[6px] left-[6px] w-[18px] h-[18px] + class="absolute bottom-[6px] right-[6px] w-[18px] h-[18px] + text-white/40 hover:text-white hover:cursor-pointer"/> + <settings-icon @click="onSettingsIconClick" + class="absolute bottom-[6px] right-[30px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/> <search-icon @click="onSearchIconClick" - class="absolute bottom-[6px] left-[30px] w-[18px] h-[18px] + class="absolute bottom-[6px] right-[54px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/> <play-icon @click="onPlayIconClick" - class="absolute bottom-[6px] left-[54px] w-[18px] h-[18px] + class="absolute bottom-[6px] right-[78px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/> <!-- Modals --> <transition name="fade"> @@ -646,18 +650,9 @@ export default defineComponent({ <help-modal v-if="helpOpen" :uiOpts="uiOpts" @help-modal-close="helpOpen = false"/> </transition> <!-- Settings --> - <transition name="slide-bottom-right"> - <settings-pane v-if="settingsOpen" :lytOpts="lytOpts" :uiOpts="uiOpts" - @settings-close="settingsOpen = false" - @layout-option-change="onLayoutOptionChange" @tree-change="onTreeChange"/> - <div v-else class="absolute bottom-0 right-0 w-[100px] h-[100px] invisible"> - <!-- Note: Above enclosing div prevents transition interference with inner rotate --> - <div class="absolute bottom-[-50px] right-[-50px] w-[100px] h-[100px] visible -rotate-45 - bg-black text-white hover:cursor-pointer" @click="onSettingsIconClick"> - <settings-icon class="w-6 h-6 mx-auto mt-2"/> - </div> - </div> - </transition> + <settings-modal v-if="settingsOpen" :lytOpts="lytOpts" :uiOpts="uiOpts" + @settings-close="settingsOpen = false" + @layout-option-change="onLayoutOptionChange" @tree-change="onTreeChange"/> <!-- Overlay used to prevent interaction and capture clicks --> <div :style="{visibility: modeRunning ? 'visible' : 'hidden'}" class="absolute left-0 top-0 w-full h-full" @click="modeRunning = false"></div> @@ -673,13 +668,4 @@ export default defineComponent({ transition-duration: 300ms; transition-timing-function: ease-out; } -.slide-bottom-right-enter-from, .slide-bottom-right-leave-to { - transform: translate(100%, 100%); - opacity: 0; -} -.slide-bottom-right-enter-active, .slide-bottom-right-leave-active { - transition-property: transform, opacity; - transition-duration: 300ms; - transition-timing-function: ease-in-out; -} </style> diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue new file mode 100644 index 0000000..5f3b3c4 --- /dev/null +++ b/src/components/SettingsModal.vue @@ -0,0 +1,139 @@ +<script lang="ts"> +import {defineComponent, PropType} from 'vue'; +import CloseIcon from './icon/CloseIcon.vue'; +import type {LayoutOptions} from '../layout'; + +// Displays configurable options, and sends option-change requests +export default defineComponent({ + props: { + lytOpts: {type: Object as PropType<LayoutOptions>, required: true}, + uiOpts: {type: Object, required: true}, + }, + methods: { + onCloseClick(evt: Event){ + if (evt.target == this.$el || (this.$refs.closeIcon as typeof CloseIcon).$el.contains(evt.target)){ + this.$emit('settings-close'); + } + }, + onLytOptChg(){ + this.$emit('layout-option-change'); + }, + onMinTileSzChg(){ + let minInput = this.$refs.minTileSzInput as HTMLInputElement; + let maxInput = this.$refs.maxTileSzInput as HTMLInputElement; + if (Number(minInput.value) > Number(maxInput.value)){ + this.lytOpts.maxTileSz = this.lytOpts.minTileSz; + } + this.onLytOptChg(); + }, + onMaxTileSzChg(){ + let minInput = this.$refs.minTileSzInput as HTMLInputElement; + let maxInput = this.$refs.maxTileSzInput as HTMLInputElement; + if (Number(maxInput.value) < Number(minInput.value)){ + this.lytOpts.minTileSz = this.lytOpts.maxTileSz; + } + this.onLytOptChg(); + }, + onTreeChg(){ + this.$emit('tree-change'); + }, + }, + components: {CloseIcon, }, + emits: ['settings-close', 'layout-option-change', 'tree-change', ], +}); +</script> + +<template> +<div class="fixed left-0 top-0 w-full h-full bg-black/40" @click="onCloseClick"> + <div class="absolute left-1/2 -translate-x-1/2 w-4/5 top-1/2 -translate-y-1/2 max-h-[80%] + p-3 bg-stone-50 visible rounded-md shadow shadow-black"> + <close-icon @click="onCloseClick" ref="closeIcon" + class="block absolute top-2 right-2 w-6 h-6 hover:cursor-pointer" /> + <h1 class="text-xl font-bold mb-2">Settings</h1> + <hr class="border-stone-400"/> + <div> + <label>Tile Spacing <input type="range" min="0" max="20" class="mx-2 w-[3cm]" + v-model.number="lytOpts.tileSpacing" @input="onLytOptChg"/></label> + </div> + <hr class="border-stone-400"/> + <div> + <label> + <span class="inline-block w-[3cm]">Min Tile Size</span> + <input type="range" min="0" max="400" v-model.number="lytOpts.minTileSz" class="w-[3cm]" + @input="onMinTileSzChg" ref="minTileSzInput"/> + </label> + </div> + <div> + <label> + <span class="inline-block w-[3cm]">Max Tile Size</span> + <input type="range" min="0" max="400" v-model.number="lytOpts.maxTileSz" class="w-[3cm]" + @input="onMaxTileSzChg" ref="maxTileSzInput"/> + </label> + </div> + <hr class="border-stone-400"/> + <div> + Layout Method + <ul> + <li> + <label> <input type="radio" v-model="lytOpts.layoutType" value="sqr" + @change="onLytOptChg"/> Squares </label> + </li> + <li> + <label> <input type="radio" v-model="lytOpts.layoutType" value="rect" + @change="onLytOptChg"/> Rectangles </label> + </li> + <li> + <label> <input type="radio" v-model="lytOpts.layoutType" value="sweep" + @change="onLytOptChg"/> Sweep to side </label> + </li> + </ul> + </div> + <hr class="border-stone-400"/> + <div> + <label> <input type="checkbox" v-model="lytOpts.sweepToParent" + @change="onLytOptChg"/> Sweep to parent</label> + </div> + <hr class="border-stone-400"/> + <div> + Sweep Mode + <ul> + <li> + <label> <input type="radio" v-model="lytOpts.sweepMode" value="left" + @change="onLytOptChg"/> To left </label> + </li> + <li> + <label> <input type="radio" v-model="lytOpts.sweepMode" value="top" + @change="onLytOptChg"/> To top </label> + </li> + <li> + <label> <input type="radio" v-model="lytOpts.sweepMode" value="shorter" + @change="onLytOptChg"/> To shorter </label> + </li> + <li> + <label> <input type="radio" v-model="lytOpts.sweepMode" value="auto" + @change="onLytOptChg"/> Auto </label> + </li> + </ul> + </div> + <hr class="border-stone-400"/> + <div> + <label>Animation Duration <input type="range" min="0" max="3000" class="mx-2 w-[3cm]" + v-model.number="uiOpts.tileChgDuration"/></label> + </div> + <hr class="border-stone-400"/> + <div> + Tree + <ul> + <li> + <label> <input type="radio" v-model="uiOpts.useReducedTree" :value="false" + @change="onTreeChg"/> Default </label> + </li> + <li> + <label> <input type="radio" v-model="uiOpts.useReducedTree" :value="true" + @change="onTreeChg"/> Reduced </label> + </li> + </ul> + </div> + </div> +</div> +</template> diff --git a/src/components/SettingsPane.vue b/src/components/SettingsPane.vue deleted file mode 100644 index cf046c3..0000000 --- a/src/components/SettingsPane.vue +++ /dev/null @@ -1,136 +0,0 @@ -<script lang="ts"> -import {defineComponent, PropType} from 'vue'; -import CloseIcon from './icon/CloseIcon.vue'; -import type {LayoutOptions} from '../layout'; - -// Displays configurable options, and sends option-change requests -export default defineComponent({ - props: { - lytOpts: {type: Object as PropType<LayoutOptions>, required: true}, - uiOpts: {type: Object, required: true}, - }, - methods: { - onCloseClick(evt: Event){ - if (evt.target == this.$el || (this.$refs.closeIcon as typeof CloseIcon).$el.contains(evt.target)){ - this.$emit('settings-close'); - } - }, - onLytOptChg(){ - this.$emit('layout-option-change'); - }, - onMinTileSzChg(){ - let minInput = this.$refs.minTileSzInput as HTMLInputElement; - let maxInput = this.$refs.maxTileSzInput as HTMLInputElement; - if (Number(minInput.value) > Number(maxInput.value)){ - this.lytOpts.maxTileSz = this.lytOpts.minTileSz; - } - this.onLytOptChg(); - }, - onMaxTileSzChg(){ - let minInput = this.$refs.minTileSzInput as HTMLInputElement; - let maxInput = this.$refs.maxTileSzInput as HTMLInputElement; - if (Number(maxInput.value) < Number(minInput.value)){ - this.lytOpts.minTileSz = this.lytOpts.maxTileSz; - } - this.onLytOptChg(); - }, - onTreeChg(){ - this.$emit('tree-change'); - }, - }, - components: {CloseIcon, }, - emits: ['settings-close', 'layout-option-change', 'tree-change', ], -}); -</script> - -<template> -<div class="absolute bottom-4 right-4 min-w-[5cm] p-3 bg-stone-50 visible rounded-md shadow shadow-black"> - <close-icon @click="onCloseClick" ref="closeIcon" - class="block absolute top-2 right-2 w-6 h-6 hover:cursor-pointer" /> - <h1 class="text-xl font-bold mb-2">Settings</h1> - <hr class="border-stone-400"/> - <div> - <label>Tile Spacing <input type="range" min="0" max="20" class="mx-2 w-[3cm]" - v-model.number="lytOpts.tileSpacing" @input="onLytOptChg"/></label> - </div> - <hr class="border-stone-400"/> - <div> - <label> - <span class="inline-block w-[3cm]">Min Tile Size</span> - <input type="range" min="0" max="400" v-model.number="lytOpts.minTileSz" class="w-[3cm]" - @input="onMinTileSzChg" ref="minTileSzInput"/> - </label> - </div> - <div> - <label> - <span class="inline-block w-[3cm]">Max Tile Size</span> - <input type="range" min="0" max="400" v-model.number="lytOpts.maxTileSz" class="w-[3cm]" - @input="onMaxTileSzChg" ref="maxTileSzInput"/> - </label> - </div> - <hr class="border-stone-400"/> - <div> - Layout Method - <ul> - <li> - <label> <input type="radio" v-model="lytOpts.layoutType" value="sqr" - @change="onLytOptChg"/> Squares </label> - </li> - <li> - <label> <input type="radio" v-model="lytOpts.layoutType" value="rect" - @change="onLytOptChg"/> Rectangles </label> - </li> - <li> - <label> <input type="radio" v-model="lytOpts.layoutType" value="sweep" - @change="onLytOptChg"/> Sweep to side </label> - </li> - </ul> - </div> - <hr class="border-stone-400"/> - <div> - <label> <input type="checkbox" v-model="lytOpts.sweepToParent" - @change="onLytOptChg"/> Sweep to parent</label> - </div> - <hr class="border-stone-400"/> - <div> - Sweep Mode - <ul> - <li> - <label> <input type="radio" v-model="lytOpts.sweepMode" value="left" - @change="onLytOptChg"/> To left </label> - </li> - <li> - <label> <input type="radio" v-model="lytOpts.sweepMode" value="top" - @change="onLytOptChg"/> To top </label> - </li> - <li> - <label> <input type="radio" v-model="lytOpts.sweepMode" value="shorter" - @change="onLytOptChg"/> To shorter </label> - </li> - <li> - <label> <input type="radio" v-model="lytOpts.sweepMode" value="auto" - @change="onLytOptChg"/> Auto </label> - </li> - </ul> - </div> - <hr class="border-stone-400"/> - <div> - <label>Animation Duration <input type="range" min="0" max="3000" class="mx-2 w-[3cm]" - v-model.number="uiOpts.tileChgDuration"/></label> - </div> - <hr class="border-stone-400"/> - <div> - Tree - <ul> - <li> - <label> <input type="radio" v-model="uiOpts.useReducedTree" :value="false" - @change="onTreeChg"/> Default </label> - </li> - <li> - <label> <input type="radio" v-model="uiOpts.useReducedTree" :value="true" - @change="onTreeChg"/> Reduced </label> - </li> - </ul> - </div> -</div> -</template> |
