custom: optimize ai image generator page

This commit is contained in:
javayhu 2025-06-27 01:05:19 +08:00
parent 985579b964
commit 3058484803
3 changed files with 60 additions and 55 deletions

View File

@ -75,8 +75,9 @@ export function ImagePlayground({
};
return (
<div className="min-h-screen bg-background py-8 px-4 sm:px-6 lg:px-8">
<div className="min-h-screen rounded-lg bg-background py-8 px-4 sm:px-6 lg:px-8">
<div className="max-w-7xl mx-auto">
{/* input prompt */}
<PromptInput
onSubmit={handlePromptSubmit}
isLoading={isLoading}
@ -86,6 +87,8 @@ export function ImagePlayground({
onModeChange={handleModeChange}
suggestions={suggestions}
/>
{/* models carousel */}
{(() => {
const getModelProps = () =>
(Object.keys(PROVIDERS) as ProviderKey[]).map((key) => {
@ -125,7 +128,7 @@ export function ImagePlayground({
))}
</div>
{activePrompt && activePrompt.length > 0 && (
<div className="text-center mt-4 text-muted-foreground">
<div className="text-center mt-8 text-muted-foreground">
{activePrompt}
</div>
)}

View File

@ -71,12 +71,13 @@ export function ModelSelect({
<Card
className={cn('w-full transition-opacity', enabled ? '' : 'opacity-50')}
>
<CardContent className="pt-6 h-full">
<CardContent className="h-full">
<div className="flex items-center justify-between gap-2 mb-4">
<div className="flex items-center gap-2 w-full transition-opacity duration-200">
<div className="bg-primary p-2 rounded-full">
<div className="flex flex-col items-center gap-4 w-full transition-opacity duration-200">
{/* model provider icon */}
<div className="flex items-center gap-4">
<Link
className="hover:opacity-80"
className="bg-primary hover:opacity-80 p-2 rounded-full"
href={
'https://sdk.vercel.ai/providers/ai-sdk-providers/' +
PROVIDER_LINKS[providerKey]
@ -84,11 +85,10 @@ export function ModelSelect({
target="_blank"
>
<div className="text-primary-foreground">
<Icon size={28} />
<Icon size={24} />
</div>
</Link>
</div>
<div className="flex flex-col w-full">
<Link
className="hover:opacity-80"
href={
@ -99,43 +99,45 @@ export function ModelSelect({
>
<h3 className="font-semibold text-lg">{label}</h3>
</Link>
<div className="flex justify-between items-center w-full">
<Select
defaultValue={value}
value={value}
onValueChange={(selectedValue) =>
onChange(selectedValue, providerKey)
}
>
<SelectTrigger>
<SelectValue placeholder={value || 'Select a model'} />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{models.map((model) => (
<SelectItem key={model} value={model} className="">
<span className="hidden xl:inline">
{imageHelpers.formatModelId(model).length > 30
? imageHelpers.formatModelId(model).slice(0, 30) +
'...'
: imageHelpers.formatModelId(model)}
</span>
<span className="hidden lg:inline xl:hidden">
{imageHelpers.formatModelId(model).length > 20
? imageHelpers.formatModelId(model).slice(0, 20) +
'...'
: imageHelpers.formatModelId(model)}
</span>
</div>
<span className="lg:hidden">
{imageHelpers.formatModelId(model)}
</span>
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
{/* models in provider */}
<div className="flex justify-center items-center w-full">
<Select
defaultValue={value}
value={value}
onValueChange={(selectedValue) =>
onChange(selectedValue, providerKey)
}
>
<SelectTrigger className="cursor-pointer w-full">
<SelectValue placeholder={value || 'Select a model'} />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{models.map((model) => (
<SelectItem key={model} value={model} className="">
<span className="hidden xl:inline">
{imageHelpers.formatModelId(model).length > 30
? imageHelpers.formatModelId(model).slice(0, 30) +
'...'
: imageHelpers.formatModelId(model)}
</span>
<span className="hidden lg:inline xl:hidden">
{imageHelpers.formatModelId(model).length > 20
? imageHelpers.formatModelId(model).slice(0, 20) +
'...'
: imageHelpers.formatModelId(model)}
</span>
<span className="lg:hidden">
{imageHelpers.formatModelId(model)}
</span>
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
</div>

View File

@ -54,7 +54,7 @@ export function PromptInput({
return (
<div className="w-full mb-8">
<div className="bg-zinc-50 rounded-xl p-4">
<div className="bg-card rounded-xl p-4">
<div className="flex flex-col gap-3">
<Textarea
value={input}
@ -62,16 +62,16 @@ export function PromptInput({
onKeyDown={handleKeyDown}
placeholder="Enter your prompt here"
rows={3}
className="text-base bg-transparent border-none p-0 resize-none placeholder:text-zinc-500 text-[#111111] focus-visible:ring-0 focus-visible:ring-offset-0"
className="text-base bg-transparent border-muted-foreground p-2 resize-none placeholder:text-muted-foreground text-foreground focus-visible:ring-0 focus-visible:ring-offset-0"
/>
<div className="flex items-center justify-between pt-1">
<div className="flex items-center justify-between space-x-2">
<button
type="button"
onClick={updateSuggestions}
className="flex items-center justify-between px-2 rounded-lg py-1 bg-background text-sm hover:opacity-70 group transition-opacity duration-200"
className="flex items-center justify-between cursor-pointer px-2 rounded-lg py-1 bg-background text-sm hover:opacity-70 group transition-opacity duration-200"
>
<RefreshCw className="w-4 h-4 text-zinc-500 group-hover:opacity-70" />
<RefreshCw className="w-4 h-4 text-muted-foreground group-hover:opacity-70" />
</button>
{suggestions.map((suggestion, index) => (
<button
@ -79,7 +79,7 @@ export function PromptInput({
key={index}
onClick={() => handleSuggestionSelect(suggestion.prompt)}
className={cn(
'flex items-center justify-between px-2 rounded-lg py-1 bg-background text-sm hover:opacity-70 group transition-opacity duration-200',
'flex items-center justify-between cursor-pointer px-2 rounded-lg py-1 bg-background text-sm hover:opacity-70 group transition-opacity duration-200',
index > 2
? 'hidden md:flex'
: index > 1
@ -88,11 +88,11 @@ export function PromptInput({
)}
>
<span>
<span className="text-black text-xs sm:text-sm">
<span className="text-foreground text-xs sm:text-sm">
{suggestion.text.toLowerCase()}
</span>
</span>
<ArrowUpRight className="ml-1 h-2 w-2 sm:h-3 sm:w-3 text-zinc-500 group-hover:opacity-70" />
<ArrowUpRight className="ml-1 h-2 w-2 sm:h-3 sm:w-3 text-muted-foreground group-hover:opacity-70" />
</button>
))}
</div>
@ -100,12 +100,12 @@ export function PromptInput({
type="button"
onClick={handleSubmit}
disabled={isLoading || !input.trim()}
className="h-8 w-8 rounded-full bg-black flex items-center justify-center disabled:opacity-50"
className="h-8 w-8 rounded-full bg-primary flex items-center justify-center disabled:opacity-50"
>
{isLoading ? (
<Spinner className="w-3 h-3 text-white" />
<Spinner className="w-3 h-3 text-primary-foreground" />
) : (
<ArrowUp className="w-5 h-5 text-white" />
<ArrowUp className="w-5 h-5 text-primary-foreground" />
)}
</button>
</div>