fix: polish ScriptSetupBlock — orange accent bar, terminal dots, tighter storage/TTL, framework icons
- Add gradient orange accent bar and macOS-style terminal dots to code block - Copy button uses brand-orange styling instead of plain gray - Storage and TTL selects sit side-by-side tightly instead of spread apart - TTL options shortened (24h, 48h, 7d, 30d) - Replace framework dropdown with compact icon+label buttons (logos visible) - Add "All integrations" link in section header
This commit is contained in:
@@ -11,13 +11,7 @@ import { API_URL, APP_URL } from '@/lib/api/client'
|
|||||||
import { integrations, getIntegration } from '@/lib/integrations'
|
import { integrations, getIntegration } from '@/lib/integrations'
|
||||||
import { toast, Toggle, Select, CheckIcon } from '@ciphera-net/ui'
|
import { toast, Toggle, Select, CheckIcon } from '@ciphera-net/ui'
|
||||||
|
|
||||||
const FRAMEWORK_OPTIONS = [
|
const FRAMEWORKS = integrations.filter((i) => i.category === 'framework').slice(0, 10)
|
||||||
{ value: '', label: 'Choose framework' },
|
|
||||||
...integrations
|
|
||||||
.filter((i) => i.category === 'framework')
|
|
||||||
.slice(0, 10)
|
|
||||||
.map((i) => ({ value: i.id, label: i.name })),
|
|
||||||
]
|
|
||||||
|
|
||||||
const STORAGE_OPTIONS = [
|
const STORAGE_OPTIONS = [
|
||||||
{ value: 'local', label: 'Cross-tab (localStorage)' },
|
{ value: 'local', label: 'Cross-tab (localStorage)' },
|
||||||
@@ -25,10 +19,10 @@ const STORAGE_OPTIONS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const TTL_OPTIONS = [
|
const TTL_OPTIONS = [
|
||||||
{ value: '24', label: '24 hours' },
|
{ value: '24', label: '24h' },
|
||||||
{ value: '48', label: '48 hours' },
|
{ value: '48', label: '48h' },
|
||||||
{ value: '168', label: '7 days' },
|
{ value: '168', label: '7d' },
|
||||||
{ value: '720', label: '30 days' },
|
{ value: '720', label: '30d' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const FEATURES = [
|
const FEATURES = [
|
||||||
@@ -111,35 +105,47 @@ export default function ScriptSetupBlock({
|
|||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{/* ── Script snippet ──────────────────────────────────────────────── */}
|
{/* ── Script snippet ──────────────────────────────────────────────── */}
|
||||||
<div className="rounded-2xl border border-neutral-800 bg-neutral-950 overflow-hidden">
|
<div className="rounded-2xl border border-neutral-200 dark:border-neutral-800 overflow-hidden">
|
||||||
<div className="flex items-center justify-between px-5 py-3 border-b border-neutral-800">
|
{/* * Orange accent bar */}
|
||||||
<span className="text-xs font-medium text-neutral-400 uppercase tracking-wider">
|
<div className="h-1 bg-gradient-to-r from-brand-orange via-brand-orange/60 to-transparent" />
|
||||||
Your tracking script
|
<div className="bg-neutral-950">
|
||||||
</span>
|
<div className="flex items-center justify-between px-5 py-3">
|
||||||
<button
|
<div className="flex items-center gap-2">
|
||||||
type="button"
|
{/* * Terminal dots */}
|
||||||
onClick={copyScript}
|
<div className="flex gap-1.5">
|
||||||
className="flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-lg transition-colors cursor-pointer bg-neutral-800 hover:bg-neutral-700 text-neutral-300 hover:text-white"
|
<div className="w-2.5 h-2.5 rounded-full bg-red-500/70" />
|
||||||
>
|
<div className="w-2.5 h-2.5 rounded-full bg-yellow-500/70" />
|
||||||
{copied ? (
|
<div className="w-2.5 h-2.5 rounded-full bg-green-500/70" />
|
||||||
<>
|
</div>
|
||||||
<CheckIcon className="w-3.5 h-3.5 text-green-400" />
|
<span className="text-xs font-medium text-neutral-500 ml-2">
|
||||||
<span className="text-green-400">Copied</span>
|
tracking script
|
||||||
</>
|
</span>
|
||||||
) : (
|
</div>
|
||||||
<>
|
<button
|
||||||
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
type="button"
|
||||||
<rect x="9" y="9" width="13" height="13" rx="2" strokeLinecap="round" strokeLinejoin="round" />
|
onClick={copyScript}
|
||||||
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" strokeLinecap="round" strokeLinejoin="round" />
|
className="flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-lg transition-all cursor-pointer bg-brand-orange/10 hover:bg-brand-orange/20 text-brand-orange border border-brand-orange/20"
|
||||||
</svg>
|
>
|
||||||
Copy
|
{copied ? (
|
||||||
</>
|
<>
|
||||||
)}
|
<CheckIcon className="w-3.5 h-3.5" />
|
||||||
</button>
|
Copied
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||||
|
<rect x="9" y="9" width="13" height="13" rx="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||||
|
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" strokeLinecap="round" strokeLinejoin="round" />
|
||||||
|
</svg>
|
||||||
|
Copy
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<pre className="px-5 pb-5 text-[13px] leading-relaxed font-mono text-neutral-300 whitespace-pre-wrap break-all overflow-x-auto selection:bg-brand-orange/30">
|
||||||
|
{scriptSnippet}
|
||||||
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
<pre className="px-5 py-4 text-[13px] leading-relaxed font-mono text-neutral-200 whitespace-pre-wrap break-all overflow-x-auto">
|
|
||||||
{scriptSnippet}
|
|
||||||
</pre>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ── Feature toggles ─────────────────────────────────────────────── */}
|
{/* ── Feature toggles ─────────────────────────────────────────────── */}
|
||||||
@@ -184,10 +190,10 @@ export default function ScriptSetupBlock({
|
|||||||
<h4 className="text-sm font-semibold text-neutral-900 dark:text-white mb-3">
|
<h4 className="text-sm font-semibold text-neutral-900 dark:text-white mb-3">
|
||||||
Visitor identity
|
Visitor identity
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex flex-col sm:flex-row gap-3">
|
<div className="flex items-end gap-3">
|
||||||
<div className="flex-1">
|
<div className="min-w-0">
|
||||||
<label className="text-xs font-medium text-neutral-500 dark:text-neutral-400 mb-1 block">
|
<label className="text-xs font-medium text-neutral-500 dark:text-neutral-400 mb-1 block">
|
||||||
Storage mode
|
Storage
|
||||||
</label>
|
</label>
|
||||||
<Select
|
<Select
|
||||||
variant="input"
|
variant="input"
|
||||||
@@ -197,9 +203,9 @@ export default function ScriptSetupBlock({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{storage === 'local' && (
|
{storage === 'local' && (
|
||||||
<div className="sm:w-40">
|
<div>
|
||||||
<label className="text-xs font-medium text-neutral-500 dark:text-neutral-400 mb-1 block">
|
<label className="text-xs font-medium text-neutral-500 dark:text-neutral-400 mb-1 block">
|
||||||
TTL (expiry)
|
TTL
|
||||||
</label>
|
</label>
|
||||||
<Select
|
<Select
|
||||||
variant="input"
|
variant="input"
|
||||||
@@ -215,40 +221,48 @@ export default function ScriptSetupBlock({
|
|||||||
{/* ── Framework guide ─────────────────────────────────────────────── */}
|
{/* ── Framework guide ─────────────────────────────────────────────── */}
|
||||||
{showFrameworkPicker && (
|
{showFrameworkPicker && (
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<h4 className="text-sm font-semibold text-neutral-900 dark:text-white mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
Setup guide
|
<h4 className="text-sm font-semibold text-neutral-900 dark:text-white">
|
||||||
</h4>
|
Setup guide
|
||||||
<div className="flex items-end gap-3">
|
</h4>
|
||||||
<div className="flex-1">
|
<Link
|
||||||
<Select
|
href="/integrations"
|
||||||
variant="input"
|
target="_blank"
|
||||||
value={framework}
|
rel="noopener noreferrer"
|
||||||
onChange={setFramework}
|
className="text-xs font-medium text-neutral-500 dark:text-neutral-400 hover:text-brand-orange transition-colors"
|
||||||
options={FRAMEWORK_OPTIONS}
|
>
|
||||||
placeholder="Choose framework"
|
All integrations →
|
||||||
/>
|
</Link>
|
||||||
</div>
|
|
||||||
{selectedIntegration && (
|
|
||||||
<Link
|
|
||||||
href={`/integrations/${framework}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="shrink-0 text-sm font-medium text-brand-orange hover:text-brand-orange/80 transition-colors pb-2"
|
|
||||||
>
|
|
||||||
See {selectedIntegration.name} guide →
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
{!selectedIntegration && (
|
|
||||||
<Link
|
|
||||||
href="/integrations"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="shrink-0 text-sm font-medium text-neutral-500 hover:text-neutral-400 transition-colors pb-2"
|
|
||||||
>
|
|
||||||
All integrations →
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{FRAMEWORKS.map((fw) => (
|
||||||
|
<button
|
||||||
|
key={fw.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => setFramework(framework === fw.id ? '' : fw.id)}
|
||||||
|
className={`flex items-center gap-2 rounded-lg border px-3 py-2 text-sm transition-all cursor-pointer ${
|
||||||
|
framework === fw.id
|
||||||
|
? 'border-brand-orange bg-brand-orange/10 text-brand-orange'
|
||||||
|
: 'border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 text-neutral-600 dark:text-neutral-400 hover:border-neutral-300 dark:hover:border-neutral-700 hover:text-neutral-900 dark:hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<span className="[&_svg]:h-4 [&_svg]:w-4 shrink-0 flex items-center">
|
||||||
|
{fw.icon}
|
||||||
|
</span>
|
||||||
|
<span className="font-medium">{fw.name}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{selectedIntegration && (
|
||||||
|
<Link
|
||||||
|
href={`/integrations/${framework}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1 mt-3 text-sm font-medium text-brand-orange hover:text-brand-orange/80 transition-colors"
|
||||||
|
>
|
||||||
|
See full {selectedIntegration.name} guide →
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user