fix(settings): wrap all settings items in card blocks for visual consistency

This commit is contained in:
Usman Baig
2026-03-25 22:44:23 +01:00
parent e7b8943097
commit 1da71aa1a2
7 changed files with 31 additions and 26 deletions

View File

@@ -69,8 +69,8 @@ export default function AccountProfileTab({ onDirtyChange, onRegisterSave }: { o
</div>
{/* Display Name */}
<div className="space-y-4">
<div>
<div className="space-y-3">
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Display Name</label>
<Input
value={displayName}
@@ -80,7 +80,7 @@ export default function AccountProfileTab({ onDirtyChange, onRegisterSave }: { o
</div>
{/* Email — read-only display */}
<div>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Email Address</label>
<Input value={user.email} disabled className="opacity-60" />
<p className="text-xs text-neutral-500 mt-1">Email changes require password verification. Use <a href="https://auth.ciphera.net/settings" target="_blank" rel="noopener noreferrer" className="text-brand-orange hover:underline">Ciphera Auth</a> to change your email.</p>

View File

@@ -104,13 +104,13 @@ export default function SiteGeneralTab({ siteId, onDirtyChange, onRegisterSave }
<p className="text-sm text-neutral-400">Update your site details and tracking script.</p>
</div>
<div className="space-y-4">
<div>
<div className="space-y-3">
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Site Name</label>
<Input value={name} onChange={e => setName(e.target.value)} placeholder="My Website" />
</div>
<div>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Timezone</label>
<Select
value={timezone}
@@ -120,7 +120,7 @@ export default function SiteGeneralTab({ siteId, onDirtyChange, onRegisterSave }
/>
</div>
<div>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Domain</label>
<Input value={site.domain} disabled className="opacity-60" />
<p className="text-xs text-neutral-500 mt-1">Domain cannot be changed after creation.</p>

View File

@@ -18,7 +18,7 @@ const GEO_OPTIONS = [
function PrivacyToggle({ label, desc, checked, onToggle }: { label: string; desc: string; checked: boolean; onToggle: () => void }) {
return (
<div className="flex items-center justify-between py-3 px-4 rounded-xl hover:bg-neutral-800/20 transition-colors">
<div className="flex items-center justify-between p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<div>
<p className="text-sm font-medium text-white">{label}</p>
<p className="text-xs text-neutral-500">{desc}</p>
@@ -132,7 +132,7 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
<p className="text-sm text-neutral-400">Control what data is collected from your visitors.</p>
</div>
<div className="space-y-1">
<div className="space-y-3">
<PrivacyToggle label="Page paths" desc="Track which pages visitors view." checked={collectPagePaths} onToggle={() => setCollectPagePaths(v => !v)} />
<PrivacyToggle label="Referrers" desc="Track where visitors come from." checked={collectReferrers} onToggle={() => setCollectReferrers(v => !v)} />
<PrivacyToggle label="Device info" desc="Track browser, OS, and device type." checked={collectDeviceInfo} onToggle={() => setCollectDeviceInfo(v => !v)} />
@@ -140,15 +140,20 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
<PrivacyToggle label="Hide unknown locations" desc='Exclude "Unknown" from location stats.' checked={hideUnknownLocations} onToggle={() => setHideUnknownLocations(v => !v)} />
</div>
<div>
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Geographic data</label>
<Select
value={collectGeoData}
onChange={setCollectGeoData}
variant="input"
options={GEO_OPTIONS}
/>
<p className="text-xs text-neutral-500 mt-1">Controls location granularity. "Disabled" collects no geographic data at all.</p>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-white">Geographic data</p>
<p className="text-xs text-neutral-500 mt-0.5">Controls location granularity. &quot;Disabled&quot; collects no geographic data at all.</p>
</div>
<Select
value={collectGeoData}
onChange={setCollectGeoData}
variant="input"
options={GEO_OPTIONS}
className="min-w-[200px]"
/>
</div>
</div>
{/* Data Retention */}

View File

@@ -90,7 +90,7 @@ export default function SiteVisibilityTab({ siteId, onDirtyChange, onRegisterSav
className="space-y-4 overflow-hidden"
>
{/* Share link */}
<div>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Public Link</label>
<div className="flex gap-2">
<Input value={`${APP_URL}/share/${siteId}`} readOnly className="font-mono text-xs" />

View File

@@ -91,18 +91,18 @@ export default function WorkspaceGeneralTab({ onDirtyChange, onRegisterSave }: {
<p className="text-sm text-neutral-400">Basic details about your organization.</p>
</div>
<div>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Organization Name</label>
<Input value={name} onChange={e => setName(e.target.value)} placeholder="Acme Corp" />
</div>
<div>
<div className="p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<label className="block text-sm font-medium text-neutral-300 mb-1.5">Organization Slug</label>
<div className="flex items-center gap-2">
<span className="text-sm text-neutral-500">pulse.ciphera.net/</span>
<Input value={slug} onChange={e => setSlug(e.target.value)} placeholder="acme-corp" />
</div>
<p className="text-xs text-neutral-500 mt-1">Changing the slug will change your organization's URL.</p>
<p className="text-xs text-neutral-500 mt-1">Changing the slug will change your organization&apos;s URL.</p>
</div>
</div>

View File

@@ -144,9 +144,9 @@ export default function WorkspaceMembersTab() {
)}
{/* Members list */}
<div className="space-y-1">
<div className="rounded-xl border border-neutral-800 bg-neutral-800/30 divide-y divide-neutral-800">
{members.map(member => (
<div key={member.user_id} className="flex items-center justify-between px-4 py-3 rounded-xl hover:bg-neutral-800/40 transition-colors group">
<div key={member.user_id} className="flex items-center justify-between px-4 py-3 group">
<div className="flex items-center gap-3">
<UserCircle weight="fill" className="w-8 h-8 text-neutral-600" />
<div>

View File

@@ -62,9 +62,9 @@ export default function WorkspaceNotificationsTab({ onDirtyChange, onRegisterSav
<p className="text-sm text-neutral-400">Choose what notifications you receive.</p>
</div>
<div className="space-y-1">
<div className="space-y-3">
{(data?.categories || []).map(cat => (
<div key={cat.id} className="flex items-center justify-between py-3 px-4 rounded-xl hover:bg-neutral-800/20 transition-colors">
<div key={cat.id} className="flex items-center justify-between p-4 rounded-xl border border-neutral-800 bg-neutral-800/30">
<div>
<p className="text-sm font-medium text-white">{cat.label}</p>
<p className="text-xs text-neutral-400">{cat.description}</p>