feat: Add card insert buttons toolbar
## ✨ New Feature: Card Insert Buttons! ### What's Added: **Card Insert Toolbar** above the rich text editor with 6 quick-insert buttons: 1. **Basic Card** - Plain card with default content 2. **Success Card** - Green checkmark, success message 3. **Info Card** - Blue info icon, informational content 4. **Warning Card** - Orange alert icon, warning message 5. **Hero Card** - Large text, background image support 6. **Button** - Call-to-action button with link ### Features: **Visual Toolbar:** ``` Insert Card: [Basic] [✓ Success] [ℹ Info] [⚠ Warning] [🖼 Hero] | [+ Button] ``` **One-Click Insert:** - Click button → Card inserted at end of content - Pre-filled with sample content - Proper [card] syntax - Toast notification confirms insertion **Smart Behavior:** - Only shows in Visual Editor mode (hidden in Code Mode) - Styled toolbar with icons and colors - Responsive layout (wraps on mobile) - Separator between cards and button ### Card Types: **Basic:** ```html [card] <h2>Card Title</h2> <p>Card content goes here...</p> [/card] ``` **Success:** ```html [card type="success"] <h2>✅ Success!</h2> <p>Your action was successful.</p> [/card] ``` **Info, Warning, Hero** - Similar structure with different types **Button:** ```html <p style="text-align: center;"> <a href="{order_url}" class="button">Button Text</a> </p> ``` ### Benefits: - ✅ **No manual typing** of [card] tags - ✅ **Consistent formatting** every time - ✅ **Visual feedback** with toast notifications - ✅ **Beginner-friendly** - just click and edit - ✅ **Professional templates** with pre-filled content ### Next: Email Appearance Settings 🎨
This commit is contained in:
@@ -9,7 +9,7 @@ import { Input } from '@/components/ui/input';
|
||||
import { RichTextEditor } from '@/components/ui/rich-text-editor';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { ArrowLeft, Eye, Edit, RotateCcw } from 'lucide-react';
|
||||
import { ArrowLeft, Eye, Edit, RotateCcw, Plus, CheckCircle, Info, AlertCircle, Image } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { __ } from '@/lib/i18n';
|
||||
|
||||
@@ -125,6 +125,30 @@ export default function EditTemplate() {
|
||||
}
|
||||
};
|
||||
|
||||
// Insert card helpers
|
||||
const insertCard = (type?: string, content?: string) => {
|
||||
let cardText = '';
|
||||
|
||||
if (type) {
|
||||
cardText = `[card type="${type}"]
|
||||
${content || '<h2>Card Title</h2>\n<p>Card content goes here...</p>'}
|
||||
[/card]\n\n`;
|
||||
} else {
|
||||
cardText = `[card]
|
||||
${content || '<h2>Card Title</h2>\n<p>Card content goes here...</p>'}
|
||||
[/card]\n\n`;
|
||||
}
|
||||
|
||||
setBody(body + cardText);
|
||||
toast.success(__('Card inserted'));
|
||||
};
|
||||
|
||||
const insertButton = () => {
|
||||
const buttonHtml = `<p style="text-align: center;"><a href="{order_url}" class="button">Button Text</a></p>`;
|
||||
setBody(body + buttonHtml + '\n');
|
||||
toast.success(__('Button inserted'));
|
||||
};
|
||||
|
||||
// Get variable keys for the rich text editor
|
||||
const variableKeys = Object.keys(variables);
|
||||
|
||||
@@ -343,6 +367,76 @@ export default function EditTemplate() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Card Insert Buttons */}
|
||||
{!codeMode && (
|
||||
<div className="flex flex-wrap gap-2 p-3 bg-muted/50 rounded-md border">
|
||||
<span className="text-xs font-medium text-muted-foreground flex items-center">
|
||||
{__('Insert Card:')}
|
||||
</span>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => insertCard()}
|
||||
className="h-7 text-xs gap-1"
|
||||
>
|
||||
<Plus className="h-3 w-3" />
|
||||
{__('Basic')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => insertCard('success', '<h2>✅ Success!</h2>\n<p>Your action was successful.</p>')}
|
||||
className="h-7 text-xs gap-1"
|
||||
>
|
||||
<CheckCircle className="h-3 w-3 text-green-600" />
|
||||
{__('Success')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => insertCard('info', '<h2>ℹ️ Information</h2>\n<p>Important information here.</p>')}
|
||||
className="h-7 text-xs gap-1"
|
||||
>
|
||||
<Info className="h-3 w-3 text-blue-600" />
|
||||
{__('Info')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => insertCard('warning', '<h2>⚠️ Warning</h2>\n<p>Please pay attention to this.</p>')}
|
||||
className="h-7 text-xs gap-1"
|
||||
>
|
||||
<AlertCircle className="h-3 w-3 text-orange-600" />
|
||||
{__('Warning')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => insertCard('hero', '<h1>Big Announcement</h1>\n<p>Hero card with large text.</p>', 'https://example.com/bg.jpg')}
|
||||
className="h-7 text-xs gap-1"
|
||||
>
|
||||
<Image className="h-3 w-3 text-purple-600" />
|
||||
{__('Hero')}
|
||||
</Button>
|
||||
<div className="border-l mx-1"></div>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={insertButton}
|
||||
className="h-7 text-xs gap-1"
|
||||
>
|
||||
<Plus className="h-3 w-3" />
|
||||
{__('Button')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{codeMode ? (
|
||||
<textarea
|
||||
value={body}
|
||||
|
||||
Reference in New Issue
Block a user