All checks were successful
Build and Deploy Nuxt / build (push) Successful in 24s
86 lines
3.0 KiB
Vue
86 lines
3.0 KiB
Vue
<script setup lang="ts">
|
||
/* One page of the open book that holds one of the wiki's own surfaces — the
|
||
link map, the graphing calculator — instead of an article. The paper is the
|
||
same as an article's page: a spine with the title standing on end and the ×
|
||
that closes the page, click anywhere to turn back to it. What fills the
|
||
page is not scrolling prose but the live surface, edge to edge — its own
|
||
instance, kept warm beside the articles you are reading.
|
||
|
||
Everything but the spine of a page that isn't in view is `inert`: the map
|
||
won't take drags and the calculator won't take typing until you turn to it. */
|
||
import type { ToolPage } from '~/utils/routes'
|
||
|
||
const props = defineProps<{
|
||
/** which of the wiki's own pages this page holds */
|
||
tool: ToolPage
|
||
index: number
|
||
active: boolean
|
||
}>()
|
||
|
||
const emit = defineEmits<{
|
||
activate: []
|
||
close: []
|
||
}>()
|
||
|
||
const { t } = useI18n()
|
||
const title = computed(() => t(TOOL_LABEL_KEYS[props.tool]))
|
||
|
||
function turnToThisPage() {
|
||
if (!props.active) emit('activate')
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<section
|
||
class="book-pane pane-tools"
|
||
:class="{ active }"
|
||
:data-tab="toolPageIdentity(tool)"
|
||
:data-index="index"
|
||
:style="{ '--i': index }"
|
||
:aria-label="t('pane.aria', { title })"
|
||
@click="turnToThisPage"
|
||
>
|
||
<div
|
||
class="pane-spine"
|
||
role="button"
|
||
tabindex="0"
|
||
:aria-current="active ? 'page' : undefined"
|
||
:aria-disabled="active"
|
||
:title="t('pane.spineHint', { title })"
|
||
@click.stop="turnToThisPage"
|
||
@keydown.enter.prevent="turnToThisPage"
|
||
>
|
||
<button
|
||
type="button"
|
||
class="spine-close"
|
||
:aria-label="t('common.closeTab')"
|
||
@click.stop="emit('close')"
|
||
>
|
||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" aria-hidden="true">
|
||
<path d="M6 6l12 12M18 6L6 18" />
|
||
</svg>
|
||
</button>
|
||
<!-- the surface's own mark, under the ×, so the spine reads as the
|
||
page it holds even fanned out among articles -->
|
||
<svg v-if="tool === 'graph'" class="spine-glyph" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<circle cx="18" cy="5" r="3" />
|
||
<circle cx="6" cy="12" r="3" />
|
||
<circle cx="18" cy="19" r="3" />
|
||
<path d="m8.6 10.5 6.8-4M8.6 13.5l6.8 4" />
|
||
</svg>
|
||
<svg v-else class="spine-glyph" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<path d="M4 3v17a1 1 0 0 0 1 1h17" />
|
||
<path d="M4.5 16.5c2.6 0 3.4-10.5 6.8-10.5s3.9 7 8.2 7" />
|
||
</svg>
|
||
<span class="spine-title">{{ title }}</span>
|
||
</div>
|
||
|
||
<div class="pane-body" :inert="active ? null : ''">
|
||
<div class="pane-stage">
|
||
<GraphStage v-if="tool === 'graph'" />
|
||
<CalculatorStage v-else />
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</template>
|