Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 20 additions & 45 deletions src/lib/components/Card.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
*
* Two deliberate extensions to the upstream API, neither of which changes how
* a plain Card renders:
* - `href` renders the card as an anchor, making the whole card one click
* target (upstream is always a <section>).
* - `href` makes the title a link (upstream has no link variant). Only the
* title is the link, not the whole card: text inside an anchor cannot be
* selected by dragging, and the subtitle and body must stay selectable.
* - `leading` is a snippet slot before the titles, for an icon.
*/
import type { Snippet } from 'svelte';
Expand Down Expand Up @@ -62,7 +63,8 @@
<div class="ogcr-card__titles">
{#if title}
<!-- svelte-ignore svelte_component_deprecated -->
<svelte:element this={`h${headingLevel}`} class="ogcr-card__title">{title}</svelte:element
<svelte:element this={`h${headingLevel}`} class="ogcr-card__title"
>{#if href}<a {href} class="ogcr-card__link">{title}</a>{:else}{title}{/if}</svelte:element
>
{/if}
{#if subtitle}
Expand All @@ -79,24 +81,13 @@
{/if}
{/snippet}

{#if href}
<a
{href}
class="ogcr-card ogcr-card--link ogcr-card--padding-{padding} {className}"
class:ogcr-card--floating={floating}
{...rest}
>
{@render inner()}
</a>
{:else}
<section
class="ogcr-card ogcr-card--padding-{padding} {className}"
class:ogcr-card--floating={floating}
{...rest}
>
{@render inner()}
</section>
{/if}
<section
class="ogcr-card ogcr-card--padding-{padding} {className}"
class:ogcr-card--floating={floating}
{...rest}
>
{@render inner()}
</section>

<style>
.ogcr-card {
Expand Down Expand Up @@ -126,38 +117,26 @@
box-shadow: var(--elevation-l);
}

/* Link cards lift on hover via elevation and a border shift — never a fill
change, which would not survive a theme swap and reads as a state change
rather than an affordance. */
.ogcr-card--link {
text-decoration: none;
/* The title link reads as the title, underlining on hover like any link. */
.ogcr-card__link {
color: inherit;
transition:
border-color var(--motion-fast),
box-shadow var(--motion-fast);
text-decoration: none;
}

.ogcr-card--link:hover {
border-color: var(--border-strong);
box-shadow: var(--elevation-l);
.ogcr-card__link:hover {
text-decoration: underline;
}

/* Two-stop focus ring, spec §8: an inner surface halo so the ring has
breathing room without outline-offset, then the solid interaction tone
at 4px, which clears the 3:1 minimum of WCAG SC 2.4.11. */
.ogcr-card--link:focus-visible {
.ogcr-card__link:focus-visible {
outline: none;
border-radius: var(--radius-s);
box-shadow:
0 0 0 2px var(--surface-light),
0 0 0 4px var(--interaction-primary-default);
}

@media (prefers-reduced-motion: reduce) {
.ogcr-card--link {
transition: none;
}
}

.ogcr-card__header {
display: flex;
align-items: center;
Expand Down Expand Up @@ -236,11 +215,7 @@
color: var(--color-primary-200);
}

:global([data-mode='dark']) .ogcr-card--link:hover {
border-color: var(--color-surface-500);
}

:global([data-mode='dark']) .ogcr-card--link:focus-visible {
:global([data-mode='dark']) .ogcr-card__link:focus-visible {
box-shadow:
0 0 0 2px var(--color-surface-900),
0 0 0 4px var(--interaction-primary-default);
Expand Down
34 changes: 20 additions & 14 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@
icon: Link2,
title: 'Chain',
description: 'Inspect on-chain state and the sync status.'
},
{
href: '/design',
icon: Palette,
title: 'Design System',
description: 'Browse OGCR components and tokens.'
}
];

Expand Down Expand Up @@ -87,20 +81,18 @@
<title>OGCR DCR</title>
</svelte:head>

<!-- The app's own sections first; after a gap, the OBP tools of this deployment. -->
<!-- The app's own sections first; then the technical environment of this deployment; the design system last. -->
<section class="flex w-full justify-center p-8">
<div class="w-full max-w-5xl">
<div class="text-center">
<img src="/ogcr_logo.svg" alt="OGCR" class="mx-auto mb-6 h-16" />
<h1 class="mb-6 h1">OGCR DCR</h1>
<p class="mb-4 text-xl text-surface-600-400">
Explore features and architecture of the OGCR DCR
<p class="mb-4 h3 text-surface-600-400">
Explore and Operate
</p>
</div>

<!-- 1 column on mobile, 2 on tablet, 3 on desktop (design system §3). Six
cards divide evenly into three, where the four-column desktop maximum
would leave a ragged 4 + 2. -->
<!-- 1 column on mobile, 2 on tablet, 3 on desktop (design system §3). -->
<nav aria-label="Sections" class="mt-10 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{#each destinations as { href, icon: Icon, title, description } (href)}
<Card {href} {title} subtitle={description}>
Expand All @@ -114,9 +106,9 @@
</section>

{#if tools.length > 0}
<section aria-labelledby="obp-tools" class="mt-16 flex w-full justify-center px-8 pb-12">
<section aria-labelledby="obp-tools" class="mt-16 flex w-full justify-center px-8">
<div class="w-full max-w-5xl">
<h2 id="obp-tools" class="mb-6 text-center h3">Environment</h2>
<h2 id="obp-tools" class="mb-6 text-center h3">Technical Environment</h2>
<nav aria-labelledby="obp-tools" class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{#each tools as { href, icon: Icon, title, description } (title)}
<Card {href} {title} subtitle={description}>
Expand All @@ -129,3 +121,17 @@
</div>
</section>
{/if}

<section aria-labelledby="design" class="mt-16 flex w-full justify-center px-8 pb-12">
<div class="w-full max-w-5xl">
<h2 id="design" class="mb-6 text-center h3">Design</h2>
<!-- One card, centred at the width of one column of the grids above. -->
<nav aria-labelledby="design" class="mx-auto grid max-w-sm grid-cols-1">
<Card href="/design" title="Design System" subtitle="Browse OGCR components and tokens.">
{#snippet leading()}
<Palette class="size-6" aria-hidden="true" />
{/snippet}
</Card>
</nav>
</div>
</section>
3 changes: 2 additions & 1 deletion src/routes/design/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,8 @@
<Card title="Link card" subtitle="app extension" href="/design" padding="l">
<p class="text-body-s" style="color: var(--text-secondary);">
<code>href</code> and the <code>leading</code> snippet are our two documented additions to the
upstream API. Hover lifts by elevation, never by fill.
upstream API. With <code>href</code> only the title is a link, so the rest of the card
stays selectable text.
</p>
</Card>
</div>
Expand Down
Loading