custom: optimize ai image generator page
This commit is contained in:
parent
985579b964
commit
3058484803
@ -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>
|
||||
)}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user