also looking at this
refactor(ui): adopt shared workspace badges
#17
5 files
+118
-9
| @@ -6,6 +6,20 @@ import type { CrosswindConfig, Theme } from '@cwcss/crosswind' | ||
| 6 | 6 | * Use theme entries rather than layered preflight overrides of library tokens. |
| 7 | 7 | */ |
| 8 | 8 | export default { |
| 9 | shortcuts: { | |
| 10 | // Preserve the existing consent pill while Badge owns its markup. Explicit | |
| 11 | // precedence is required: class attribute order does not decide CSS order. | |
| 12 | 'audience-consent-badge': 'sm:!inline !px-2.5 !py-1 !font-bold !text-[#466833] !bg-[#edf5e8] ' | |
| 13 | + 'dark:!text-[#acd294] dark:!bg-[#75a65a]/15', | |
| 14 | // These were flex items. Block-level flex avoids an extra inline baseline | |
| 15 | // inside the component scope wrapper, preserving the original row heights. | |
| 16 | 'workspace-change-badge': '!flex !px-2.5 !py-1 !font-bold !text-[11px] !leading-[inherit] ' | |
| 17 | + '!text-[#42652e] !bg-[#eef5e8] dark:!text-[#a8d28e] dark:!bg-[#75a65a]/15', | |
| 18 | 'workspace-record-badge': '!flex !py-1 !font-bold !text-[10px] !leading-[inherit] ' | |
| 19 | + '!text-[#466833] !bg-[#eef5e8] dark:!text-[#acd294] dark:!bg-[#75a65a]/15', | |
| 20 | // The readiness panel is dark in both modes, so this treatment stays fixed. | |
| 21 | 'workspace-check-badge': '!flex !py-1 !font-bold !text-[10px] !leading-[inherit] !text-[#bfe2ab] !bg-white/10', | |
| 22 | }, | |
| 9 | 23 | theme: { |
| 10 | 24 | extend: { |
| 11 | 25 | borderRadius: { |
| @@ -11,7 +11,7 @@ const contacts = [ | ||
| 11 | 11 | <div class="mx-auto max-w-[1500px]"> |
| 12 | 12 | <header class="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between mb-7"> |
| 13 | 13 | <div> |
| 14 | <p class="font-bold text-[#b8402f] dark:text-[#ff8c79] text-[11px] tracking-[0.2em] uppercase">Audience</p> | |
| 14 | <p class="font-bold text-[#b8402f] text-[11px] tracking-[0.2em] uppercase dark:text-[#ff8c79]">Audience</p> | |
| 15 | 15 | <h1 class="mt-2 font-semibold text-4xl tracking-[-0.04em]">People, not rows.</h1> |
| 16 | 16 | <p class="mt-2 max-w-2xl text-[#666a63] text-sm dark:text-[#aaa9a3]">One profile across email, SMS, purchases, consent, and publication membership.</p> |
| 17 | 17 | </div> |
| @@ -33,17 +33,17 @@ const contacts = [ | ||
| 33 | 33 | <label class="relative"><span class="sr-only">Search contacts</span><span aria-hidden="true" class="absolute left-3 top-3 h-4 w-4 text-[#5f635d] dark:text-[#bcbab5] i-hugeicons-search-01"></span><input type="search" class="pl-9 pr-4 min-h-11 w-full sm:w-auto text-sm bg-transparent border border-[#171916]/12 rounded-full dark:border-white/15 focus:border-[#bf4936] focus:outline-none" placeholder="Search people"></label> |
| 34 | 34 | </div> |
| 35 | 35 | |
| 36 | <div class="sm:hidden divide-y divide-[#171916]/10 dark:divide-white/10"> | |
| 36 | <div class="sm:hidden divide-[#171916]/10 divide-y dark:divide-white/10"> | |
| 37 | 37 | @foreach(contacts as contact) |
| 38 | 38 | <article class="p-5"> |
| 39 | 39 | <div class="flex gap-3 items-start justify-between"> |
| 40 | 40 | <div class="min-w-0"><h3 class="font-bold text-sm">{{ contact.name }}</h3><p class="mt-0.5 break-all text-[#5f635d] text-xs dark:text-[#bcbab5]">{{ contact.address }}</p></div> |
| 41 | 41 | <button type="button" aria-label="Open contact menu for " class="inline-flex items-center justify-center shrink-0 h-11 w-11 hover:bg-black/5 dark:hover:bg-white/10 rounded-full"><span aria-hidden="true" class="block h-4 w-4 i-hugeicons-more-horizontal"></span></button> |
| 42 | 42 | </div> |
| 43 | <dl class="grid grid-cols-2 gap-3 mt-4 text-xs"> | |
| 43 | <dl class="grid gap-3 grid-cols-2 mt-4 text-xs"> | |
| 44 | 44 | <div><dt class="text-[#5f635d] dark:text-[#bcbab5]">Source</dt><dd class="mt-1 font-medium">{{ contact.source }}</dd></div> |
| 45 | 45 | <div><dt class="text-[#5f635d] dark:text-[#bcbab5]">Revenue</dt><dd class="mt-1 font-bold">{{ contact.value }}</dd></div> |
| 46 | <div class="col-span-2"><dt class="sr-only">Consent</dt><dd class="inline-flex px-2.5 py-1 font-bold text-[#466833] dark:text-[#acd294] bg-[#edf5e8] dark:bg-[#75a65a]/15 rounded-full">{{ contact.state }}</dd></div> | |
| 46 | <div class="col-span-2"><dt class="sr-only">Consent</dt><dd><Badge size="sm" className="audience-consent-badge">{{ contact.state }}</Badge></dd></div> | |
| 47 | 47 | </dl> |
| 48 | 48 | </article> |
| 49 | 49 | @endforeach |
| @@ -57,7 +57,7 @@ const contacts = [ | ||
| 57 | 57 | <tr class="border-[#171916]/8 border-t dark:border-white/8"> |
| 58 | 58 | <td class="px-5 py-4"><p class="font-bold text-sm">{{ contact.name }}</p><p class="mt-0.5 text-[#5f635d] text-xs dark:text-[#bcbab5]">{{ contact.address }}</p></td> |
| 59 | 59 | <td class="px-5 py-4 text-sm">{{ contact.source }}</td> |
| 60 | <td class="px-5 py-4"><span class="px-2.5 py-1 font-bold text-[#466833] text-xs dark:text-[#acd294] bg-[#edf5e8] dark:bg-[#75a65a]/15 rounded-full">{{ contact.state }}</span></td> | |
| 60 | <td class="px-5 py-4"><Badge size="sm" className="audience-consent-badge">{{ contact.state }}</Badge></td> | |
| 61 | 61 | <td class="px-5 py-4 font-bold text-sm">{{ contact.value }}</td> |
| 62 | 62 | <td class="px-5 py-4 text-right"><button type="button" aria-label="Open contact menu for " class="inline-flex items-center justify-center h-11 w-11 hover:bg-black/5 dark:hover:bg-white/10 rounded-full"><span aria-hidden="true" class="block h-4 w-4 i-hugeicons-more-horizontal"></span></button></td> |
| 63 | 63 | </tr> |
| @@ -18,7 +18,7 @@ const activity = [ | ||
| 18 | 18 | <div class="mx-auto max-w-[1500px]"> |
| 19 | 19 | <header class="flex flex-col gap-5 lg:flex-row lg:items-end lg:justify-between pb-7 border-[#171916]/10 border-b dark:border-white/10"> |
| 20 | 20 | <div> |
| 21 | <p class="mb-2 font-bold text-[#bd3e2e] dark:text-[#ff8a78] text-[11px] tracking-[0.2em] uppercase">Sunday Paper Co.</p> | |
| 21 | <p class="mb-2 font-bold text-[#bd3e2e] text-[11px] tracking-[0.2em] uppercase dark:text-[#ff8a78]">Sunday Paper Co.</p> | |
| 22 | 22 | <h1 class="max-w-3xl font-semibold text-3xl tracking-[-0.04em] sm:text-4xl">Your audience is growing. Three moments need your attention.</h1> |
| 23 | 23 | </div> |
| 24 | 24 | <div class="flex flex-wrap gap-2"> |
| @@ -32,7 +32,7 @@ const activity = [ | ||
| 32 | 32 | <div class="grid gap-3 sm:grid-cols-2 xl:grid-cols-4"> |
| 33 | 33 | @foreach(performance as item) |
| 34 | 34 | <article class="p-5 bg-white/75 dark:bg-white/[0.04] border border-[#171916]/10 rounded-[1.4rem] dark:border-white/10 shadow-[0_1px_0_rgba(23,25,22,0.04)] hover:shadow-[0_18px_45px_rgba(35,28,22,0.08)] transition group hover:-translate-y-0.5"> |
| 35 | <div class="flex items-center justify-between mb-6"><span class="grid place-items-center h-9 w-9 text-[#bd3e2e] dark:text-[#ff8c79] bg-[#fce5df] dark:bg-[#e65743]/15 rounded-full"><span class="h-[18px] w-[18px] "></span></span><span class="px-2.5 py-1 font-bold text-[#42652e] text-[11px] dark:text-[#a8d28e] bg-[#eef5e8] dark:bg-[#75a65a]/15 rounded-full">{{ item.change }}</span></div> | |
| 35 | <div class="flex items-center justify-between mb-6"><span class="grid place-items-center h-9 w-9 text-[#bd3e2e] dark:text-[#ff8c79] bg-[#fce5df] dark:bg-[#e65743]/15 rounded-full"><span class="h-[18px] w-[18px] "></span></span><Badge size="sm" className="workspace-change-badge">{{ item.change }}</Badge></div> | |
| 36 | 36 | <p class="font-semibold text-3xl tracking-[-0.04em]">{{ item.value }}</p><p class="mt-1 text-[#6c6f68] text-sm dark:text-[#aaa9a3]">{{ item.label }}</p> |
| 37 | 37 | </article> |
| 38 | 38 | @endforeach |
| @@ -162,7 +162,7 @@ const viewState = state('populated') | ||
| 162 | 162 | <div class="flex items-center justify-between px-5 py-4 border-[#171916]/10 border-b dark:border-white/10"><h2 id="records-title" class="font-bold text-sm">Active work</h2><button type="button" aria-label="Filter records" class="p-2 text-[#6c6f68] dark:text-[#aaa9a3] hover:bg-black/5 dark:hover:bg-white/10 rounded-full"><span aria-hidden="true" class="block h-4 w-4 i-hugeicons-filter-horizontal"></span></button></div> |
| 163 | 163 | <div class="divide-[#171916]/8 divide-y dark:divide-white/8"> |
| 164 | 164 | @foreach(page().records as record) |
| 165 | <article class="grid gap-4 sm:grid-cols-[1fr_auto] sm:items-center px-5 py-5"><div><div class="flex flex-wrap gap-2 items-center"><h3 class="font-bold text-sm">{{ record.name }}</h3><span class="px-2 py-1 font-bold text-[#466833] text-[10px] dark:text-[#acd294] bg-[#eef5e8] dark:bg-[#75a65a]/15 rounded-full">{{ record.status }}</span></div><p class="mt-1 leading-5 text-[#6c6f68] text-xs dark:text-[#aaa9a3]">{{ record.detail }}</p></div><p class="font-bold text-sm">{{ record.value }}</p></article> | |
| 165 | <article class="grid gap-4 sm:grid-cols-[1fr_auto] sm:items-center px-5 py-5"><div><div class="flex flex-wrap gap-2 items-center"><h3 class="font-bold text-sm">{{ record.name }}</h3><Badge size="sm" className="workspace-record-badge">{{ record.status }}</Badge></div><p class="mt-1 leading-5 text-[#6c6f68] text-xs dark:text-[#aaa9a3]">{{ record.detail }}</p></div><p class="font-bold text-sm">{{ record.value }}</p></article> | |
| 166 | 166 | @endforeach |
| 167 | 167 | </div> |
| 168 | 168 | </section> |
| @@ -171,7 +171,7 @@ const viewState = state('populated') | ||
| 171 | 171 | <div class="flex items-center justify-between"><h2 id="checks-title" class="font-bold text-sm">Readiness checks</h2><span aria-hidden="true" class="h-5 w-5 text-[#ff8c79] i-hugeicons-shield-02"></span></div> |
| 172 | 172 | <div class="mt-5 space-y-1"> |
| 173 | 173 | @foreach(page().checklist as check) |
| 174 | <div class="py-4 border-b border-white/10 last:border-0"><div class="flex gap-4 items-start justify-between"><p class="font-bold text-sm">{{ check.label }}</p><span class="px-2 py-1 font-bold text-[#bfe2ab] text-[10px] bg-white/10 rounded-full">{{ check.state }}</span></div><p class="mt-1 leading-5 text-white/55 text-xs">{{ check.detail }}</p></div> | |
| 174 | <div class="py-4 border-b border-white/10 last:border-0"><div class="flex gap-4 items-start justify-between"><p class="font-bold text-sm">{{ check.label }}</p><Badge size="sm" className="workspace-check-badge">{{ check.state }}</Badge></div><p class="mt-1 leading-5 text-white/55 text-xs">{{ check.detail }}</p></div> | |
| 175 | 175 | @endforeach |
| 176 | 176 | </div> |
| 177 | 177 | </aside> |