Merge pull request #12 from ciphera-net/staging
[PULSE-44] Design consistency audit fixes
This commit is contained in:
@@ -165,7 +165,7 @@ export default function AboutPage() {
|
||||
transition={{ duration: 0.5 }}
|
||||
className="mt-8 p-6 bg-neutral-100 dark:bg-neutral-800/50 rounded-xl border border-neutral-200 dark:border-neutral-800"
|
||||
>
|
||||
<h3 className="text-lg font-bold mb-2 text-neutral-900 dark:text-white">What about Plausible?</h3>
|
||||
<h3 className="text-xl font-bold mb-2 text-neutral-900 dark:text-white">What about Plausible?</h3>
|
||||
<p className="text-neutral-600 dark:text-neutral-400 text-sm">
|
||||
We love Plausible! They paved the way for privacy-friendly analytics.
|
||||
Pulse offers a similar philosophy but with a focus on even deeper integration with the Ciphera ecosystem
|
||||
|
||||
@@ -58,7 +58,7 @@ function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) {
|
||||
>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="w-full py-6 flex items-center justify-between text-left hover:text-brand-orange transition-colors"
|
||||
className="w-full py-6 flex items-center justify-between text-left hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2"
|
||||
>
|
||||
<h3 className="text-lg font-semibold text-neutral-900 dark:text-white pr-4">
|
||||
{faq.question}
|
||||
@@ -104,7 +104,7 @@ export default function FAQPage() {
|
||||
className="text-center mb-16"
|
||||
>
|
||||
<span className="badge-primary mb-4 inline-flex">FAQ</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white mb-4">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white mb-4">
|
||||
Frequently asked questions
|
||||
</h1>
|
||||
<p className="text-lg text-neutral-600 dark:text-neutral-400 max-w-2xl mx-auto">
|
||||
|
||||
@@ -31,7 +31,7 @@ export default function NextJsIntegrationPage() {
|
||||
<path d="M64 0C28.7 0 0 28.7 0 64s28.7 64 64 64 64-28.7 64-64S99.3 0 64 0zm27.6 93.9c-.8.9-2.2 1-3.1.2L42.8 52.8V88c0 1.3-1.1 2.3-2.3 2.3h-7.4c-1.3 0-2.3-1.1-2.3-2.3V40c0-1.3 1.1-2.3 2.3-2.3h7.4c1 0 1.9.6 2.2 1.5l48.6 44.8V40c0-1.3 1.1-2.3 2.3-2.3h7.4c1.3 0 2.3 1.1 2.3 2.3v48c0 1.3-1.1 2.3-2.3 2.3h-6.8c-.9 0-1.7-.5-2.1-1.3z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-neutral-900 dark:text-white">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white">
|
||||
Next.js Integration
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function IntegrationsPage() {
|
||||
>
|
||||
<Link
|
||||
href={`/integrations/${integration.id}`}
|
||||
className="group relative p-8 bg-white/50 dark:bg-neutral-900/50 backdrop-blur-sm border border-neutral-200 dark:border-neutral-800 rounded-2xl hover:border-brand-orange/50 dark:hover:border-brand-orange/50 transition-all duration-300 hover:-translate-y-1 hover:shadow-xl block"
|
||||
className="group relative p-8 bg-white/50 dark:bg-neutral-900/50 backdrop-blur-sm border border-neutral-200 dark:border-neutral-800 rounded-2xl hover:border-brand-orange/50 dark:hover:border-brand-orange/50 transition-all duration-300 hover:-translate-y-1 hover:shadow-xl block focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-6">
|
||||
<div className="p-3 bg-neutral-100 dark:bg-neutral-800 rounded-xl group-hover:scale-110 transition-transform duration-300">
|
||||
@@ -118,7 +118,7 @@ export default function IntegrationsPage() {
|
||||
transition={{ duration: 0.5, delay: integrations.length * 0.1 }}
|
||||
className="p-8 border border-dashed border-neutral-300 dark:border-neutral-700 rounded-2xl flex flex-col items-center justify-center text-center"
|
||||
>
|
||||
<h3 className="text-lg font-bold text-neutral-900 dark:text-white mb-2">
|
||||
<h3 className="text-xl font-bold text-neutral-900 dark:text-white mb-2">
|
||||
Missing something?
|
||||
</h3>
|
||||
<p className="text-neutral-600 dark:text-neutral-400 text-sm mb-4">
|
||||
@@ -126,7 +126,7 @@ export default function IntegrationsPage() {
|
||||
</p>
|
||||
<a
|
||||
href="mailto:support@ciphera.net"
|
||||
className="text-sm font-medium text-brand-orange hover:underline"
|
||||
className="text-sm font-medium text-brand-orange hover:underline focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
Request Integration
|
||||
</a>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function ReactIntegrationPage() {
|
||||
<circle cx="64" cy="64" r="10.6" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-neutral-900 dark:text-white">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white">
|
||||
React Integration
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function VueIntegrationPage() {
|
||||
<path d="M64 24.6H39L64 67.4l25-42.8H64z" fill="#35495E" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-neutral-900 dark:text-white">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white">
|
||||
Vue.js Integration
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,7 @@ export default function WordPressIntegrationPage() {
|
||||
<path d="M116.6 64c0-19.2-10.4-36-26-45.2l28.6 78.4c-1 3.2-2.2 6.2-3.6 9.2-11.4 12.4-27.8 20.2-46 20.2-6.2 0-12.2-.8-17.8-2.4l26.2-76.4c1.2.2 2.4.4 3.6.4 5.4 0 13.8-.8 13.8-.8 2.8-.2 3.2 4 .4 4.2 0 0-2.8.2-6 .4l19 56.6 5.4-18c2.4-7.4 4.2-12.8 4.2-17.4 0-6-2.2-10.2-7.6-12.6-2.8-1.2-2.2-5.4 1.4-5.4h4.4zM64 121.2c-15.8 0-30.2-6.4-40.8-16.8L46.6 36.8c-2.8-.2-5.8-.4-5.8-.4-2.8-.2-2.4-4.4.4-4.2 0 0 8.4.8 13.6.8 5.4 0 13.6-.8 13.6-.8 2.8-.2 3.2 4 .4 4.2 0 0-2.8.2-5.8.4l18.2 54.4 10.6-31.8L64 121.2zM11.4 64c0 17 8.2 32.2 20.8 41.8L18.8 66.8c-.8-3.4-1.2-6.6-1.2-9.2 0-6.8 2.6-13 6.2-17.8C15.6 47.4 11.4 55.2 11.4 64zM64 6.8c16.2 0 30.8 6.8 41.4 17.6-1.4-.2-2.8-.2-4.2-.2-7.8 0-14.2 1.4-14.2 1.4-2.8.6-2.2 4.8.6 4.2 0 0 5-1 10.6-1 2.2 0 4.6.2 6.6.4L88.2 53 71.4 6.8h-7.4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-neutral-900 dark:text-white">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white">
|
||||
WordPress Integration
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function NotFound() {
|
||||
<h1 className="text-9xl font-bold text-transparent bg-clip-text bg-gradient-to-b from-neutral-900 to-neutral-500 dark:from-white dark:to-neutral-500 mb-4">
|
||||
404
|
||||
</h1>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-neutral-900 dark:text-white mb-6">
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-6">
|
||||
Page not found
|
||||
</h2>
|
||||
<p className="text-lg text-neutral-600 dark:text-neutral-400 max-w-md mx-auto mb-10 leading-relaxed">
|
||||
|
||||
@@ -44,13 +44,13 @@ export default function OnboardingPage() {
|
||||
if (loading) return <LoadingOverlay logoSrc="/pulse_icon_no_margins.png" title="Creating Organization..." />
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-neutral-900 px-4">
|
||||
<div className="min-h-screen flex items-center justify-center bg-neutral-50 dark:bg-neutral-900 px-4">
|
||||
<div className="max-w-md w-full space-y-8">
|
||||
<div className="text-center">
|
||||
<h2 className="mt-6 text-3xl font-bold text-gray-900 dark:text-white">
|
||||
<h2 className="mt-6 text-2xl font-bold text-neutral-900 dark:text-white">
|
||||
Welcome to Pulse
|
||||
</h2>
|
||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<p className="mt-2 text-sm text-neutral-600 dark:text-neutral-400">
|
||||
To get started, please create an organization for your team.
|
||||
</p>
|
||||
</div>
|
||||
@@ -80,7 +80,7 @@ export default function OnboardingPage() {
|
||||
value={slug}
|
||||
onChange={(e) => setSlug(e.target.value)}
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
<p className="text-xs text-neutral-500 mt-1">
|
||||
This will be used in your organization's URL.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -48,7 +48,7 @@ function ComparisonSection() {
|
||||
return (
|
||||
<div className="w-full max-w-4xl mx-auto mb-32">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold text-neutral-900 dark:text-white mb-4">Why choose Pulse?</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-4">Why choose Pulse?</h2>
|
||||
<p className="text-neutral-500">The lightweight, privacy-friendly alternative.</p>
|
||||
</div>
|
||||
|
||||
@@ -270,7 +270,7 @@ export default function HomePage() {
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-center mb-20"
|
||||
>
|
||||
<h2 className="text-3xl font-bold text-neutral-900 dark:text-white mb-6">Ready to switch?</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-6">Ready to switch?</h2>
|
||||
<Button onClick={() => initiateOAuthFlow()} variant="primary" className="px-8 py-4 text-lg shadow-lg shadow-brand-orange/20">
|
||||
Start your free trial
|
||||
</Button>
|
||||
@@ -355,11 +355,11 @@ export default function HomePage() {
|
||||
)}
|
||||
<div className="mt-2 flex gap-2">
|
||||
{subscription.has_payment_method ? (
|
||||
<Link href="/org-settings?tab=billing" className="text-sm font-medium text-brand-orange hover:underline">
|
||||
<Link href="/org-settings?tab=billing" className="text-sm font-medium text-brand-orange hover:underline focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded">
|
||||
Manage billing
|
||||
</Link>
|
||||
) : (
|
||||
<Link href="/pricing" className="text-sm font-medium text-brand-orange hover:underline">
|
||||
<Link href="/pricing" className="text-sm font-medium text-brand-orange hover:underline focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded">
|
||||
Upgrade
|
||||
</Link>
|
||||
)}
|
||||
|
||||
@@ -270,7 +270,7 @@ export default function PublicDashboardPage() {
|
||||
<div className="w-2 h-2 rounded-full bg-brand-orange animate-pulse" />
|
||||
<span className="text-sm font-medium text-brand-orange uppercase tracking-wider">Public Dashboard</span>
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold text-neutral-900 dark:text-white flex items-center gap-3">
|
||||
<h1 className="text-2xl font-bold text-neutral-900 dark:text-white flex items-center gap-3">
|
||||
<img
|
||||
src={`https://www.google.com/s2/favicons?domain=${site.domain}&sz=64`}
|
||||
alt={site.name}
|
||||
|
||||
@@ -104,7 +104,7 @@ export default function FunnelsPage() {
|
||||
<div className="bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-2xl p-6 hover:border-brand-orange/50 transition-colors">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 className="text-lg font-medium text-neutral-900 dark:text-white group-hover:text-brand-orange transition-colors">
|
||||
<h3 className="text-xl font-bold text-neutral-900 dark:text-white group-hover:text-brand-orange transition-colors">
|
||||
{funnel.name}
|
||||
</h3>
|
||||
{funnel.description && (
|
||||
|
||||
@@ -236,7 +236,7 @@ export default function SiteDashboardPage() {
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-neutral-900 dark:text-white mb-2">
|
||||
<h1 className="text-2xl font-bold text-neutral-900 dark:text-white mb-2">
|
||||
{site.name}
|
||||
</h1>
|
||||
<p className="text-neutral-600 dark:text-neutral-400">
|
||||
|
||||
@@ -98,7 +98,7 @@ export default function RealtimePage() {
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<button onClick={() => router.push(`/sites/${siteId}`)} className="text-sm text-neutral-500 hover:text-neutral-900 dark:hover:text-white transition-colors">
|
||||
<button onClick={() => router.push(`/sites/${siteId}`)} className="text-sm text-neutral-500 hover:text-neutral-900 dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded">
|
||||
← Back to Dashboard
|
||||
</button>
|
||||
</div>
|
||||
@@ -108,18 +108,18 @@ export default function RealtimePage() {
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-3 w-3 bg-green-500"></span>
|
||||
</span>
|
||||
<span className="text-lg font-normal text-neutral-500">
|
||||
<span className="text-lg font-normal text-neutral-500" aria-live="polite" aria-atomic="true">
|
||||
{visitors.length} active now
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 gap-6 min-h-0">
|
||||
<div className="flex flex-col md:flex-row flex-1 gap-6 min-h-0">
|
||||
{/* Visitors List */}
|
||||
<div className="w-1/3 border border-neutral-200 dark:border-neutral-800 rounded-2xl overflow-hidden flex flex-col bg-white dark:bg-neutral-900">
|
||||
<div className="w-full md:w-1/3 border border-neutral-200 dark:border-neutral-800 rounded-2xl overflow-hidden flex flex-col bg-white dark:bg-neutral-900">
|
||||
<div className="p-4 border-b border-neutral-200 dark:border-neutral-800 bg-neutral-50 dark:bg-neutral-800/50">
|
||||
<h2 className="font-semibold text-neutral-900 dark:text-white">Active Sessions</h2>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white">Active Sessions</h2>
|
||||
</div>
|
||||
<div className="overflow-y-auto flex-1">
|
||||
{visitors.length === 0 ? (
|
||||
@@ -145,7 +145,7 @@ export default function RealtimePage() {
|
||||
exit={{ opacity: 0, x: -10 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
onClick={() => handleSelectVisitor(visitor)}
|
||||
className={`w-full text-left p-4 hover:bg-neutral-50 dark:hover:bg-neutral-800/50 transition-colors ${
|
||||
className={`w-full text-left p-4 hover:bg-neutral-50 dark:hover:bg-neutral-800/50 transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-inset ${
|
||||
selectedVisitor?.session_id === visitor.session_id ? 'bg-neutral-50 dark:bg-neutral-800/50 ring-1 ring-inset ring-neutral-200 dark:ring-neutral-700' : ''
|
||||
}`}
|
||||
>
|
||||
@@ -181,7 +181,7 @@ export default function RealtimePage() {
|
||||
{/* Session Details */}
|
||||
<div className="flex-1 border border-neutral-200 dark:border-neutral-800 rounded-2xl overflow-hidden flex flex-col bg-white dark:bg-neutral-900">
|
||||
<div className="p-4 border-b border-neutral-200 dark:border-neutral-800 bg-neutral-50 dark:bg-neutral-800/50 flex justify-between items-center">
|
||||
<h2 className="font-semibold text-neutral-900 dark:text-white">
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white">
|
||||
{selectedVisitor ? 'Session Journey' : 'Select a visitor'}
|
||||
</h2>
|
||||
{selectedVisitor && (
|
||||
|
||||
@@ -306,7 +306,7 @@ export default function SiteSettingsPage() {
|
||||
<div className="min-h-screen pt-12 pb-12 px-4 sm:px-6">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-neutral-900 dark:text-white">Site Settings</h1>
|
||||
<h1 className="text-2xl font-bold text-neutral-900 dark:text-white">Site Settings</h1>
|
||||
<p className="mt-2 text-neutral-600 dark:text-neutral-400">
|
||||
Manage settings for <span className="font-medium text-neutral-900 dark:text-white">{site.domain}</span>
|
||||
</p>
|
||||
@@ -314,10 +314,12 @@ export default function SiteSettingsPage() {
|
||||
|
||||
<div className="flex flex-col md:flex-row gap-8">
|
||||
{/* Sidebar Navigation */}
|
||||
<nav className="w-full md:w-64 flex-shrink-0 space-y-1">
|
||||
<nav className="w-full md:w-64 flex-shrink-0 space-y-1" role="tablist" aria-label="Site settings sections">
|
||||
<button
|
||||
onClick={() => setActiveTab('general')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'general'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'general'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -328,7 +330,9 @@ export default function SiteSettingsPage() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('visibility')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'visibility'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'visibility'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -339,7 +343,9 @@ export default function SiteSettingsPage() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('data')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'data'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'data'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -350,7 +356,9 @@ export default function SiteSettingsPage() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('goals')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'goals'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'goals'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -381,7 +389,7 @@ export default function SiteSettingsPage() {
|
||||
<div className="space-y-12">
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">General Configuration</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">General Configuration</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Update your site details and tracking script.</p>
|
||||
</div>
|
||||
|
||||
@@ -433,7 +441,7 @@ export default function SiteSettingsPage() {
|
||||
</div>
|
||||
|
||||
<div className="pt-4 border-t border-neutral-100 dark:border-neutral-800">
|
||||
<h3 className="text-lg font-medium text-neutral-900 dark:text-white mb-2">Tracking Script</h3>
|
||||
<h3 className="text-lg font-semibold text-neutral-900 dark:text-white mb-2">Tracking Script</h3>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400 mb-4">
|
||||
Add this script to your website to start tracking visitors.
|
||||
</p>
|
||||
@@ -455,7 +463,7 @@ export default function SiteSettingsPage() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowVerificationModal(true)}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-white dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 text-neutral-700 dark:text-neutral-300 rounded-xl hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-all text-sm font-medium"
|
||||
className="flex items-center gap-2 px-4 py-2 bg-white dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 text-neutral-700 dark:text-neutral-300 rounded-xl hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-all text-sm font-medium focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2"
|
||||
>
|
||||
<ZapIcon className="w-4 h-4" />
|
||||
Verify Installation
|
||||
@@ -490,9 +498,9 @@ export default function SiteSettingsPage() {
|
||||
{canEdit && (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-red-600 dark:text-red-500 mb-1">Danger Zone</h2>
|
||||
<h2 className="text-2xl font-bold text-red-600 dark:text-red-500 mb-1">Danger Zone</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Irreversible actions for your site.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="p-4 border border-red-200 dark:border-red-900/50 bg-red-50 dark:bg-red-900/10 rounded-2xl flex items-center justify-between">
|
||||
@@ -502,7 +510,7 @@ export default function SiteSettingsPage() {
|
||||
</div>
|
||||
<button
|
||||
onClick={handleResetData}
|
||||
className="px-4 py-2 bg-white dark:bg-neutral-900 border border-red-200 dark:border-red-900 text-red-600 dark:text-red-400 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors text-sm font-medium"
|
||||
className="px-4 py-2 bg-white dark:bg-neutral-900 border border-red-200 dark:border-red-900 text-red-600 dark:text-red-400 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors text-sm font-medium focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
||||
>
|
||||
Reset Data
|
||||
</button>
|
||||
@@ -515,7 +523,7 @@ export default function SiteSettingsPage() {
|
||||
</div>
|
||||
<button
|
||||
onClick={handleDeleteSite}
|
||||
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors text-sm font-medium"
|
||||
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors text-sm font-medium focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
||||
>
|
||||
Delete Site
|
||||
</button>
|
||||
@@ -530,7 +538,7 @@ export default function SiteSettingsPage() {
|
||||
<div className="space-y-12">
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">Visibility Settings</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">Visibility Settings</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Manage who can view your dashboard.</p>
|
||||
</div>
|
||||
|
||||
@@ -555,7 +563,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, is_public: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -581,7 +589,7 @@ export default function SiteSettingsPage() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={copyLink}
|
||||
className="px-4 py-2 bg-white dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 text-neutral-900 dark:text-white rounded-xl font-medium hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors"
|
||||
className="px-4 py-2 bg-white dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 text-neutral-900 dark:text-white rounded-xl font-medium hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2"
|
||||
>
|
||||
{linkCopied ? 'Copied!' : 'Copy Link'}
|
||||
</button>
|
||||
@@ -607,7 +615,7 @@ export default function SiteSettingsPage() {
|
||||
}}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -664,7 +672,7 @@ export default function SiteSettingsPage() {
|
||||
<div className="space-y-12">
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">Data & Privacy</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">Data & Privacy</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Control what visitor data is collected. Less data = more privacy.</p>
|
||||
</div>
|
||||
|
||||
@@ -688,7 +696,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, collect_page_paths: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -709,7 +717,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, collect_referrers: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -730,7 +738,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, collect_device_info: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -775,7 +783,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, collect_screen_resolution: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -799,7 +807,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, filter_bots: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -823,7 +831,7 @@ export default function SiteSettingsPage() {
|
||||
onChange={(e) => setFormData({ ...formData, enable_performance_insights: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-orange"></div>
|
||||
<div className="w-11 h-6 bg-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-orange/20 dark:peer-focus:ring-brand-orange/20 rounded-full peer dark:bg-neutral-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-neutral-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-neutral-600 peer-checked:bg-brand-orange"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -921,7 +929,7 @@ export default function SiteSettingsPage() {
|
||||
{activeTab === 'goals' && (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">Goals & Events</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">Goals & Events</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">
|
||||
Define goals to label custom events (e.g. signup, purchase). Track with <code className="px-1.5 py-0.5 rounded bg-neutral-200 dark:bg-neutral-700 text-xs">pulse.track('event_name')</code> in your snippet.
|
||||
</p>
|
||||
|
||||
@@ -55,7 +55,7 @@ export default function NewSitePage() {
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8 max-w-2xl">
|
||||
<h1 className="text-3xl font-bold mb-8 text-neutral-900 dark:text-white">
|
||||
<h1 className="text-2xl font-bold mb-8 text-neutral-900 dark:text-white">
|
||||
Create New Site
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function ToolsPage() {
|
||||
<div className="max-w-2xl mx-auto py-10 px-4">
|
||||
<h1 className="text-2xl font-bold mb-6 text-neutral-900 dark:text-white">Tools</h1>
|
||||
<div className="bg-white dark:bg-neutral-900 p-6 rounded-2xl border border-neutral-200 dark:border-neutral-800">
|
||||
<h2 className="text-lg font-semibold mb-4 text-neutral-900 dark:text-white">UTM Campaign Builder</h2>
|
||||
<h2 className="text-2xl font-bold mb-4 text-neutral-900 dark:text-white">UTM Campaign Builder</h2>
|
||||
<UtmBuilder />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,13 +51,13 @@ export function Footer({ LinkComponent = Link, appName = 'Pulse', isAuthenticate
|
||||
© 2024-{year} Ciphera. All rights reserved.
|
||||
</div>
|
||||
<div className="flex gap-6 text-sm font-medium text-neutral-600 dark:text-neutral-300">
|
||||
<Component href="/about" className="hover:text-brand-orange transition-colors">
|
||||
<Component href="/about" className="hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded">
|
||||
Why {appName}
|
||||
</Component>
|
||||
<Component href="/pricing" className="hover:text-brand-orange transition-colors">
|
||||
<Component href="/pricing" className="hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded">
|
||||
Pricing
|
||||
</Component>
|
||||
<Component href="/faq" className="hover:text-brand-orange transition-colors">
|
||||
<Component href="/faq" className="hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded">
|
||||
FAQ
|
||||
</Component>
|
||||
</div>
|
||||
@@ -102,7 +102,7 @@ export function Footer({ LinkComponent = Link, appName = 'Pulse', isAuthenticate
|
||||
href="https://github.com/ciphera-net"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-9 h-9 rounded-lg bg-neutral-100 dark:bg-neutral-800 flex items-center justify-center text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange hover:bg-neutral-200 dark:hover:bg-neutral-700 transition-colors"
|
||||
className="w-9 h-9 rounded-lg bg-neutral-100 dark:bg-neutral-800 flex items-center justify-center text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange hover:bg-neutral-200 dark:hover:bg-neutral-700 transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange"
|
||||
aria-label="GitHub"
|
||||
>
|
||||
<GithubIcon className="w-5 h-5" />
|
||||
@@ -111,7 +111,7 @@ export function Footer({ LinkComponent = Link, appName = 'Pulse', isAuthenticate
|
||||
href="https://x.com/cipheranet"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-9 h-9 rounded-lg bg-neutral-100 dark:bg-neutral-800 flex items-center justify-center text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange hover:bg-neutral-200 dark:hover:bg-neutral-700 transition-colors"
|
||||
className="w-9 h-9 rounded-lg bg-neutral-100 dark:bg-neutral-800 flex items-center justify-center text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange hover:bg-neutral-200 dark:hover:bg-neutral-700 transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange"
|
||||
aria-label="X (Twitter)"
|
||||
>
|
||||
<TwitterIcon className="w-5 h-5" />
|
||||
@@ -130,14 +130,14 @@ export function Footer({ LinkComponent = Link, appName = 'Pulse', isAuthenticate
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
{link.name}
|
||||
</a>
|
||||
) : (
|
||||
<Component
|
||||
href={link.href}
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
{link.name}
|
||||
</Component>
|
||||
@@ -158,14 +158,14 @@ export function Footer({ LinkComponent = Link, appName = 'Pulse', isAuthenticate
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
{link.name}
|
||||
</a>
|
||||
) : (
|
||||
<Component
|
||||
href={link.href}
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
{link.name}
|
||||
</Component>
|
||||
@@ -186,14 +186,14 @@ export function Footer({ LinkComponent = Link, appName = 'Pulse', isAuthenticate
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
{link.name}
|
||||
</a>
|
||||
) : (
|
||||
<Component
|
||||
href={link.href}
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors"
|
||||
className="text-sm text-neutral-600 dark:text-neutral-400 hover:text-brand-orange dark:hover:text-brand-orange transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
{link.name}
|
||||
</Component>
|
||||
|
||||
@@ -219,7 +219,7 @@ export default function PricingSection() {
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-center mb-12"
|
||||
>
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-neutral-900 dark:text-white mb-6 tracking-tight">
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-6">
|
||||
Transparent Pricing
|
||||
</h2>
|
||||
<p className="text-xl text-neutral-600 dark:text-neutral-400">
|
||||
|
||||
@@ -96,18 +96,20 @@ export default function ContentStats({ topPages, entryPages, exitPages, domain,
|
||||
{showViewAll && (
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors"
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
View All
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg">
|
||||
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg" role="tablist" aria-label="Content view tabs">
|
||||
{(['top_pages', 'entry_pages', 'exit_pages'] as Tab[]).map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === tab}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange ${
|
||||
activeTab === tab
|
||||
? 'bg-white dark:bg-neutral-700 text-neutral-900 dark:text-white shadow-sm'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white'
|
||||
|
||||
@@ -196,18 +196,20 @@ export default function Locations({ countries, cities, regions, geoDataLevel = '
|
||||
{showViewAll && (
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors"
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
View All
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg">
|
||||
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg" role="tablist" aria-label="Location view tabs">
|
||||
{(['map', 'countries', 'regions', 'cities'] as Tab[]).map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors capitalize ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === tab}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors capitalize focus:outline-none focus:ring-2 focus:ring-brand-orange ${
|
||||
activeTab === tab
|
||||
? 'bg-white dark:bg-neutral-700 text-neutral-900 dark:text-white shadow-sm'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white'
|
||||
|
||||
@@ -119,18 +119,20 @@ export default function TechSpecs({ browsers, os, devices, screenResolutions, co
|
||||
{showViewAll && (
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors"
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
View All
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg">
|
||||
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg" role="tablist" aria-label="Technology view tabs">
|
||||
{(['browsers', 'os', 'devices', 'screens'] as Tab[]).map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors capitalize ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === tab}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors capitalize focus:outline-none focus:ring-2 focus:ring-brand-orange ${
|
||||
activeTab === tab
|
||||
? 'bg-white dark:bg-neutral-700 text-neutral-900 dark:text-white shadow-sm'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white'
|
||||
|
||||
@@ -63,7 +63,7 @@ export default function TopReferrers({ referrers, collectReferrers = true, siteI
|
||||
{showViewAll && (
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors"
|
||||
className="text-xs font-medium text-neutral-500 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded"
|
||||
>
|
||||
View All
|
||||
</button>
|
||||
|
||||
@@ -353,7 +353,7 @@ export default function OrganizationSettings() {
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-neutral-900 dark:text-white">Organization Settings</h1>
|
||||
<h1 className="text-2xl font-bold text-neutral-900 dark:text-white">Organization Settings</h1>
|
||||
<p className="mt-2 text-neutral-600 dark:text-neutral-400">
|
||||
Manage your organization workspace and members.
|
||||
</p>
|
||||
@@ -361,10 +361,12 @@ export default function OrganizationSettings() {
|
||||
|
||||
<div className="flex flex-col md:flex-row gap-8">
|
||||
{/* Sidebar Navigation */}
|
||||
<nav className="w-full md:w-64 flex-shrink-0 space-y-1">
|
||||
<nav className="w-full md:w-64 flex-shrink-0 space-y-1" role="tablist" aria-label="Organization settings sections">
|
||||
<button
|
||||
onClick={() => handleTabChange('general')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'general'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'general'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -375,7 +377,9 @@ export default function OrganizationSettings() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleTabChange('members')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'members'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'members'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -386,7 +390,9 @@ export default function OrganizationSettings() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleTabChange('billing')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'billing'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'billing'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -397,7 +403,9 @@ export default function OrganizationSettings() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleTabChange('audit')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 ${
|
||||
role="tab"
|
||||
aria-selected={activeTab === 'audit'}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2 ${
|
||||
activeTab === 'audit'
|
||||
? 'bg-brand-orange/10 text-brand-orange'
|
||||
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
||||
@@ -420,9 +428,9 @@ export default function OrganizationSettings() {
|
||||
{activeTab === 'general' && (
|
||||
<div className="space-y-12">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">General Information</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">General Information</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Basic details about your organization.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleUpdateOrg} className="space-y-4">
|
||||
<div className="space-y-1.5">
|
||||
@@ -497,7 +505,7 @@ export default function OrganizationSettings() {
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-red-600 dark:text-red-500 mb-1">Danger Zone</h2>
|
||||
<h2 className="text-2xl font-bold text-red-600 dark:text-red-500 mb-1">Danger Zone</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Irreversible actions for this organization.</p>
|
||||
</div>
|
||||
|
||||
@@ -521,7 +529,7 @@ export default function OrganizationSettings() {
|
||||
<div className="space-y-12">
|
||||
{/* Invite Section */}
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">Organization Members</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">Organization Members</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400 mb-6">Manage who has access to this organization.</p>
|
||||
|
||||
<div className="bg-neutral-50 dark:bg-neutral-900/50 border border-neutral-200 dark:border-neutral-800 rounded-2xl p-4">
|
||||
@@ -647,7 +655,7 @@ export default function OrganizationSettings() {
|
||||
{activeTab === 'billing' && (
|
||||
<div className="space-y-12">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">Billing & Subscription</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">Billing & Subscription</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Manage your subscription plan and payment methods.</p>
|
||||
</div>
|
||||
|
||||
@@ -832,7 +840,7 @@ export default function OrganizationSettings() {
|
||||
{activeTab === 'audit' && (
|
||||
<div className="space-y-12">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-1">Audit log</h2>
|
||||
<h2 className="text-2xl font-bold text-neutral-900 dark:text-white mb-1">Audit log</h2>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-400">Who did what and when for this organization.</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function SiteList({ sites, loading, onDelete }: SiteListProps) {
|
||||
if (sites.length === 0) {
|
||||
return (
|
||||
<div className="rounded-lg border border-dashed border-neutral-300 dark:border-neutral-700 p-12 text-center">
|
||||
<h3 className="text-lg font-medium text-neutral-900 dark:text-white">No sites yet</h3>
|
||||
<h3 className="text-lg font-semibold text-neutral-900 dark:text-white">No sites yet</h3>
|
||||
<p className="mt-2 text-sm text-neutral-500 dark:text-neutral-400">Create your first site to get started.</p>
|
||||
</div>
|
||||
)
|
||||
@@ -105,7 +105,7 @@ export default function SiteList({ sites, loading, onDelete }: SiteListProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onDelete(site.id)}
|
||||
className="flex items-center justify-center rounded-lg border border-neutral-200 px-3 hover:bg-neutral-50 dark:border-neutral-700 dark:hover:bg-neutral-800 text-neutral-500 hover:text-red-600 dark:hover:text-red-400 transition-colors"
|
||||
className="flex items-center justify-center rounded-lg border border-neutral-200 px-3 hover:bg-neutral-50 dark:border-neutral-700 dark:hover:bg-neutral-800 text-neutral-500 hover:text-red-600 dark:hover:text-red-400 transition-colors focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
||||
title="Delete Site"
|
||||
>
|
||||
<SettingsIcon className="h-4 w-4" />
|
||||
|
||||
1042
docs/DESIGN_SYSTEM.md
Normal file
1042
docs/DESIGN_SYSTEM.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user