componenets standardization 1
This commit is contained in:
@@ -6,6 +6,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Card } from '../ui/card';
|
||||
import Badge from '../ui/badge/Badge';
|
||||
import Button from '../ui/button/Button';
|
||||
// import { fetchSiteProgress, SiteProgress } from '../../services/api';
|
||||
import { CheckCircleIcon, XCircleIcon, AlertCircleIcon, ArrowRightIcon } from '../../icons';
|
||||
|
||||
@@ -326,7 +327,7 @@ export default function SiteProgressWidget({ blueprintId, siteId }: SiteProgress
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertCircleIcon className="w-4 h-4 text-warning-600 dark:text-warning-400 mt-0.5 flex-shrink-0" />
|
||||
<div className="text-xs text-warning-800 dark:text-warning-300">
|
||||
Some data may be outdated. <button onClick={handleRetry} className="underline font-medium">Refresh</button>
|
||||
Some data may be outdated. <Button variant="ghost" size="xs" onClick={handleRetry} className="underline font-medium p-0 h-auto">Refresh</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Card } from '../../ui/card';
|
||||
import Button from '../../ui/button/Button';
|
||||
import Label from '../../form/Label';
|
||||
import TextArea from '../../form/input/TextArea';
|
||||
import InputField from '../../form/input/InputField';
|
||||
import { useToast } from '../../ui/toast/ToastContainer';
|
||||
|
||||
export interface StyleSettings {
|
||||
@@ -106,53 +107,41 @@ export default function StyleEditor({ styleSettings, onChange, onSave, onReset }
|
||||
{/* Tabs */}
|
||||
<div className="border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
type="button"
|
||||
<Button
|
||||
variant={activeTab === 'css' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('css')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'css'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<CodeIcon className="w-4 h-4 inline mr-2" />
|
||||
<CodeIcon className="w-4 h-4 mr-2" />
|
||||
Custom CSS
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'colors' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('colors')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'colors'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<PaletteIcon className="w-4 h-4 inline mr-2" />
|
||||
<PaletteIcon className="w-4 h-4 mr-2" />
|
||||
Colors
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'typography' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('typography')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'typography'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<TypeIcon className="w-4 h-4 inline mr-2" />
|
||||
<TypeIcon className="w-4 h-4 mr-2" />
|
||||
Typography
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'spacing' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('spacing')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'spacing'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
Spacing
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -185,18 +174,18 @@ export default function StyleEditor({ styleSettings, onChange, onSave, onReset }
|
||||
<div key={colorKey}>
|
||||
<Label>{colorKey.charAt(0).toUpperCase() + colorKey.slice(1)} Color</Label>
|
||||
<div className="flex gap-2 mt-1">
|
||||
<input
|
||||
<InputField
|
||||
type="color"
|
||||
value={styleSettings.colorPalette?.[colorKey as keyof typeof styleSettings.colorPalette] || '#000000'}
|
||||
onChange={(e) => handleColorChange(colorKey, e.target.value)}
|
||||
className="w-16 h-10 rounded border border-gray-300 dark:border-gray-700 cursor-pointer"
|
||||
className="w-16 h-10"
|
||||
/>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.colorPalette?.[colorKey as keyof typeof styleSettings.colorPalette] || ''}
|
||||
onChange={(e) => handleColorChange(colorKey, e.target.value)}
|
||||
placeholder="#000000"
|
||||
className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -211,45 +200,45 @@ export default function StyleEditor({ styleSettings, onChange, onSave, onReset }
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>Font Family</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.typography?.fontFamily || ''}
|
||||
onChange={(e) => handleTypographyChange('fontFamily', e.target.value)}
|
||||
placeholder="Arial, sans-serif"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="mt-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Heading Font</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.typography?.headingFont || ''}
|
||||
onChange={(e) => handleTypographyChange('headingFont', e.target.value)}
|
||||
placeholder="Georgia, serif"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="mt-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Base Font Size</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.typography?.fontSize || ''}
|
||||
onChange={(e) => handleTypographyChange('fontSize', e.target.value)}
|
||||
placeholder="16px"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="mt-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Line Height</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.typography?.lineHeight || ''}
|
||||
onChange={(e) => handleTypographyChange('lineHeight', e.target.value)}
|
||||
placeholder="1.5"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="mt-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -262,12 +251,12 @@ export default function StyleEditor({ styleSettings, onChange, onSave, onReset }
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>Base Spacing Unit</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.spacing?.base || ''}
|
||||
onChange={(e) => handleSpacingChange('base', e.target.value)}
|
||||
placeholder="8px"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="mt-1"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Base unit for spacing calculations (e.g., 8px, 1rem)
|
||||
@@ -276,12 +265,12 @@ export default function StyleEditor({ styleSettings, onChange, onSave, onReset }
|
||||
|
||||
<div>
|
||||
<Label>Spacing Scale</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={styleSettings.spacing?.scale || ''}
|
||||
onChange={(e) => handleSpacingChange('scale', e.target.value)}
|
||||
placeholder="1.5"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="mt-1"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Multiplier for spacing scale (e.g., 1.5 for 1.5x spacing)
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Card } from '../../ui/card';
|
||||
import Label from '../../form/Label';
|
||||
import SelectDropdown from '../../form/SelectDropdown';
|
||||
import Button from '../../ui/button/Button';
|
||||
import InputField from '../../form/input/InputField';
|
||||
|
||||
export interface TemplateCustomization {
|
||||
layout: string;
|
||||
@@ -68,54 +69,42 @@ export default function TemplateCustomizer({
|
||||
{/* Tabs */}
|
||||
<div className="border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
type="button"
|
||||
<Button
|
||||
variant={activeTab === 'layout' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('layout')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'layout'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<LayoutIcon className="w-4 h-4 inline mr-2" />
|
||||
<LayoutIcon className="w-4 h-4 mr-2" />
|
||||
Layout
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'colors' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('colors')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'colors'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<PaletteIcon className="w-4 h-4 inline mr-2" />
|
||||
<PaletteIcon className="w-4 h-4 mr-2" />
|
||||
Colors
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'typography' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('typography')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'typography'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<TypeIcon className="w-4 h-4 inline mr-2" />
|
||||
<TypeIcon className="w-4 h-4 mr-2" />
|
||||
Typography
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'spacing' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('spacing')}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
activeTab === 'spacing'
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<SettingsIcon className="w-4 h-4 inline mr-2" />
|
||||
<SettingsIcon className="w-4 h-4 mr-2" />
|
||||
Spacing
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -203,7 +192,7 @@ export default function TemplateCustomizer({
|
||||
<div>
|
||||
<Label>Primary Color</Label>
|
||||
<div className="flex gap-2 mt-1">
|
||||
<input
|
||||
<InputField
|
||||
type="color"
|
||||
value={customization.customStyles?.primaryColor || '#3b82f6'}
|
||||
onChange={(e) =>
|
||||
@@ -211,9 +200,9 @@ export default function TemplateCustomizer({
|
||||
customStyles: { ...customization.customStyles, primaryColor: e.target.value },
|
||||
})
|
||||
}
|
||||
className="w-16 h-10 rounded border border-gray-300 dark:border-gray-700 cursor-pointer"
|
||||
className="w-16 h-10"
|
||||
/>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={customization.customStyles?.primaryColor || '#3b82f6'}
|
||||
onChange={(e) =>
|
||||
@@ -222,7 +211,7 @@ export default function TemplateCustomizer({
|
||||
})
|
||||
}
|
||||
placeholder="#3b82f6"
|
||||
className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -230,7 +219,7 @@ export default function TemplateCustomizer({
|
||||
<div>
|
||||
<Label>Background Color</Label>
|
||||
<div className="flex gap-2 mt-1">
|
||||
<input
|
||||
<InputField
|
||||
type="color"
|
||||
value={customization.customStyles?.backgroundColor || '#ffffff'}
|
||||
onChange={(e) =>
|
||||
@@ -238,9 +227,9 @@ export default function TemplateCustomizer({
|
||||
customStyles: { ...customization.customStyles, backgroundColor: e.target.value },
|
||||
})
|
||||
}
|
||||
className="w-16 h-10 rounded border border-gray-300 dark:border-gray-700 cursor-pointer"
|
||||
className="w-16 h-10"
|
||||
/>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={customization.customStyles?.backgroundColor || '#ffffff'}
|
||||
onChange={(e) =>
|
||||
@@ -249,7 +238,7 @@ export default function TemplateCustomizer({
|
||||
})
|
||||
}
|
||||
placeholder="#ffffff"
|
||||
className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
className="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import React, { useState } from 'react';
|
||||
import { SearchIcon, FilterIcon, CheckIcon } from '../../icons';
|
||||
import { Card } from '../../ui/card';
|
||||
import Button from '../../ui/button/Button';
|
||||
import InputField from '../../form/input/InputField';
|
||||
|
||||
export interface TemplateOption {
|
||||
id: string;
|
||||
@@ -106,47 +107,37 @@ export default function TemplateLibrary({
|
||||
<div className="space-y-4">
|
||||
{/* Search and Filters */}
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
<div className="relative flex-1">
|
||||
<SearchIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||
<input
|
||||
<div className="flex-1">
|
||||
<InputField
|
||||
type="text"
|
||||
placeholder="Search templates..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
startIcon={<SearchIcon className="w-4 h-4" />}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
<Button
|
||||
variant={showFeaturedOnly ? 'primary' : 'outline'}
|
||||
onClick={() => setShowFeaturedOnly(!showFeaturedOnly)}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
showFeaturedOnly
|
||||
? 'bg-brand-500 text-white'
|
||||
: 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'
|
||||
}`}
|
||||
startIcon={<FilterIcon className="w-4 h-4" />}
|
||||
>
|
||||
<FilterIcon className="w-4 h-4 inline mr-2" />
|
||||
Featured Only
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Category Filter */}
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{categories.map((category) => (
|
||||
<button
|
||||
<Button
|
||||
key={category}
|
||||
type="button"
|
||||
variant={selectedCategory === category ? 'primary' : 'outline'}
|
||||
size="sm"
|
||||
onClick={() => setSelectedCategory(category)}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
selectedCategory === category
|
||||
? 'bg-brand-500 text-white'
|
||||
: 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'
|
||||
}`}
|
||||
>
|
||||
{category.charAt(0).toUpperCase() + category.slice(1)}
|
||||
</button>
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card } from '../ui/card';
|
||||
import Button from '../ui/button/Button';
|
||||
import IconButton from '../ui/button/IconButton';
|
||||
import Label from '../form/Label';
|
||||
import Input from '../form/input/InputField';
|
||||
import Checkbox from '../form/input/Checkbox';
|
||||
import Switch from '../form/switch/Switch';
|
||||
import { useToast } from '../ui/toast/ToastContainer';
|
||||
import { integrationApi, SiteIntegration } from '../../services/integration.api';
|
||||
import { fetchAPI } from '../../services/api';
|
||||
@@ -218,26 +220,11 @@ export default function WordPressIntegrationForm({
|
||||
|
||||
{/* Toggle Switch */}
|
||||
{apiKey && (
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{integrationEnabled ? 'Sync Enabled' : 'Sync Disabled'}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleToggleIntegration(!integrationEnabled)}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 ${
|
||||
integrationEnabled ? 'bg-brand-600' : 'bg-gray-300 dark:bg-gray-600'
|
||||
}`}
|
||||
role="switch"
|
||||
aria-checked={integrationEnabled}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
integrationEnabled ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<Switch
|
||||
label={integrationEnabled ? 'Sync Enabled' : 'Sync Disabled'}
|
||||
checked={integrationEnabled}
|
||||
onChange={(checked) => handleToggleIntegration(checked)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -293,30 +280,32 @@ export default function WordPressIntegrationForm({
|
||||
</label>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative">
|
||||
<input
|
||||
id="api-key"
|
||||
className="dark:bg-dark-900 shadow-theme-xs focus:border-brand-300 focus:ring-brand-500/10 dark:focus:border-brand-800 h-11 w-full min-w-[360px] rounded-lg border border-gray-300 bg-transparent py-3 pr-[90px] pl-4 text-sm text-gray-800 placeholder:text-gray-400 focus:ring-3 focus:outline-hidden dark:border-gray-700 dark:bg-gray-900 dark:text-white/90 dark:placeholder:text-white/30 font-mono"
|
||||
<Input
|
||||
className="w-full min-w-[360px] pr-[90px] font-mono"
|
||||
readOnly
|
||||
type={apiKeyVisible ? 'text' : 'password'}
|
||||
value={apiKeyVisible ? apiKey : maskApiKey(apiKey)}
|
||||
/>
|
||||
<button
|
||||
<Button
|
||||
onClick={handleCopyApiKey}
|
||||
className="absolute top-1/2 right-0 inline-flex h-11 -translate-y-1/2 cursor-pointer items-center gap-1 rounded-r-lg border border-gray-300 py-3 pr-3 pl-3.5 text-sm font-medium text-gray-700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
variant="outline"
|
||||
tone="neutral"
|
||||
size="sm"
|
||||
className="absolute top-1/2 right-0 -translate-y-1/2 rounded-l-none"
|
||||
>
|
||||
<CopyIcon className="w-4 h-4 fill-current" />
|
||||
<span>Copy</span>
|
||||
</button>
|
||||
<CopyIcon className="w-4 h-4" />
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
<div className="group relative inline-block">
|
||||
<button
|
||||
<IconButton
|
||||
onClick={handleRegenerateApiKey}
|
||||
disabled={generatingKey}
|
||||
className="inline-flex h-11 w-11 items-center justify-center rounded-lg border border-gray-300 text-gray-700 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50"
|
||||
variant="outline"
|
||||
title="Regenerate"
|
||||
>
|
||||
<RefreshCwIcon className={`w-5 h-5 ${generatingKey ? 'animate-spin' : ''}`} />
|
||||
</button>
|
||||
</IconButton>
|
||||
<div className="invisible absolute bottom-full left-1/2 z-50 mb-2.5 -translate-x-1/2 opacity-0 transition-opacity duration-300 group-hover:visible group-hover:opacity-100">
|
||||
<div className="relative">
|
||||
<div className="rounded-lg bg-white px-3 py-2 text-xs font-medium whitespace-nowrap text-gray-700 shadow-xs dark:bg-gray-800 dark:text-white">
|
||||
@@ -326,9 +315,9 @@ export default function WordPressIntegrationForm({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
<IconButton
|
||||
onClick={() => setApiKeyVisible(!apiKeyVisible)}
|
||||
className="inline-flex h-11 w-11 items-center justify-center rounded-lg border border-gray-300 text-gray-700 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
variant="outline"
|
||||
>
|
||||
{apiKeyVisible ? (
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -340,7 +329,7 @@ export default function WordPressIntegrationForm({
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -354,22 +343,23 @@ export default function WordPressIntegrationForm({
|
||||
</td>
|
||||
<td className="px-5 py-3 whitespace-nowrap">
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
<IconButton
|
||||
onClick={handleRegenerateApiKey}
|
||||
disabled={generatingKey}
|
||||
className="text-gray-500 hover:text-brand-500 dark:text-gray-400 dark:hover:text-brand-400 disabled:opacity-50 transition-colors"
|
||||
variant="ghost"
|
||||
title="Regenerate API key"
|
||||
>
|
||||
<RefreshCwIcon className={`w-5 h-5 ${generatingKey ? 'animate-spin' : ''}`} />
|
||||
</button>
|
||||
<button
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleRevokeApiKey}
|
||||
disabled={generatingKey}
|
||||
className="text-gray-500 hover:text-error-500 dark:text-gray-400 dark:hover:text-error-400 disabled:opacity-50 transition-colors"
|
||||
variant="ghost"
|
||||
tone="danger"
|
||||
title="Revoke API key"
|
||||
>
|
||||
<TrashBinIcon className="w-5 h-5" />
|
||||
</button>
|
||||
</IconButton>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user