From 436e0a59103693c709892070a94e35959ccab6f2 Mon Sep 17 00:00:00 2001 From: Sir Blob Date: Mon, 1 Dec 2025 09:10:55 +0000 Subject: [PATCH] feat: Implement inline grouping for TuiLine components within TuiGroup, enhancing layout and music player UI. --- src/lib/assets/css/tui-body.css | 3 +- src/lib/components/tui/TuiCard.svelte | 15 ++-- src/lib/components/tui/TuiGroup.svelte | 91 +++++++++++++++++++++---- src/lib/components/tui/TuiLine.svelte | 2 +- src/routes/about/+page.svelte | 94 ++++++++++++++++++-------- 5 files changed, 150 insertions(+), 55 deletions(-) diff --git a/src/lib/assets/css/tui-body.css b/src/lib/assets/css/tui-body.css index 022029a..96f955c 100644 --- a/src/lib/assets/css/tui-body.css +++ b/src/lib/assets/css/tui-body.css @@ -24,7 +24,8 @@ align-items: flex-start; } -.tui-inline-group:has(.inline-image) .inline-content { +.tui-inline-group:has(.inline-image) .inline-content, +.tui-inline-group:has(.inline-image) .tui-group { flex: 1; min-width: 0; } diff --git a/src/lib/components/tui/TuiCard.svelte b/src/lib/components/tui/TuiCard.svelte index dbf66ab..936313d 100644 --- a/src/lib/components/tui/TuiCard.svelte +++ b/src/lib/components/tui/TuiCard.svelte @@ -94,9 +94,7 @@ {#each titleSegments as segment} {#if getSegmentStyle(segment)} - {segment.text} + {segment.text} {:else} {segment.text} {/if} @@ -107,11 +105,7 @@
{#if line.image} - {line.imageAlt + {line.imageAlt {/if}
{#each segments as segment} @@ -249,7 +243,10 @@ .card-children.grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-template-columns: repeat( + auto-fill, + minmax(max(200px, calc((100% - 5rem) / 6)), 1fr) + ); gap: 1rem; } diff --git a/src/lib/components/tui/TuiGroup.svelte b/src/lib/components/tui/TuiGroup.svelte index 51a3937..2465174 100644 --- a/src/lib/components/tui/TuiGroup.svelte +++ b/src/lib/components/tui/TuiGroup.svelte @@ -31,6 +31,47 @@ }), ); + // Group consecutive inline elements + const processedChildren = $derived.by(() => { + const groups: Array< + | { kind: "single"; index: number; line: TerminalLine } + | { + kind: "inline"; + items: Array<{ index: number; line: TerminalLine }>; + } + > = []; + let i = 0; + + while (i < parsedChildren.length) { + const child = parsedChildren[i]; + const isInline = child.line.inline || child.line.display === "inline"; + + if (isInline) { + const inlineItems: Array<{ + index: number; + line: TerminalLine; + }> = []; + while (i < parsedChildren.length) { + const nextChild = parsedChildren[i]; + const nextIsInline = + nextChild.line.inline || nextChild.line.display === "inline"; + if (!nextIsInline) break; + + inlineItems.push({ + index: i, + line: nextChild.line, + }); + i++; + } + groups.push({ kind: "inline", items: inlineItems }); + } else { + groups.push({ kind: "single", index: i, line: child.line }); + i++; + } + } + return groups; + }); + // Style for the group container const groupStyle = $derived(() => { const styles: string[] = []; @@ -64,19 +105,38 @@ style={groupStyle()} id={line.id} > - {#each parsedChildren as parsed, idx (idx)} - + {#each processedChildren as group} + {#if group.kind === "inline"} +
+ {#each group.items as item} + + {/each} +
+ {:else} + + {/if} {/each}
@@ -95,7 +155,10 @@ .tui-group.grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-template-columns: repeat( + auto-fill, + minmax(max(200px, calc((100% - 3.75rem) / 6)), 1fr) + ); width: 100%; } diff --git a/src/lib/components/tui/TuiLine.svelte b/src/lib/components/tui/TuiLine.svelte index 8b4e59a..0ecf2b3 100644 --- a/src/lib/components/tui/TuiLine.svelte +++ b/src/lib/components/tui/TuiLine.svelte @@ -138,7 +138,7 @@ {line.imageAlt {#if line.content}{line.content}{/if}
diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte index 8d7d61d..c726d5e 100644 --- a/src/routes/about/+page.svelte +++ b/src/routes/about/+page.svelte @@ -76,37 +76,71 @@ terminal.updateById("music-player", { children: [ { - type: "output", - content: `(&primary)Now Playing:(&)`, - inline: true, - }, - { - type: "link", - content: `(&blue)${song.title}(&)`, - href: song.url, - inline: true, - external: true, - }, - { type: "blank", content: "" }, - { - type: "output", - content: `(&primary)Artist:(&)`, - inline: true, - }, - { - type: "link", - content: `(&blue)${song.author}(&)`, - href: song.authorUrl, - inline: true, - external: true, - }, - { - type: "progress", + type: "image", content: "", - progress: progress, - progressLabel: `${formatTime(Math.floor((progress / 100) * parseDuration(song.duration || "0:00")))} / ${song.duration}`, - inline: false, - progressStyle: "text", + image: song.thumbnail, + imageAlt: song.title, + inline: true, + imageWidth: 200, + }, + { + type: "group", + content: "", + groupDirection: "column", + groupAlign: "stretch", + inline: true, + children: [ + { + type: "group", + content: "", + groupDirection: "row", + groupAlign: "center", + inline: false, + children: [ + { + type: "output", + content: `(&primary)Now Playing:(&)`, + inline: true, + }, + { + type: "link", + content: `(&blue)${song.title}(&)`, + href: song.url, + inline: true, + external: true, + }, + ] + }, + { + type: "group", + content: "", + groupDirection: "row", + groupAlign: "center", + inline: false, + children: [ + { + type: "output", + content: `(&primary)Artist:(&)`, + inline: true, + }, + { + type: "link", + content: `(&blue)${song.author}(&)`, + href: song.authorUrl, + inline: true, + external: true, + }, + ] + }, + { + type: "progress", + content: "", + progress: progress, + progressLabel: `${formatTime(Math.floor((progress / 100) * parseDuration(song.duration || "0:00")))} / ${song.duration}`, + inline: false, + progressStyle: "text", + }, + ] }, { type: "group",