language-learning-app/frontend/src/routes/app/adventures/[id]/PreviousEntries.svelte
2026-05-06 22:51:55 +01:00

220 lines
5.5 KiB
Svelte

<script lang="ts">
type Props = {
entries: {
id: string;
text: string;
possibleChoices: {
id: string;
text: string;
isSelected: boolean;
}[];
}[];
};
const { entries }: Props = $props();
function toParagraphs(text: string): string[] {
return text
.split(/\n\s*\n/g)
.map((paragraph) => paragraph.trim())
.filter(Boolean);
}
</script>
{#if entries.length > 0}
<section class="previous-entries" aria-label="Previous story entries">
<header class="previous-entries__header">
<h2 class="previous-entries__title">Previous entries</h2>
</header>
<ol class="previous-entries__list">
{#each entries as entry, index (entry.id)}
<li class="previous-entries__item">
<article class="entry-card" aria-label={`Entry ${index + 1}`}>
<header class="entry-card__header">
<p class="entry-card__index">Entry {String(index + 1).padStart(2, '0')}</p>
</header>
<div class="entry-card__body">
{#each toParagraphs(entry.text) as paragraph, paragraphIndex (paragraphIndex)}
<p class="entry-card__paragraph">{paragraph}</p>
{/each}
</div>
{#if entry.possibleChoices.length > 0}
<footer class="entry-card__choices">
<p class="entry-card__choices-label">Possible choices</p>
<ul class="entry-card__choices-list" aria-label="Choices for this entry">
{#each entry.possibleChoices as choice, choiceIndex (choice.id)}
<li class="entry-card__choice" class:entry-card__choice--selected={choice.isSelected}>
<span class="entry-card__choice-index" aria-hidden="true"
>{String(choiceIndex + 1).padStart(2, '0')}</span
>
<span class="entry-card__choice-text">{choice.text}</span>
{#if choice.isSelected}
<span class="entry-card__choice-state">Selected</span>
{/if}
</li>
{/each}
</ul>
</footer>
{/if}
</article>
</li>
{/each}
</ol>
</section>
{/if}
<style>
.previous-entries {
--previous-surface: var(--color-surface-container-low);
--previous-surface-elevated: var(--color-surface-container-lowest);
max-width: 88rem;
border-radius: var(--radius-xl);
}
.previous-entries__header {
margin-bottom: var(--space-4);
}
.previous-entries__title {
margin: var(--space-1) 0 0;
font-family: var(--font-display);
font-size: clamp(1.3rem, 1.12rem + 0.85vw, 1.9rem);
line-height: 1.15;
color: var(--color-on-surface);
}
.previous-entries__list {
list-style: none;
padding: 0;
margin: 0;
display: grid;
gap: var(--space-3);
grid-template-columns: 1fr;
}
.entry-card {
padding: clamp(0.9rem, 0.8rem + 0.7vw, 1.4rem);
border-radius: var(--radius-lg);
background-color: var(--previous-surface-elevated);
}
.entry-card__header {
margin-bottom: var(--space-2);
}
.entry-card__index {
margin: 0;
font-family: var(--font-label);
font-size: var(--text-label-md);
font-weight: var(--weight-semibold);
letter-spacing: 0.08em;
text-transform: uppercase;
color: color-mix(in srgb, var(--color-on-surface) 72%, transparent);
}
.entry-card__body::-webkit-scrollbar {
width: 0.65rem;
}
.entry-card__body::-webkit-scrollbar-track {
background: transparent;
}
.entry-card__body::-webkit-scrollbar-thumb {
background-color: color-mix(in srgb, var(--colour-yellow-300) 26%, transparent);
border: 0.16rem solid transparent;
border-radius: var(--radius-full);
background-clip: content-box;
}
.entry-card__paragraph {
font-family: var(--font-body);
font-size: clamp(1rem, 0.97rem + 0.2vw, 1.12rem);
line-height: var(--leading-loose);
color: var(--color-on-surface);
text-wrap: pretty;
}
.entry-card__paragraph + .entry-card__paragraph {
margin-top: var(--space-3);
padding-top: var(--space-3);
}
.entry-card__choices {
margin-top: var(--space-3);
padding-top: var(--space-2);
}
.entry-card__choices-label {
margin: 0 0 var(--space-2);
font-family: var(--font-label);
font-size: var(--text-label-md);
font-weight: var(--weight-medium);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: color-mix(in srgb, var(--color-on-surface) 72%, transparent);
}
.entry-card__choices-list {
list-style: none;
margin: 0;
padding: 0;
display: grid;
gap: var(--space-2);
}
.entry-card__choice {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: start;
gap: var(--space-2);
padding: var(--space-2);
border-radius: var(--radius-md);
}
.entry-card__choice-index {
font-family: var(--font-label);
font-size: var(--text-label-md);
font-weight: var(--weight-medium);
letter-spacing: var(--tracking-wide);
color: color-mix(in srgb, var(--color-on-surface) 62%, transparent);
}
.entry-card__choice-text {
font-family: var(--font-body);
font-size: var(--text-body-lg);
line-height: var(--leading-relaxed);
color: color-mix(in srgb, var(--color-on-surface) 84%, transparent);
text-wrap: pretty;
}
.entry-card__choice-state {
font-family: var(--font-label);
font-size: var(--text-label-md);
font-weight: var(--weight-medium);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--color-primary);
}
.entry-card__choice--selected {
background-color: color-mix(in srgb, var(--color-primary-container) 56%, transparent);
}
.entry-card__choice--selected .entry-card__choice-text {
color: var(--color-on-surface);
}
@media (max-width: 42rem) {
.previous-entries {
padding: var(--space-2);
}
.entry-card {
padding: var(--space-3);
}
}
</style>