SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%
1.6 KB · 39 lines tsx
Raw Blame History
1'use client';2import { type ReactNode, useState } from 'react';3import { cn } from '@/lib/cn';45/**6 * Linear / log axis switch for a server-rendered chart: both variants are rendered by the server (SEO, no client7 * fetch); this only toggles which one is visible and mirrors the choice into `?scale=` with `replaceState`8 * (no navigation, no re-render of the page).9 */10export function ScaleToggle({ linear, log, initial = 'linear', className }: { linear: ReactNode; log: ReactNode; initial?: 'linear' | 'log'; className?: string }) {11  const [scale, setScale] = useState<'linear' | 'log'>(initial);12  const set = (s: 'linear' | 'log') => {13    setScale(s);14    try {15      const url = new URL(window.location.href);16      if (s === 'log') url.searchParams.set('scale', 'log');17      else url.searchParams.delete('scale');18      window.history.replaceState(null, '', url.toString());19    } catch {20      /* ignore */21    }22  };23  const btn = (s: 'linear' | 'log', label: string) => (24    <button type="button" onClick={() => set(s)} aria-pressed={scale === s} className={cn('h-9 border px-3 text-xs font-medium transition-colors', scale === s ? 'border-ink bg-ink text-canvas' : 'border-rule text-ink-2 hover:border-rule-strong hover:text-ink')}>25      {label}26    </button>27  );28  return (29    <div className={className}>30      <div className="mb-2 flex items-center gap-1" role="group" aria-label="Y axis scale">31        {btn('linear', 'Linear')}32        {btn('log', 'Log scale')}33      </div>34      <div hidden={scale !== 'linear'}>{linear}</div>35      <div hidden={scale !== 'log'}>{log}</div>36    </div>37  );38}39