mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-31 21:50:53 +00:00
feat(stats): polish rankings page
This commit is contained in:
parent
6a9087007c
commit
0d67d659fc
6 changed files with 369 additions and 76 deletions
1
bun.lock
1
bun.lock
|
|
@ -639,6 +639,7 @@
|
|||
"effect": "catalog:",
|
||||
"nitro": "3.0.1-alpha.1",
|
||||
"solid-js": "catalog:",
|
||||
"sst": "catalog:",
|
||||
"vite": "catalog:",
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
"d3-scale": "4.0.2",
|
||||
"effect": "catalog:",
|
||||
"nitro": "3.0.1-alpha.1",
|
||||
"sst": "catalog:",
|
||||
"solid-js": "catalog:",
|
||||
"vite": "catalog:"
|
||||
},
|
||||
|
|
|
|||
10
packages/stats/app/src/resource.d.ts
vendored
Normal file
10
packages/stats/app/src/resource.d.ts
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import "sst/resource"
|
||||
|
||||
declare module "sst/resource" {
|
||||
export interface Resource {
|
||||
EMAILOCTOPUS_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
}
|
||||
}
|
||||
}
|
||||
29
packages/stats/app/src/routes/api/newsletter.ts
Normal file
29
packages/stats/app/src/routes/api/newsletter.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { Resource } from "sst/resource"
|
||||
|
||||
const listId = "8b9bb82c-9d5f-11f0-975f-0df6fd1e4945"
|
||||
|
||||
export async function POST(event: { request: Request }) {
|
||||
const contentType = event.request.headers.get("content-type") ?? ""
|
||||
if (!contentType.includes("multipart/form-data") && !contentType.includes("application/x-www-form-urlencoded")) {
|
||||
return Response.json({ error: "Email address is required" }, { status: 400 })
|
||||
}
|
||||
|
||||
const form = await event.request.formData()
|
||||
const emailAddress = form.get("email")
|
||||
if (typeof emailAddress !== "string" || emailAddress.trim().length === 0) {
|
||||
return Response.json({ error: "Email address is required" }, { status: 400 })
|
||||
}
|
||||
|
||||
const response = await fetch(`https://api.emailoctopus.com/lists/${listId}/contacts`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
Authorization: `Bearer ${Resource.EMAILOCTOPUS_API_KEY.value}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email_address: emailAddress.trim(),
|
||||
}),
|
||||
})
|
||||
if (!response.ok) return Response.json({ error: "Failed to subscribe" }, { status: 502 })
|
||||
return Response.json({ success: true })
|
||||
}
|
||||
|
|
@ -67,6 +67,9 @@
|
|||
--stats-dot: #d4d4d4;
|
||||
--stats-hero-muted: #5c5c5c;
|
||||
--stats-hero-pattern: #eeeeee;
|
||||
--stats-logo-bg: #161616;
|
||||
--stats-logo-fill: #454545;
|
||||
--stats-logo-stroke: #e2e2e2;
|
||||
--stats-page-padding: 5rem;
|
||||
--stats-section-padding: 6rem;
|
||||
min-height: 100vh;
|
||||
|
|
@ -343,7 +346,7 @@
|
|||
gap: 56px;
|
||||
box-sizing: border-box;
|
||||
min-height: 0;
|
||||
padding: 112px 0 24px;
|
||||
padding: 112px clamp(32px, 4vw, 48px) 24px;
|
||||
color: var(--stats-text);
|
||||
font-family:
|
||||
"IBM Plex Mono",
|
||||
|
|
@ -364,9 +367,10 @@
|
|||
color: var(--stats-text);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="footer-mark"] [data-slot="brand-mark"] {
|
||||
width: 24px;
|
||||
height: 30px;
|
||||
[data-page="stats"] [data-slot="footer-mark"] [data-slot="opencode-mark"] {
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="footer-column"] {
|
||||
|
|
@ -415,10 +419,19 @@
|
|||
justify-content: center;
|
||||
width: fit-content;
|
||||
height: 28px;
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--stats-line);
|
||||
border-radius: 0;
|
||||
appearance: none;
|
||||
background: var(--stats-bg);
|
||||
color: var(--stats-text) !important;
|
||||
font: inherit;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-button"]:hover {
|
||||
|
|
@ -426,6 +439,176 @@
|
|||
background: var(--stats-layer);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-button"]:focus-visible,
|
||||
[data-page="stats"] [data-component="subscribe-modal"] button:focus-visible,
|
||||
[data-page="stats"] [data-component="subscribe-modal"] input:focus-visible {
|
||||
outline: 2px solid var(--stats-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="subscribe-modal"] {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 80;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
color: var(--stats-text);
|
||||
font-family:
|
||||
"IBM Plex Mono",
|
||||
var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-scrim"] {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: #00000066;
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-panel"] {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: min(374px, calc(100vw - 16px));
|
||||
overflow: hidden;
|
||||
background: var(--stats-layer);
|
||||
box-shadow:
|
||||
0 0 0 0.5px #00000024,
|
||||
0 16px 32px #0000001f,
|
||||
0 8px 16px #00000014;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-brand"] {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 122px;
|
||||
background: #242424;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-logo"] {
|
||||
display: block;
|
||||
width: 234px;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-close"] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-close"]:hover {
|
||||
background: #ffffff1a;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-body"] {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
padding: 24px 12px 12px;
|
||||
background: var(--stats-layer);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-intro"] {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-intro"] h2 {
|
||||
color: var(--stats-text);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="modal-intro"] p {
|
||||
color: var(--stats-muted);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-form"] {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-form"] input,
|
||||
[data-page="stats"] [data-slot="subscribe-form"] button {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
appearance: none;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-form"] input {
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--stats-line);
|
||||
background: var(--stats-bg);
|
||||
color: var(--stats-text);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-form"] input::placeholder {
|
||||
color: var(--stats-faint);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-form"] button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
background: #242424;
|
||||
color: #ffffff;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-form"] button:disabled {
|
||||
cursor: progress;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-feedback"]:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-feedback"] p {
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-feedback"] p[data-state="success"] {
|
||||
color: #198b43;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="subscribe-feedback"] p[data-state="error"] {
|
||||
color: #b82d35;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="footer-pattern"] {
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
|
|
@ -470,30 +653,6 @@
|
|||
background: #198b43;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="theme-toggle"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 2px;
|
||||
background: var(--stats-layer);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="theme-toggle"] button {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 18px;
|
||||
height: 16px;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
color: var(--stats-muted);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="theme-toggle"] button[data-active="true"] {
|
||||
color: var(--stats-text);
|
||||
background: var(--stats-bg);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="content"] a {
|
||||
color: var(--stats-text);
|
||||
text-decoration: none;
|
||||
|
|
@ -1373,6 +1532,10 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="section-bridge"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="section-title"] {
|
||||
max-width: 1200px;
|
||||
margin-bottom: 40px;
|
||||
|
|
@ -1779,7 +1942,7 @@
|
|||
background: transparent;
|
||||
color: var(--stats-text);
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
line-height: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
|
@ -1804,6 +1967,7 @@
|
|||
overflow: hidden;
|
||||
color: var(--stats-muted);
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
@ -1907,7 +2071,7 @@
|
|||
}
|
||||
|
||||
[data-page="stats"] [data-component="live-filter"] {
|
||||
display: flex;
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 0;
|
||||
|
|
@ -1960,6 +2124,9 @@
|
|||
--stats-dot: #303030;
|
||||
--stats-hero-muted: #808080;
|
||||
--stats-hero-pattern: #303030;
|
||||
--stats-logo-bg: #f1ecec;
|
||||
--stats-logo-fill: #b7b1b1;
|
||||
--stats-logo-stroke: #211e1e;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="chart-tooltip"] {
|
||||
|
|
@ -2040,6 +2207,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (min-width: 90rem) {
|
||||
[data-page="stats"] [data-component="footer"] {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 74rem) {
|
||||
[data-page="stats"] [data-section="top-models"],
|
||||
[data-page="stats"] [data-section="leaderboard"],
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import ibmPlexMonoRegularLatin1 from "@ibm/plex/IBM-Plex-Mono/fonts/split/woff2/
|
|||
import ibmPlexMonoMediumLatin1 from "@ibm/plex/IBM-Plex-Mono/fonts/split/woff2/IBMPlexMono-Medium-Latin1.woff2?url"
|
||||
import ibmPlexMonoSemiBoldLatin1 from "@ibm/plex/IBM-Plex-Mono/fonts/split/woff2/IBMPlexMono-SemiBold-Latin1.woff2?url"
|
||||
import ibmPlexMonoBoldLatin1 from "@ibm/plex/IBM-Plex-Mono/fonts/split/woff2/IBMPlexMono-Bold-Latin1.woff2?url"
|
||||
import opencodeWordmarkDark from "../asset/logo-ornate-dark.svg"
|
||||
import {
|
||||
getStatsHomeData,
|
||||
type LeaderboardEntry,
|
||||
|
|
@ -1318,7 +1319,18 @@ function StatsMark() {
|
|||
)
|
||||
}
|
||||
|
||||
function OpenCodeMark() {
|
||||
return (
|
||||
<svg data-slot="opencode-mark" width="40" height="40" viewBox="0 0 40 40" fill="none" aria-hidden="true">
|
||||
<path d="M40 40H0V0H40V40Z" fill="var(--stats-logo-bg)" />
|
||||
<path d="M26 29H14V17H26V29Z" fill="var(--stats-logo-fill)" />
|
||||
<path d="M26 11H14V29H26V11ZM32 35H8V5H32V35Z" fill="var(--stats-logo-stroke)" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function Footer() {
|
||||
const [subscribeOpen, setSubscribeOpen] = createSignal(false)
|
||||
const modelStats = [
|
||||
{ href: "#top-models", label: "Top Models" },
|
||||
{ href: "#leaderboard", label: "Leaderboard" },
|
||||
|
|
@ -1333,17 +1345,17 @@ function Footer() {
|
|||
const connect = [
|
||||
{ href: "mailto:hello@opencode.ai", label: "Contact us" },
|
||||
{ href: "https://opencode.ai/discord", label: "Community" },
|
||||
{ href: "https://x.com/opencode_ai", label: "X" },
|
||||
{ href: "https://github.com/sst/opencode", label: "GitHub" },
|
||||
{ href: "https://youtube.com/@opencode-ai", label: "YouTube" },
|
||||
{ href: "https://x.com/opencode", label: "X" },
|
||||
{ href: "https://github.com/anomalyco/opencode", label: "GitHub" },
|
||||
{ href: "https://www.youtube.com/@anomaly-co", label: "YouTube" },
|
||||
]
|
||||
|
||||
return (
|
||||
<footer data-component="footer">
|
||||
<SectionBridge label="SESSION COST" href="#session-cost" />
|
||||
<div data-slot="footer-grid">
|
||||
<a data-slot="footer-mark" href="/" aria-label="OpenCode home">
|
||||
<StatsMark />
|
||||
<a data-slot="footer-mark" href="https://opencode.ai" aria-label="OpenCode home">
|
||||
<OpenCodeMark />
|
||||
</a>
|
||||
<FooterColumn title="Model Stats" links={modelStats} />
|
||||
<FooterColumn title="Legal" links={legal} />
|
||||
|
|
@ -1351,9 +1363,9 @@ function Footer() {
|
|||
<div data-slot="footer-column">
|
||||
<h2>Newsletter</h2>
|
||||
<p>Be the first to know about new releases.</p>
|
||||
<a data-slot="subscribe-button" href="https://opencode.ai/">
|
||||
<button data-slot="subscribe-button" type="button" onClick={() => setSubscribeOpen(true)}>
|
||||
Subscribe
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="footer-pattern" aria-hidden="true" />
|
||||
|
|
@ -1362,19 +1374,114 @@ function Footer() {
|
|||
<span>© 2026 Anomaly Innovations Inc.</span>
|
||||
<span data-slot="status">All systems Operational</span>
|
||||
</div>
|
||||
<div data-slot="theme-toggle" aria-label="Theme preference">
|
||||
<button type="button" aria-label="Use dark theme">
|
||||
<MoonIcon />
|
||||
</button>
|
||||
<button type="button" aria-label="Use light theme">
|
||||
<SunIcon />
|
||||
</button>
|
||||
<button type="button" aria-label="Use system theme" data-active="true">
|
||||
<MonitorIcon />
|
||||
</div>
|
||||
<Show when={subscribeOpen()}>
|
||||
<SubscribeModal onClose={() => setSubscribeOpen(false)} />
|
||||
</Show>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
function SubscribeModal(props: { onClose: () => void }) {
|
||||
const [status, setStatus] = createSignal<"idle" | "pending" | "success" | "error">("idle")
|
||||
const [message, setMessage] = createSignal("")
|
||||
let input: HTMLInputElement | undefined
|
||||
|
||||
onMount(() => {
|
||||
if (typeof document === "undefined") return
|
||||
const activeElement = document.activeElement instanceof HTMLElement ? document.activeElement : undefined
|
||||
const htmlOverflow = document.documentElement.style.overflow
|
||||
const bodyOverflow = document.body.style.overflow
|
||||
document.documentElement.style.overflow = "hidden"
|
||||
document.body.style.overflow = "hidden"
|
||||
const focusTimeout = window.setTimeout(() => input?.focus(), 0)
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") props.onClose()
|
||||
}
|
||||
document.addEventListener("keydown", onKeyDown)
|
||||
onCleanup(() => {
|
||||
window.clearTimeout(focusTimeout)
|
||||
document.documentElement.style.overflow = htmlOverflow
|
||||
document.body.style.overflow = bodyOverflow
|
||||
document.removeEventListener("keydown", onKeyDown)
|
||||
activeElement?.focus()
|
||||
})
|
||||
})
|
||||
|
||||
return (
|
||||
<div data-component="subscribe-modal" role="dialog" aria-modal="true" aria-labelledby="subscribe-title">
|
||||
<div data-slot="modal-scrim" aria-hidden="true" onClick={props.onClose} />
|
||||
<div data-slot="modal-panel">
|
||||
<div data-slot="modal-brand">
|
||||
<img data-slot="modal-logo" src={opencodeWordmarkDark} alt="OpenCode" />
|
||||
<button data-slot="modal-close" type="button" aria-label="Close newsletter signup" onClick={props.onClose}>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<path d="M4.44 4.44L11.56 11.56M11.56 4.44L4.44 11.56" stroke="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div data-slot="modal-body">
|
||||
<div data-slot="modal-intro">
|
||||
<h2 id="subscribe-title">OpenCode Newsletter</h2>
|
||||
<p>
|
||||
Be the first to know
|
||||
<br />
|
||||
about new releases.
|
||||
</p>
|
||||
</div>
|
||||
<form
|
||||
data-slot="subscribe-form"
|
||||
method="post"
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault()
|
||||
setStatus("pending")
|
||||
setMessage("")
|
||||
fetch("/api/newsletter", {
|
||||
method: "POST",
|
||||
body: new FormData(event.currentTarget),
|
||||
}).then(
|
||||
async (response) => {
|
||||
if (response.ok) {
|
||||
event.currentTarget.reset()
|
||||
setStatus("success")
|
||||
return
|
||||
}
|
||||
setMessage(await newsletterErrorMessage(response))
|
||||
setStatus("error")
|
||||
},
|
||||
() => {
|
||||
setMessage("Failed to subscribe")
|
||||
setStatus("error")
|
||||
},
|
||||
)
|
||||
}}
|
||||
>
|
||||
<input ref={input} type="email" name="email" placeholder="Email address" required />
|
||||
<button type="submit" disabled={status() === "pending"}>
|
||||
{status() === "pending" ? "Subscribing..." : "Subscribe"}
|
||||
</button>
|
||||
</form>
|
||||
<div data-slot="subscribe-feedback" aria-live="polite">
|
||||
<Show when={status() === "success"}>
|
||||
<p data-state="success">You're subscribed.</p>
|
||||
</Show>
|
||||
<Show when={status() === "error"}>
|
||||
<p data-state="error">{message()}</p>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function newsletterErrorMessage(response: Response) {
|
||||
return response.json().then(
|
||||
(body: unknown) =>
|
||||
body && typeof body === "object" && "error" in body && typeof body.error === "string"
|
||||
? body.error
|
||||
: "Failed to subscribe",
|
||||
() => "Failed to subscribe",
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1394,32 +1501,3 @@ function FooterColumn(props: { title: string; links: { href: string; label: stri
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function MoonIcon() {
|
||||
return (
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M8.8 7.9A4.3 4.3 0 0 1 4.1 3.2A3.9 3.9 0 1 0 8.8 7.9Z" stroke="currentColor" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function SunIcon() {
|
||||
return (
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path
|
||||
d="M6 3.5V2M6 10V8.5M8.5 6H10M2 6H3.5M7.75 4.25L8.8 3.2M3.2 8.8L4.25 7.75M4.25 4.25L3.2 3.2M8.8 8.8L7.75 7.75"
|
||||
stroke="currentColor"
|
||||
/>
|
||||
<circle cx="6" cy="6" r="1.7" stroke="currentColor" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function MonitorIcon() {
|
||||
return (
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M2 3H10V8H2V3Z" stroke="currentColor" />
|
||||
<path d="M4.5 10H7.5M6 8V10" stroke="currentColor" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue