diff options
Diffstat (limited to 'lib/components')
| -rw-r--r-- | lib/components/AppTitle.svelte | 41 | ||||
| -rw-r--r-- | lib/components/AppVersion.svelte | 20 | ||||
| -rw-r--r-- | lib/components/BeginActions.svelte | 50 | ||||
| -rw-r--r-- | lib/components/BeginScreen.svelte | 48 | ||||
| -rw-r--r-- | lib/components/InitialLoadScreen.svelte | 56 | ||||
| -rw-r--r-- | lib/components/MenuButton.svelte | 51 | ||||
| -rw-r--r-- | lib/components/ProgressBar.svelte | 34 |
7 files changed, 300 insertions, 0 deletions
diff --git a/lib/components/AppTitle.svelte b/lib/components/AppTitle.svelte new file mode 100644 index 0000000..ce5c859 --- /dev/null +++ b/lib/components/AppTitle.svelte @@ -0,0 +1,41 @@ +<script lang="ts"> + interface Props { + size?: number + subtitle?: string | null + letterSpacing?: number + } + + let { size = 38, subtitle = null, letterSpacing = 2 }: Props = $props() +</script> + +<div class="app-title"> + <p class="name" style:font-size="{size}px" style:letter-spacing="{letterSpacing}px"> + Hollowdark + </p> + {#if subtitle} + <p class="subtitle">{subtitle}</p> + {/if} +</div> + +<style> + .app-title { + text-align: center; + } + + .name { + font-family: var(--font-body); + font-style: italic; + font-weight: 400; + color: var(--color-text); + margin: 0 0 var(--space-6); + } + + .subtitle { + font-family: var(--font-ui); + font-size: 11px; + color: var(--color-text-tertiary); + letter-spacing: 2px; + text-transform: uppercase; + margin: 0; + } +</style> diff --git a/lib/components/AppVersion.svelte b/lib/components/AppVersion.svelte new file mode 100644 index 0000000..315a47b --- /dev/null +++ b/lib/components/AppVersion.svelte @@ -0,0 +1,20 @@ +<script lang="ts"> + import { APP_VERSION } from '@hollowdark/lib/version' +</script> + +<p class="app-version">v {APP_VERSION}</p> + +<style> + .app-version { + position: absolute; + bottom: var(--space-6); + left: 0; + right: 0; + margin: 0; + text-align: center; + font-family: var(--font-ui); + font-size: 10px; + color: #3d382f; + letter-spacing: 1px; + } +</style> diff --git a/lib/components/BeginActions.svelte b/lib/components/BeginActions.svelte new file mode 100644 index 0000000..3ed96c4 --- /dev/null +++ b/lib/components/BeginActions.svelte @@ -0,0 +1,50 @@ +<script lang="ts"> + import MenuButton from '@hollowdark/lib/components/MenuButton.svelte' + import type { BeginState } from '@hollowdark/loading/session' + + interface Props { + state: BeginState + onBegin: () => void + onContinue?: () => void + onSettings: () => void + onCredits: () => void + } + + let { + state, + onBegin, + onContinue, + onSettings, + onCredits + }: Props = $props() + + function handleContinue(): void { + onContinue?.() + } +</script> + +<div class="begin-actions"> + {#if state.kind === 'first-ever'} + <MenuButton variant="primary" onclick={onBegin}>Begin</MenuButton> + {:else if state.kind === 'returning-active'} + <MenuButton variant="primary" onclick={handleContinue}> + Continue {state.characterName}'s life + </MenuButton> + <MenuButton variant="secondary" onclick={onBegin}>Begin a new life</MenuButton> + {:else} + <MenuButton variant="primary" onclick={handleContinue}>Continue</MenuButton> + <MenuButton variant="secondary" onclick={onBegin}>Begin a new life</MenuButton> + {/if} + + <MenuButton variant="tertiary" onclick={onSettings}>Settings</MenuButton> + <MenuButton variant="tertiary" onclick={onCredits}>Credits</MenuButton> +</div> + +<style> + .begin-actions { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--space-8); + } +</style> diff --git a/lib/components/BeginScreen.svelte b/lib/components/BeginScreen.svelte new file mode 100644 index 0000000..5832a42 --- /dev/null +++ b/lib/components/BeginScreen.svelte @@ -0,0 +1,48 @@ +<script lang="ts"> + import AppTitle from '@hollowdark/lib/components/AppTitle.svelte' + import AppVersion from '@hollowdark/lib/components/AppVersion.svelte' + import BeginActions from '@hollowdark/lib/components/BeginActions.svelte' + import type { BeginState } from '@hollowdark/loading/session' + + interface Props { + state: BeginState + onBegin: () => void + onContinue?: () => void + onSettings: () => void + onCredits: () => void + } + + let { + state, + onBegin, + onContinue, + onSettings, + onCredits + }: Props = $props() +</script> + +<section class="begin"> + <div class="top"> + <AppTitle size={38} subtitle="A Literary Life Simulation" /> + </div> + + <BeginActions {state} {onBegin} {onContinue} {onSettings} {onCredits} /> + + <AppVersion /> +</section> + +<style> + .begin { + min-height: 100dvh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--space-12); + position: relative; + } + + .top { + margin-bottom: 120px; + } +</style> diff --git a/lib/components/InitialLoadScreen.svelte b/lib/components/InitialLoadScreen.svelte new file mode 100644 index 0000000..3800715 --- /dev/null +++ b/lib/components/InitialLoadScreen.svelte @@ -0,0 +1,56 @@ +<script lang="ts"> + import AppTitle from '@hollowdark/lib/components/AppTitle.svelte' + import ProgressBar from '@hollowdark/lib/components/ProgressBar.svelte' + import { loadingProgress } from '@hollowdark/loading/progress' + + const progress = $derived($loadingProgress) +</script> + +<section class="initial-load"> + <div class="top"> + <AppTitle size={32} letterSpacing={1} /> + </div> + + <div class="bar"> + <ProgressBar value={progress.percentage} /> + </div> + + <p class="message">{progress.currentMessage}</p> + <p class="note">This will happen once. It will not happen again.</p> +</section> + +<style> + .initial-load { + min-height: 100dvh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--space-12); + text-align: center; + } + + .top { + margin-bottom: 120px; + } + + .bar { + margin-bottom: var(--space-6); + } + + .message { + font-family: var(--font-ui); + font-size: 12px; + color: var(--color-text-secondary); + letter-spacing: 0.5px; + margin: 0 0 var(--space-2); + } + + .note { + font-family: var(--font-ui); + font-size: 11px; + color: var(--color-text-tertiary); + letter-spacing: 0.3px; + margin: 0; + } +</style> diff --git a/lib/components/MenuButton.svelte b/lib/components/MenuButton.svelte new file mode 100644 index 0000000..1753155 --- /dev/null +++ b/lib/components/MenuButton.svelte @@ -0,0 +1,51 @@ +<script lang="ts"> + type Variant = 'primary' | 'secondary' | 'tertiary' + + interface Props { + variant?: Variant + onclick: () => void + children: import('svelte').Snippet + } + + let { variant = 'primary', onclick, children }: Props = $props() +</script> + +<button class="menu-button {variant}" {onclick}> + {@render children()} +</button> + +<style> + .menu-button { + font-family: var(--font-body); + letter-spacing: 0.3px; + transition: color var(--transition-fast); + } + + .primary { + font-size: var(--text-lg); + color: var(--color-accent); + letter-spacing: 0.5px; + } + + .primary:hover { + color: var(--color-text); + } + + .secondary { + font-size: 15px; + color: var(--color-text-secondary); + } + + .secondary:hover { + color: var(--color-text); + } + + .tertiary { + font-size: 13px; + color: var(--color-text-tertiary); + } + + .tertiary:hover { + color: var(--color-text-secondary); + } +</style> diff --git a/lib/components/ProgressBar.svelte b/lib/components/ProgressBar.svelte new file mode 100644 index 0000000..21c9e68 --- /dev/null +++ b/lib/components/ProgressBar.svelte @@ -0,0 +1,34 @@ +<script lang="ts"> + interface Props { + value: number + width?: number + } + + let { value, width = 320 }: Props = $props() + + const percentage = $derived(Math.max(0, Math.min(1, value)) * 100) +</script> + +<div class="progress-track" style:width="{width}px"> + <div class="progress-fill" style:width="{percentage}%"></div> +</div> + +<style> + .progress-track { + height: 2px; + background: rgba(232, 226, 213, 0.06); + border-radius: 1px; + position: relative; + overflow: hidden; + } + + .progress-fill { + position: absolute; + top: 0; + left: 0; + height: 100%; + background: var(--color-accent); + border-radius: 1px; + transition: width 300ms ease-out; + } +</style> |
