ui: convert Image, Speech, Audio interfaces to shadcn buttons
Replace .btn elements and inline SVG icons with shadcn Button and @lucide/svelte icons in the image, speech and audio playground tabs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UmuGqwNBJNEAMaWsdCDqUC
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
import { transcribeAudio } from "../../lib/audioApi";
|
||||
import { playgroundStores } from "../../stores/playgroundActivity";
|
||||
import ModelSelector from "./ModelSelector.svelte";
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
import { Copy, Check } from "@lucide/svelte";
|
||||
|
||||
const selectedModelStore = persistentStore<string>("playground-audio-model", "");
|
||||
|
||||
@@ -169,22 +171,19 @@
|
||||
{:else if transcriptionResult}
|
||||
<div class="w-full h-full flex flex-col p-4">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<h3 class="font-medium">Transcription Result</h3>
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
<h3 class="pb-0 font-medium">Transcription Result</h3>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon-sm"
|
||||
onclick={copyToClipboard}
|
||||
title={copied ? 'Copied!' : 'Copy to clipboard'}
|
||||
>
|
||||
{#if copied}
|
||||
<svg class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
<Check class="text-success" />
|
||||
{:else}
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
<Copy />
|
||||
{/if}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-auto p-3 rounded border border-border bg-background whitespace-pre-wrap">
|
||||
{transcriptionResult}
|
||||
@@ -223,33 +222,21 @@
|
||||
onchange={handleFileSelect}
|
||||
bind:this={fileInput}
|
||||
/>
|
||||
<button
|
||||
class="btn"
|
||||
onclick={() => fileInput?.click()}
|
||||
disabled={isTranscribing}
|
||||
>
|
||||
<Button variant="outline" onclick={() => fileInput?.click()} disabled={isTranscribing}>
|
||||
Browse Files
|
||||
</button>
|
||||
</Button>
|
||||
<div class="flex-1"></div>
|
||||
{#if isTranscribing}
|
||||
<button class="btn bg-red-500 hover:bg-red-600 text-white" onclick={cancelTranscription}>
|
||||
Cancel
|
||||
</button>
|
||||
<Button variant="destructive" onclick={cancelTranscription}>Cancel</Button>
|
||||
{:else}
|
||||
<button
|
||||
class="btn bg-primary text-primary-foreground hover:opacity-90"
|
||||
onclick={transcribe}
|
||||
disabled={!canTranscribe}
|
||||
>
|
||||
Transcribe
|
||||
</button>
|
||||
<button
|
||||
class="btn"
|
||||
<Button onclick={transcribe} disabled={!canTranscribe}>Transcribe</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onclick={clearAll}
|
||||
disabled={!selectedFile && !transcriptionResult && !error}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import ModelSelector from "./ModelSelector.svelte";
|
||||
import ExpandableTextarea from "./ExpandableTextarea.svelte";
|
||||
import type { ImageApiMode, SdApiLora, SdApiLoraRef } from "../../lib/types";
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
|
||||
const selectedModelStore = persistentStore<string>("playground-image-model", "");
|
||||
const selectedSizeStore = persistentStore<string>("playground-image-size", "1024x1024");
|
||||
@@ -226,12 +227,9 @@
|
||||
</select>
|
||||
|
||||
{#if isSdapi}
|
||||
<button
|
||||
class="px-3 py-2 rounded border border-border bg-background hover:bg-accent transition-colors"
|
||||
onclick={() => showSettings = !showSettings}
|
||||
>
|
||||
<Button variant="outline" onclick={() => showSettings = !showSettings}>
|
||||
{showSettings ? "Hide Settings" : "Settings"}
|
||||
</button>
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -330,13 +328,14 @@
|
||||
<div>
|
||||
<span class="text-xs text-muted-foreground block mb-1">LoRAs</span>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<button
|
||||
class="px-3 py-1.5 text-sm rounded border border-border bg-background hover:bg-accent transition-colors disabled:opacity-50"
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onclick={loadLoras}
|
||||
disabled={!$selectedModelStore || isLoadingLoras}
|
||||
>
|
||||
{isLoadingLoras ? "Loading..." : lorasLoaded ? "Reload LoRAs" : "Load LoRAs"}
|
||||
</button>
|
||||
</Button>
|
||||
{#if lorasLoaded && availableLoras.length > 0}
|
||||
<select
|
||||
class="flex-1 px-2 py-1.5 text-sm rounded border border-border bg-background focus:outline-none focus:ring-2 focus:ring-primary"
|
||||
@@ -471,24 +470,25 @@
|
||||
/>
|
||||
<div class="flex flex-row md:flex-col gap-2">
|
||||
{#if isGenerating}
|
||||
<button class="btn bg-red-500 hover:bg-red-600 text-white flex-1 md:flex-none" onclick={cancelGeneration}>
|
||||
<Button variant="destructive" class="flex-1 md:flex-none" onclick={cancelGeneration}>
|
||||
Cancel
|
||||
</button>
|
||||
</Button>
|
||||
{:else}
|
||||
<button
|
||||
class="btn bg-primary text-primary-foreground hover:opacity-90 flex-1 md:flex-none"
|
||||
<Button
|
||||
class="flex-1 md:flex-none"
|
||||
onclick={generate}
|
||||
disabled={!prompt.trim() || !$selectedModelStore}
|
||||
>
|
||||
Generate
|
||||
</button>
|
||||
<button
|
||||
class="btn flex-1 md:flex-none"
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="flex-1 md:flex-none"
|
||||
onclick={clearImage}
|
||||
disabled={generatedImages.length === 0 && !error && !prompt.trim()}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
import { playgroundStores } from "../../stores/playgroundActivity";
|
||||
import ModelSelector from "./ModelSelector.svelte";
|
||||
import ExpandableTextarea from "./ExpandableTextarea.svelte";
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
import { RefreshCw, Download } from "@lucide/svelte";
|
||||
|
||||
const selectedModelStore = persistentStore<string>("playground-speech-model", "");
|
||||
const selectedVoiceStore = persistentStore<string>("playground-speech-voice", "coral");
|
||||
@@ -220,23 +222,16 @@
|
||||
<option value="(refresh)">(refresh)</option>
|
||||
</select>
|
||||
{#if $selectedModelStore && !getVoicesCache()[$selectedModelStore]}
|
||||
<button
|
||||
class="btn shrink-0"
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="shrink-0"
|
||||
onclick={refreshVoices}
|
||||
disabled={isLoadingVoices}
|
||||
title={isLoadingVoices ? "Loading voices..." : "Load voices for this model"}
|
||||
>
|
||||
{#if isLoadingVoices}
|
||||
<svg class="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
||||
</svg>
|
||||
{/if}
|
||||
</button>
|
||||
<RefreshCw class={isLoadingVoices ? "animate-spin" : ""} />
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -285,15 +280,9 @@
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<button
|
||||
class="btn shrink-0"
|
||||
onclick={downloadAudio}
|
||||
title="Download audio file"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<Button variant="outline" size="icon" class="shrink-0" onclick={downloadAudio} title="Download audio file">
|
||||
<Download />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<!-- Audio player with larger controls -->
|
||||
@@ -327,24 +316,25 @@
|
||||
/>
|
||||
<div class="shrink-0 flex md:flex-col gap-2">
|
||||
{#if isGenerating}
|
||||
<button class="btn bg-red-500 hover:bg-red-600 text-white flex-1 md:flex-none" onclick={cancelGeneration}>
|
||||
<Button variant="destructive" class="flex-1 md:flex-none" onclick={cancelGeneration}>
|
||||
Cancel
|
||||
</button>
|
||||
</Button>
|
||||
{:else}
|
||||
<button
|
||||
class="btn bg-primary text-primary-foreground hover:opacity-90 flex-1 md:flex-none"
|
||||
<Button
|
||||
class="flex-1 md:flex-none"
|
||||
onclick={generate}
|
||||
disabled={!inputText.trim() || !$selectedModelStore}
|
||||
>
|
||||
Generate
|
||||
</button>
|
||||
<button
|
||||
class="btn flex-1 md:flex-none"
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="flex-1 md:flex-none"
|
||||
onclick={clearInput}
|
||||
disabled={!inputText.trim()}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</Button>
|
||||
<label class="flex items-center justify-center gap-2 text-sm cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
||||
Reference in New Issue
Block a user