Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
16 changes: 8 additions & 8 deletions src/brand/Helio.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useId } from 'react'
import { INK, SOLAR_RAMP, solarAlpha } from './palette'

/**
* Helio — the platform's one spectacle, here in its static, accessible fallback
Expand Down Expand Up @@ -36,20 +37,19 @@ export function Helio({ size = 360, motes = 14, breathe = true }: HelioProps) {
<svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
<defs>
<radialGradient id={coreId} cx="42%" cy="38%" r="68%">
<stop offset="0%" stopColor="#FFF4D6" />
<stop offset="34%" stopColor="#FFD451" />
<stop offset="72%" stopColor="#FFB400" />
<stop offset="100%" stopColor="#F59A00" />
{SOLAR_RAMP.map((stop) => (
<stop key={stop.offset} offset={stop.offset} stopColor={stop.color} />
))}
</radialGradient>
<radialGradient id={glowId} cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="rgba(255,180,0,0.42)" />
<stop offset="55%" stopColor="rgba(255,180,0,0.12)" />
<stop offset="100%" stopColor="rgba(255,180,0,0)" />
<stop offset="0%" stopColor={solarAlpha(0.42)} />
<stop offset="55%" stopColor={solarAlpha(0.12)} />
<stop offset="100%" stopColor={solarAlpha(0)} />
</radialGradient>
</defs>
<circle cx={cx} cy={cx} r={size * 0.48} fill={`url(#${glowId})`} />
{dots.map((d, i) => (
<circle key={i} cx={d.x} cy={d.y} r={d.s} fill="#0B2B23" opacity="0.55" />
<circle key={i} cx={d.x} cy={d.y} r={d.s} fill={INK} opacity="0.55" />
))}
<g
className="hb-orb"
Expand Down
10 changes: 3 additions & 7 deletions src/brand/HelioWebGL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import type { ComponentRef } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
import { MeshDistortMaterial } from '@react-three/drei'
import * as THREE from 'three'
/* --- Brand palette (shared with the static Helio and the CSS tokens) ------ */
import { SOLAR, SOLAR_CORE as CORE, SOLAR_HALO as HALO, INK, SOLAR_HIGHLIGHT } from './palette'

export interface HelioWebGLProps {
/** Rendered size in px (square). */
Expand All @@ -36,12 +38,6 @@ export interface HelioWebGLProps {
onReady?: () => void
}

/* --- Brand palette (matches the static Helio exactly) -------------------- */
const SOLAR = '#FFB400' // the sun — emissive accent
const CORE = '#FFD451' // warm core surface tint
const HALO = '#FFC633' // glow halo (sits between core and solar)
const INK = '#0B2B23' // deep pine — corona motes

const clamp01 = (n: number) => (n < 0 ? 0 : n > 1 ? 1 : n)

/* ------------------------------------------------------------------------- *
Expand Down Expand Up @@ -274,7 +270,7 @@ function Scene({
highlight (echoing the static SVG's specular), plus a core glow light. */}
<ambientLight intensity={0.28} />
<pointLight position={[0, 0, 0]} intensity={0.9} color={SOLAR} distance={8} />
<directionalLight position={[-2.2, 2.4, 3]} intensity={1.05} color={'#FFF4D6'} />
<directionalLight position={[-2.2, 2.4, 3]} intensity={1.05} color={SOLAR_HIGHLIGHT} />
<Halo animate={animate} intensity={intensity} />
<Sun animate={animate} intensity={intensity} />
<Corona specs={specs} animate={animate} />
Expand Down
9 changes: 8 additions & 1 deletion src/brand/Mark.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
* year-long path), drawn in currentColor with the one permitted second colour:
* a solar dot. Upper loop subtly smaller, as in the real analemma.
*/
/**
* The Heliobond analemma — a single continuous tilted figure-eight (the sun's
* year-long path), drawn in currentColor with the one permitted second colour:
* a solar dot. Upper loop subtly smaller, as in the real analemma.
*/
Comment on lines +6 to +10
import { SOLAR } from './palette'

