diff options
| author | Terry Truong <terry06890@gmail.com> | 2022-07-03 20:37:46 +1000 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2022-07-03 23:25:28 +1000 |
| commit | 567a21a8d0498f467f558d9ec1a6db8f1b52c0e6 (patch) | |
| tree | e08d687d05acf648c2a0d877455556dfdef632d8 | |
| parent | 89fc34f82956f2410ee7f1d90e03945e10805dda (diff) | |
Add SCollapsible component
Also update info-modal source-info styling
| -rw-r--r-- | src/App.vue | 7 | ||||
| -rw-r--r-- | src/README.md | 1 | ||||
| -rw-r--r-- | src/components/HelpModal.vue | 39 | ||||
| -rw-r--r-- | src/components/SCollapsible.vue | 39 | ||||
| -rw-r--r-- | src/components/TileInfoModal.vue | 113 | ||||
| -rw-r--r-- | src/components/icon/DownIcon.vue | 11 | ||||
| -rw-r--r-- | src/lib.ts | 2 |
7 files changed, 129 insertions, 83 deletions
diff --git a/src/App.vue b/src/App.vue index 47bbd1e..f98e4e9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -277,12 +277,6 @@ export default defineComponent({ this.handleActionForTutorial('settings'); } }, - helpOpen(newVal, oldVal){ - // Possibly trigger tutorial advance - if (newVal == false){ - this.handleActionForTutorial('help'); - } - }, }, methods: { // For tile expand/collapse events @@ -758,6 +752,7 @@ export default defineComponent({ } this.resetMode(); this.helpOpen = true; + this.handleActionForTutorial('help'); }, // For tutorial-pane events onTutPaneClose(): void { diff --git a/src/README.md b/src/README.md index 65f9a49..3171046 100644 --- a/src/README.md +++ b/src/README.md @@ -11,6 +11,7 @@ - TutorialPane.vue: Displays tutorial content. - SButton.vue: Simple button component. - IconButton.vue: Simple button component containing an SVG icon. + - SCollapsible.vue: Simple collapsible-content component. - icon: Contains components that display SVG icons. - lib.ts: Contains classes/types and utility functions. - layout.ts: Contains code for laying out Tiles. diff --git a/src/components/HelpModal.vue b/src/components/HelpModal.vue index f2ae8a4..f410d42 100644 --- a/src/components/HelpModal.vue +++ b/src/components/HelpModal.vue @@ -6,24 +6,35 @@ class="block absolute top-1 right-1 md:top-2 md:right-2 w-8 h-8 hover:cursor-pointer"/> <h1 class="text-center text-xl font-bold py-2 border-b border-stone-400">Help</h1> <div class="p-2 border-b border-stone-400"> - <div> - Lorem ipsum dolor sit amet, consectetur adipiscing - elit, sed do eiusmod tempor incididunt ut labore - et dolore magna aliqua. - </div> + <s-collapsible class="border border-stone-400 rounded"> + <template v-slot:summary="slotProps"> + <div class="p-1 text-center" + :style="{backgroundColor: !slotProps.collapsed ? 'gray' : 'transparent'}"> + <down-icon class="inline-block w-5 h-5 transition-transform duration-300" + :class="{'-rotate-90': slotProps.collapsed}"/> + Summary text + </div> + </template> + <template v-slot:content> + <div class="p-1"> + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore + et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. + </div> + </template> + </s-collapsible> <ul class="list-disc ml-3"> <li>What is the Tree of Life? ('tips', )</li> - <li>Representing the Tree - (OneZoom, iTol) - (tile layout, overflown-root, ) - (leaf header colors, asterisk, compound nodes/names/images, ) - </li> - <li>Data sources (OTOL, EOL, Wikipedia) (imprecision: tree, names, images, descs, )</li> - <li>Using tilo + <li>Visualising the Tree (OneZoom, iTol) (tile layout, )</li> + <li>Using Tilo (tutorial) + (leaf header colors, asterisk, compound nodes/names/images, overflown-root, ) (settings: layout methods, reduced trees, click-label-to-reset) (keyboard shortcuts) </li> + <li>Data sources (OTOL, EOL, Wikipedia) (imprecision: tree, names, images, descs, )</li> <li>Project page, error contact, other credits (feathericons, ionicons), </li> </ul> </div> @@ -38,7 +49,9 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import SButton from './SButton.vue'; +import SCollapsible from './SCollapsible.vue'; import CloseIcon from './icon/CloseIcon.vue'; +import DownIcon from './icon/DownIcon.vue'; import {UiOptions} from '../lib'; export default defineComponent({ @@ -66,7 +79,7 @@ export default defineComponent({ this.$emit('close'); }, }, - components: {SButton, CloseIcon, }, + components: {SButton, SCollapsible, CloseIcon, DownIcon, }, emits: ['close', 'start-tutorial', ], }); </script> diff --git a/src/components/SCollapsible.vue b/src/components/SCollapsible.vue new file mode 100644 index 0000000..4b414fc --- /dev/null +++ b/src/components/SCollapsible.vue @@ -0,0 +1,39 @@ +<template> +<div :style="styles"> + <div class="hover:cursor-pointer" @click="collapsed = !collapsed"> + <slot name="summary" :collapsed="collapsed">(Summary)</slot> + </div> + <div :style="contentStyles" ref="content"> + <slot name="content">(Content)</slot> + </div> +</div> +</template> + +<script lang="ts"> +import {defineComponent, PropType} from 'vue'; + +export default defineComponent({ + data(){ + return { + collapsed: true, + }; + }, + computed: { + styles(): Record<string,string> { + return { + overflow: this.collapsed ? 'hidden' : 'visible', + }; + }, + contentStyles(): Record<string,string> { + return { + overflow: 'hidden', + maxHeight: this.collapsed ? '0' : (this.$refs.content as HTMLDivElement).scrollHeight + 'px', + opacity: this.collapsed ? '0' : '1', + transitionProperty: 'max-height, opacity', + transitionDuration: '300ms', + transitionTimingFunction: 'ease-in-out', + }; + }, + }, +}); +</script> diff --git a/src/components/TileInfoModal.vue b/src/components/TileInfoModal.vue index 6b7bd26..e1b31db 100644 --- a/src/components/TileInfoModal.vue +++ b/src/components/TileInfoModal.vue @@ -1,7 +1,7 @@ <template> <div class="fixed left-0 top-0 w-full h-full bg-black/40" @click="onClose"> <div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 - max-w-[80%] min-w-[8cm] md:min-w-[15cm] max-h-[80%]" + max-w-[80%] min-w-[8cm] md:min-w-[14cm] max-h-[80%]" :style="styles"> <div class="pb-1 md:pb-2"> <div class="flex"> @@ -32,53 +32,54 @@ </div> <div v-else> <div v-if="imgInfos[idx] != null" class="mt-1 mr-2 md:mb-2 md:mr-4 md:float-left"> - <a :href="imgInfos[idx]!.url" target="_blank" class="block w-fit mx-auto"> + <a :href="imgInfos[idx]!.url != '' ? imgInfos[idx]!.url : 'javascript:;'" + :target="imgInfos[idx]!.url != '' ? '_blank' : ''" class="block w-fit mx-auto"> <div :style="getImgStyles(nodes[idx])"/> </a> - <div class="relative"> - <details class="w-fit mx-auto text-sm hover:cursor-pointer" - @click="onDetailsClick($event, idx)" ref="srcInfoDetails"> - <summary>Source information</summary> - <transition name="fade" @after-leave="onSrcInfoHideTransition(idx)"> - <div v-if="srcInfoShow[idx]" class="absolute left-1/2 -translate-x-1/2 w-max max-w-full - md:left-0 md:translate-x-0 md:max-w-[14cm] pb-2"> <!-- Provides bottom-padding --> - <ul class="rounded shadow p-1 overflow-auto" - :style="{backgroundColor: uiOpts.bgColor, color: uiOpts.textColor}"> - <li v-if="imgInfos[idx]!.url != ''"> - <span :style="{color: uiOpts.altColor}">Source: </span> - <a :href="imgInfos[idx]!.url" target="_blank">Link</a> - <external-link-icon class="inline-block w-3 h-3 ml-1"/> - </li> - <li v-if="imgInfos[idx]!.artist != ''"> - <span :style="{color: uiOpts.altColor}">Artist: </span> - {{imgInfos[idx]!.artist}} - </li> - <li v-if="imgInfos[idx]!.credit != ''"> - <span :style="{color: uiOpts.altColor}">Credits: </span> - {{imgInfos[idx]!.credit}} - </li> - <li> - <span :style="{color: uiOpts.altColor}">License: </span> - <a :href="licenseToUrl(imgInfos[idx]!.license)" target="_blank"> - {{imgInfos[idx]!.license}} - </a> - <external-link-icon class="inline-block w-3 h-3 ml-1"/> - </li> - <li v-if="imgInfos[idx]!.src != 'picked'"> - <span :style="{color: uiOpts.altColor}">Obtained via: </span> - <a v-if="imgInfos[idx]!.src == 'eol'" href="https://eol.org/">EoL</a> - <a v-else href="https://www.wikipedia.org/">Wikipedia</a> - <external-link-icon class="inline-block w-3 h-3 ml-1"/> - </li> - <li> - <span :style="{color: uiOpts.altColor}">Changes: </span> - Cropped and resized - </li> - </ul> - </div> - </transition> - </details> - </div> + <s-collapsible class="text-sm text-center max-w-full md:max-w-[200px] mx-auto"> + <template v-slot:summary="slotProps"> + <div class="py-1"> + <down-icon class="inline-block w-4 h-4 transition-transform duration-300" + :class="{'-rotate-90': !slotProps.collapsed}"/> + Source Information + </div> + </template> + <template v-slot:content> + <ul class="rounded shadow overflow-x-auto p-1" + :style="{backgroundColor: uiOpts.bgColor, color: uiOpts.textColor}"> + <li v-if="imgInfos[idx]!.url != ''"> + <span :style="{color: uiOpts.altColor}">Source: </span> + <a :href="imgInfos[idx]!.url" target="_blank">Link</a> + <external-link-icon class="inline-block w-3 h-3 ml-1"/> + </li> + <li v-if="imgInfos[idx]!.artist != ''" class="whitespace-nowrap"> + <span :style="{color: uiOpts.altColor}">Artist: </span> + {{imgInfos[idx]!.artist}} + </li> + <li v-if="imgInfos[idx]!.credit != ''" class="whitespace-nowrap"> + <span :style="{color: uiOpts.altColor}">Credits: </span> + {{imgInfos[idx]!.credit}} + </li> + <li> + <span :style="{color: uiOpts.altColor}">License: </span> + <a :href="licenseToUrl(imgInfos[idx]!.license)" target="_blank"> + {{imgInfos[idx]!.license}} + </a> + <external-link-icon class="inline-block w-3 h-3 ml-1"/> + </li> + <li v-if="imgInfos[idx]!.src != 'picked'"> + <span :style="{color: uiOpts.altColor}">Obtained via: </span> + <a v-if="imgInfos[idx]!.src == 'eol'" href="https://eol.org/">EoL</a> + <a v-else href="https://www.wikipedia.org/">Wikipedia</a> + <external-link-icon class="inline-block w-3 h-3 ml-1"/> + </li> + <li> + <span :style="{color: uiOpts.altColor}">Changes: </span> + Cropped and resized + </li> + </ul> + </template> + </s-collapsible> </div> <div v-if="descInfos[idx]! != null"> <div>{{descInfos[idx]!.text}}</div> @@ -101,8 +102,10 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; +import SCollapsible from './SCollapsible.vue'; import CloseIcon from './icon/CloseIcon.vue'; import ExternalLinkIcon from './icon/ExternalLinkIcon.vue'; +import DownIcon from './icon/DownIcon.vue'; import {TolNode, TolMap} from '../tol'; import {LayoutNode, LayoutOptions} from '../layout'; import {getImagePath, DescInfo, ImgInfo, NodeInfo, InfoResponse, UiOptions} from '../lib'; @@ -117,11 +120,6 @@ export default defineComponent({ lytOpts: {type: Object as PropType<LayoutOptions>, required: true}, uiOpts: {type: Object as PropType<UiOptions>, required: true}, }, - data(){ - return { - srcInfoShow: [false, false], // For transitioning source-info panes when enclosing <details> are clicked - }; - }, computed: { tolNode(): TolNode { return this.infoResponse.nodeInfo.tolNode; @@ -221,19 +219,8 @@ export default defineComponent({ this.$emit('close'); } }, - onDetailsClick(evt: Event, idx: number){ - this.srcInfoShow[idx] = !this.srcInfoShow[idx]; - if (this.srcInfoShow[idx] == false){ - evt.preventDefault(); // Delay <details> closure, to allow for transition - } - }, - onSrcInfoHideTransition(idx: number){ - // Close <details>, now that it's content has transitioned away - let details = this.$refs.srcInfoDetails[idx]; - details.removeAttribute('open'); - }, }, - components: {CloseIcon, ExternalLinkIcon, }, + components: {SCollapsible, CloseIcon, ExternalLinkIcon, DownIcon, }, emits: ['close', ], }); </script> diff --git a/src/components/icon/DownIcon.vue b/src/components/icon/DownIcon.vue new file mode 100644 index 0000000..dc954d1 --- /dev/null +++ b/src/components/icon/DownIcon.vue @@ -0,0 +1,11 @@ +<template> +<svg viewBox="0 0 24 24" fill="none" + stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> + <polyline points="6 9 12 15 18 9"></polyline> +</svg> +</template> + +<script lang="ts"> +import {defineComponent, PropType} from 'vue'; +export default defineComponent({}); +</script> @@ -137,7 +137,7 @@ export function getDefaultUiOpts(lytOpts: LayoutOptions): UiOptions { let bgColor = '#292524', bgColorLight = '#44403c', bgColorDark = '#1c1917', bgColorLight2 = '#57534e', bgColorDark2 = '#0e0c0b', - bgColorAlt = '#fafaf9', bgColorAltDark = '#a8a29e'; + bgColorAlt = '#f5f5f4', bgColorAltDark = '#a8a29e'; let altColor = '#a3e623', altColorDark = '#65a30d'; let accentColor = '#f59e0b'; let scrollGap = getScrollBarWidth(); |
