← Components/AI-Specific

PromptBuilder

promptbuilder-1779379195873.tsx
'use client'
import { useState } from 'react'

const TEMPLATES = [
  { id: 'role', label: 'System role', color: '#6366f1', content: 'You are a {role} expert who {expertise}.' },
  { id: 'task', label: 'Task', color: '#C9A84C', content: 'Your task is to {action} for {target}.' },
  { id: 'context', label: 'Context', color: '#22c55e', content: 'Context: {context}' },
  { id: 'format', label: 'Output format', color: '#f59e0b', content: 'Respond with {format}. Be {tone}.' },
  { id: 'example', label: 'Example', color: '#ec4899', content: 'Example: {example}' },
]

const VARS: Record<string, string[]> = {
  role: ['React developer', 'UX designer', 'technical writer', 'data scientist'],
  expertise: ['builds production components', 'creates accessible UIs', 'explains complex concepts'],
  action: ['generate a component', 'review the code', 'write documentation', 'debug the issue'],
  target: ['a Next.js app', 'a design system', 'enterprise clients', 'beginners'],
  context: ['Using React 18 + TypeScript', 'Dark mode first', 'Tailwind CSS v4', 'App Router'],
  format: ['TypeScript code', 'a markdown document', 'a JSON object', 'step-by-step instructions'],
  tone: ['concise', 'detailed', 'beginner-friendly', 'technical'],
  example: ['GlowButton component', 'data fetching pattern', 'form validation'],
}

export default function PromptBuilder() {
  const [blocks, setBlocks] = useState<string[]>(['role', 'task'])
  const [selections, setSelections] = useState<Record<string, Record<string, string>>>({})

  function resolveTemplate(id: string): string {
    const tpl = TEMPLATES.find(t => t.id === id)!
    return tpl.content.replace(/{(w+)}/g, (_, key) => {
      const sel = selections[id]?.[key]
      if (sel) return sel
      return `{${key}}`
    })
  }

  const fullPrompt = blocks.map(resolveTemplate).join(' ')
  const tokens = Math.ceil(fullPrompt.split(' ').length * 1.3)

  return (
    <div style={{ background: '#0A0A0A', padding: 24, display: 'flex', gap: 20, minHeight: 360 }}>
      {/* Builder */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }}>
          <div style={{ color: '#F5F5F0', fontSize: 14, fontWeight: 700 }}>Prompt Builder</div>
          <span style={{ color: 'rgba(255,255,255,0.3)', fontSize: 12 }}>~{tokens} tokens</span>
        </div>

        {blocks.map((id, idx) => {
          const tpl = TEMPLATES.find(t => t.id === id)!
          const vars = (tpl.content.match(/{(w+)}/g) || []).map(v => v.slice(1, -1))
          return (
            <div key={`${id}-${idx}`} style={{ background: '#111', border: `1px solid ${tpl.color}25`, borderRadius: 10, padding: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                <span style={{ color: tpl.color, fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.05em' }}>{tpl.label}</span>
                <button onClick={() => setBlocks(b => b.filter((_, i) => i !== idx))} style={{ background: 'none', border: 'none', color: 'rgba(255,255,255,0.25)', cursor: 'pointer', fontSize: 16, padding: 0 }}>×</button>
              </div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                {vars.filter(v => VARS[v]).map(v => (
                  <select key={v} value={selections[id]?.[v] || ''}
                    onChange={e => setSelections(s => ({ ...s, [id]: { ...s[id], [v]: e.target.value } }))}
                    style={{ background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: selections[id]?.[v] ? '#F5F5F0' : 'rgba(255,255,255,0.3)', borderRadius: 6, padding: '4px 8px', fontSize: 12, cursor: 'pointer' }}>
                    <option value="">{v}</option>
                    {VARS[v].map(opt => <option key={opt} value={opt}>{opt}</option>)}
                  </select>
                ))}
              </div>
            </div>
          )
        })}

        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {TEMPLATES.filter(t => !blocks.includes(t.id)).map(tpl => (
            <button key={tpl.id} onClick={() => setBlocks(b => [...b, tpl.id])} style={{ background: tpl.color + '12', border: `1px solid ${tpl.color}25`, color: tpl.color, borderRadius: 6, padding: '4px 10px', cursor: 'pointer', fontSize: 12 }}>+ {tpl.label}</button>
          ))}
        </div>
      </div>

      {/* Preview */}
      <div style={{ width: 220, display: 'flex', flexDirection: 'column', gap: 10 }}>
        <div style={{ color: '#F5F5F0', fontSize: 14, fontWeight: 700, marginBottom: 4 }}>Preview</div>
        <div style={{ flex: 1, background: '#111', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 10, padding: 14, fontSize: 12, color: 'rgba(255,255,255,0.6)', lineHeight: 1.7, wordBreak: 'break-word' }}>
          {fullPrompt || <span style={{ color: 'rgba(255,255,255,0.2)' }}>Add blocks to build your prompt</span>}
        </div>
        <button onClick={() => navigator.clipboard.writeText(fullPrompt)} style={{ background: '#C9A84C', color: '#0A0A0A', border: 'none', borderRadius: 8, padding: '9px', fontWeight: 700, cursor: 'pointer', fontSize: 13 }}>Copy prompt</button>
      </div>
    </div>
  )
}

Component info

CategoryAI-Specific
Frameworkreact
TierFREE
Views0
Copies0

About

Visual prompt builder with template blocks, variable injection, token counter, and copy output

More from AI-Specific

import React, { useState, useEffect } from 'react';

interface ChatBubbleProps {
  message: string;
  isAI: boolean;
}

const ChatBubble: React.FC<ChatBubbleProps> = ({ message, isAI }) => {
  const [isTyping, setIsTyping] = useState(false);
  const 
ChatBubble
AI-Specific
import React, { useState, useEffect } from 'react';

interface Props {
  text: string;
  speed: number;
}

const StreamingText: React.FC<Props> = ({ text, speed }) => {
  const [displayedText, setDisplayedText] = useState('');
  const [tokens, setTok
StreamingText
AI-Specific
'use client'
import { useState, useRef, useEffect } from 'react'

interface Msg { id: number; role: 'user' | 'assistant'; content: string; streaming?: boolean }

const RESPONSES = [
  "Here's a React component for you:
```tsx
export default function 
ChatInterface
AI-Specific