export interface MarkProps {
size?: number
}
Expand All @@ -24,7 +31,7 @@ export function Mark({ size = 28 }: MarkProps) {
strokeLinejoin="round"
strokeLinecap="round"
/>
<circle cx="64" cy="20" r="7" fill="#FFB400" />
<circle cx="64" cy="20" r="7" fill={SOLAR} />
</g>
</svg>
</span>
Expand Down
64 changes: 64 additions & 0 deletions src/brand/palette.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Brand palette — the single source of truth for the literal colour values that
* canvas-style renderers need.
*
* Most of the interface reads colour through the CSS custom properties in
* `src/styles/tokens/colors.css`, and that remains the preferred route. But two
* renderers cannot: the SVG <Helio> builds gradient stops, and <HelioWebGL>
* hands colours to three.js, which needs a parsed value rather than a
* `var(--solar)` string. Both used to carry their own hard-coded hexes, which
* meant the same brand colour existed in three places and could drift.
*
* These constants mirror the colour tokens exactly:
* · `solar` === `--solar`
* · `ink` === `--ink` (light theme)
* The remaining entries are the solar ramp the orb is built from. They are
* deliberately theme-independent: the Helio is a fixed brand object and renders
* the same sun after sunset as it does at noon.
*/

/** `--solar` — the sun, the brand accent. */
export const SOLAR = '#FFB400'

/** `--ink` (light theme) — deep pine, used for the corona motes. */
export const INK = '#0B2B23'

/** Warm highlight at the centre of the orb, and the key light in the WebGL scene. */
export const SOLAR_HIGHLIGHT = '#FFF4D6'

/** Warm core surface tint — the second stop of the orb gradient. */
export const SOLAR_CORE = '#FFD451'

/** Glow halo — sits between the core tint and solar proper. */
export const SOLAR_HALO = '#FFC633'

/** Deep edge of the orb, where the sun falls away into its own limb. */
export const SOLAR_DEEP = '#F59A00'

/**
* The solar ramp, centre outwards. Consumed by the SVG orb's radial gradient so
* the stop list is derived rather than restated.
*/
export const SOLAR_RAMP = [
{ offset: '0%', color: SOLAR_HIGHLIGHT },
{ offset: '34%', color: SOLAR_CORE },
{ offset: '72%', color: SOLAR },
{ offset: '100%', color: SOLAR_DEEP },
] as const

/** `--solar` as RGB channels, for building the `rgba()` glow stops. */
export const SOLAR_RGB = '255, 180, 0'

/** Build an `rgba()` string from `--solar` at a given alpha. */
export function solarAlpha(alpha: number): string {
return `rgba(${SOLAR_RGB}, ${alpha})`
}

export const BRAND = {
solar: SOLAR,
ink: INK,
solarHighlight: SOLAR_HIGHLIGHT,
solarCore: SOLAR_CORE,
solarHalo: SOLAR_HALO,
solarDeep: SOLAR_DEEP,
} as const
21 changes: 20 additions & 1 deletion src/screens/creator/CreatorDashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { type CSSProperties } from 'react'
import { useId, type CSSProperties } from 'react'
import { useTranslations } from 'next-intl'
import { StatBlock, ScoreGauge, Badge, Card, Sparkline } from '@/components'
import {
Expand All @@ -21,6 +21,7 @@ export interface CreatorDashboardProps {

export function CreatorDashboard({ data = CREATOR_DASHBOARD }: CreatorDashboardProps) {
const t = useTranslations('Creator')
const fundingCaptionId = useId()
const fundedPct =
data.fundingGoal > 0 ? Math.round((data.fundingReceived / data.fundingGoal) * 100) : 0

Expand Down Expand Up @@ -67,6 +68,15 @@ export function CreatorDashboard({ data = CREATOR_DASHBOARD }: CreatorDashboardP
/>
<div style={{ marginTop: 16 }}>
<div
role="progressbar"
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={Math.min(100, fundedPct)}
aria-valuetext={t('dashGoalDeployed', {
pct: fundedPct,
goal: data.fundingGoal.toLocaleString('en-US'),
})}
Comment on lines +74 to +78
aria-labelledby={fundingCaptionId}
style={{
height: 8,
borderRadius: 'var(--radius-pill)',
Expand All @@ -80,10 +90,19 @@ export function CreatorDashboard({ data = CREATOR_DASHBOARD }: CreatorDashboardP
width: `${Math.min(100, fundedPct)}%`,
height: '100%',
background: 'var(--solar)',
/* The fill's leading edge is drawn in ink so the boundary is
legible without perceiving the solar hue at all — the bar
still reads in greyscale, under a colour-vision deficiency,
or with forced colours on. Solar therefore decorates the
value; it never carries it alone. */
borderRight:
fundedPct > 0 && fundedPct < 100 ? '2px solid var(--ink)' : undefined,
boxSizing: 'border-box',
}}
/>
</div>
<div
id={fundingCaptionId}
style={{
fontFamily: 'var(--font-body)',
fontSize: 'var(--type-caption)',
Expand Down
Loading