feat(frontend): assemble accessible application shell

This commit is contained in:
Justin Visser 2026-08-10 15:04:17 +02:00
parent 96c69507ec
commit 036ef3cc6f
27 changed files with 1852 additions and 13 deletions

View file

@ -0,0 +1,74 @@
<script setup lang="ts">
import { computed } from 'vue'
import type { PlaylistState } from '../lib/models'
const props = defineProps<{
state: PlaylistState
trackCount: number
canSave: boolean
}>()
defineEmits<{ save: [] }>()
const buttonLabel = computed(() => {
if (props.state.status === 'saving') return 'Saving...'
if (props.state.status === 'error') return 'Try saving again'
return 'Save as playlist'
})
</script>
<template>
<div class="actions">
<button
v-if="canSave"
class="save"
type="button"
:disabled="state.status === 'saving'"
@click="$emit('save')"
>
{{ buttonLabel }}
</button>
<a v-else class="connect" href="/api/auth/login">Connect Spotify to save</a>
<span class="summary">{{ trackCount }} verified tracks ready for a private playlist</span>
</div>
</template>
<style scoped>
.actions {
display: flex;
flex-wrap: wrap;
gap: var(--s-5);
align-items: center;
}
.save,
.connect {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: var(--tap-min);
padding: 11px var(--s-6);
color: var(--c-on-accent);
font-size: var(--t-small);
font-weight: 500;
text-decoration: none;
cursor: pointer;
background: var(--c-accent);
border: 1px solid var(--c-accent);
border-radius: var(--r-md);
transition: all var(--dur-fast) ease;
}
.save:hover,
.connect:hover {
color: var(--c-on-accent);
text-decoration: none;
background: var(--c-accent-hover);
border-color: var(--c-accent-hover);
}
.summary {
color: var(--c-text-faint);
font-family: var(--f-mono);
font-size: var(--t-micro);
}
</style>