mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-31 05:15:32 +00:00
fix(stats): refine hero layout for responsive Figma match
This commit is contained in:
parent
fff7781fa8
commit
3ce9b4be0d
2 changed files with 46 additions and 19 deletions
|
|
@ -89,7 +89,7 @@
|
|||
[data-page="stats"] [data-component="container"] {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 80rem;
|
||||
max-width: calc(80rem + 2px);
|
||||
margin: 0 auto;
|
||||
border-left: 1px solid var(--stats-line);
|
||||
border-right: 1px solid var(--stats-line);
|
||||
|
|
@ -461,6 +461,7 @@
|
|||
}
|
||||
|
||||
[data-page="stats"] [data-section="hero"] h1 {
|
||||
order: 1;
|
||||
color: var(--stats-text);
|
||||
font-size: 64px;
|
||||
font-weight: 500;
|
||||
|
|
@ -469,20 +470,30 @@
|
|||
}
|
||||
|
||||
[data-page="stats"] [data-slot="hero-copy"] {
|
||||
order: 3;
|
||||
color: var(--stats-hero-muted);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="hero-copy-break"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="hero-pattern"] {
|
||||
order: 2;
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
background-image: radial-gradient(circle, var(--stats-hero-pattern) 1px, transparent 1.1px);
|
||||
background-position: 0 0;
|
||||
background-size: 6px 6px;
|
||||
background: var(--stats-hero-pattern);
|
||||
mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E");
|
||||
mask-repeat: repeat;
|
||||
mask-size: 6px 6px;
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E");
|
||||
-webkit-mask-repeat: repeat;
|
||||
-webkit-mask-size: 6px 6px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="hero-meta"] {
|
||||
|
|
@ -496,7 +507,7 @@
|
|||
background: var(--stats-layer-2);
|
||||
color: var(--stats-hero-muted);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
|
@ -514,10 +525,10 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (min-width: 58rem) {
|
||||
@media (min-width: 48rem) {
|
||||
[data-page="stats"] [data-section="hero"] {
|
||||
gap: 16px;
|
||||
padding: 128px 40px 24px;
|
||||
padding: 128px 32px 32px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="hero-canvas"] {
|
||||
|
|
@ -553,11 +564,21 @@
|
|||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
width: min(36rem, 100%);
|
||||
width: min(563px, 100%);
|
||||
padding: 12px 0 0 16px;
|
||||
background: var(--stats-bg);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="hero-copy-break"] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 75rem) {
|
||||
[data-page="stats"] [data-section="hero"] {
|
||||
padding: 128px 40px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 90rem) {
|
||||
|
|
@ -1494,7 +1515,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (max-width: 74rem) {
|
||||
@media (max-width: 80rem) {
|
||||
[data-page="stats"] [data-component="container"] {
|
||||
border: 0;
|
||||
}
|
||||
|
|
@ -1540,14 +1561,12 @@
|
|||
--stats-section-padding: 4rem;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-section="hero"],
|
||||
[data-page="stats"] [data-section="chart"],
|
||||
[data-page="stats"] [data-section="newsletter"] {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-section="hero"],
|
||||
[data-page="stats"] [data-section="newsletter"] {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import {
|
|||
import { runtime } from "@opencode-ai/stats-core/runtime"
|
||||
import { createAsync, query } from "@solidjs/router"
|
||||
import { scaleBand, scaleLinear } from "d3-scale"
|
||||
import { createEffect, createMemo, createSignal, For, onCleanup, Show, type JSX } from "solid-js"
|
||||
import { createEffect, createMemo, createSignal, For, onCleanup, onMount, Show, type JSX } from "solid-js"
|
||||
import { getRequestEvent } from "solid-js/web"
|
||||
|
||||
const products = ["All Users", "Zen", "Go", "Enterprise"] as const
|
||||
|
|
@ -98,21 +98,29 @@ export default function StatsHome() {
|
|||
}
|
||||
|
||||
function Hero(props: { updatedAt: string | null }) {
|
||||
const [timeZone, setTimeZone] = createSignal("UTC")
|
||||
onMount(() => setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC"))
|
||||
|
||||
return (
|
||||
<section data-section="hero">
|
||||
<p data-slot="hero-meta">
|
||||
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16">
|
||||
<rect x="3" y="3" width="10" height="10" fill="currentColor" />
|
||||
<rect x="7" y="6.5" width="2" height="4.5" fill="var(--stats-layer-2)" />
|
||||
<rect x="7" y="5" width="2" height="1" fill="var(--stats-layer-2)" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M13 13H3V3H13V13ZM6.46777 6.81641V7.81641H7.5791V11.3721H8.5791V6.81641H6.46777ZM7.30078 4.62891V5.62891H8.85645V4.62891H7.30078Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span>{props.updatedAt ? `Updated ${formatUpdatedAt(props.updatedAt)}` : "No rows yet"}</span>
|
||||
<span>{props.updatedAt ? `Updated ${formatUpdatedAt(props.updatedAt, timeZone())}` : "No rows yet"}</span>
|
||||
</p>
|
||||
<div data-slot="hero-canvas">
|
||||
<div data-slot="hero-pattern" aria-hidden="true" />
|
||||
<h1>Model Stats</h1>
|
||||
<p data-slot="hero-copy">
|
||||
See which models are winning real usage, how the mix shifts over time, and where momentum is moving each week.
|
||||
See which models are winning real usage, how the mix{" "}
|
||||
<br data-slot="hero-copy-break" />
|
||||
shifts over time, and where momentum is moving each week.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -154,7 +162,7 @@ function EmptyState(props: { title: string; description: string }) {
|
|||
)
|
||||
}
|
||||
|
||||
function formatUpdatedAt(value: string) {
|
||||
function formatUpdatedAt(value: string, timeZone: string) {
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) return "just now"
|
||||
return new Intl.DateTimeFormat("en", {
|
||||
|
|
@ -162,7 +170,7 @@ function formatUpdatedAt(value: string) {
|
|||
day: "numeric",
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
timeZone: "UTC",
|
||||
timeZone,
|
||||
timeZoneName: "short",
|
||||
}).format(date)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue