Parcourir la source

feat(stats): improve cache ratio chart

Adam il y a 3 mois
Parent
commit
69345a29b0
2 fichiers modifiés avec 164 ajouts et 18 suppressions
  1. 123 0
      packages/stats/app/src/routes/index.css
  2. 41 18
      packages/stats/app/src/routes/index.tsx

+ 123 - 0
packages/stats/app/src/routes/index.css

@@ -2264,6 +2264,116 @@
   color: var(--stats-muted);
 }
 
+[data-page="stats"] [data-slot="cache-ratio-heading"] {
+  display: grid;
+  grid-template-columns: 56px minmax(96px, 180px) minmax(160px, 1fr);
+  align-items: center;
+  gap: 12px;
+  height: 18px;
+  padding: 0 12px;
+  color: var(--stats-faint);
+  font-size: 9px;
+  font-weight: 600;
+  line-height: 1;
+  text-transform: uppercase;
+}
+
+[data-page="stats"] [data-slot="cache-ratio-heading"] b {
+  justify-self: end;
+  font-weight: 600;
+}
+
+[data-page="stats"] [data-slot="cache-ratio-rows"] {
+  display: grid;
+  gap: 8px;
+}
+
+[data-page="stats"] button[data-component="cache-ratio-row"] {
+  display: grid;
+  grid-template-columns: 56px minmax(96px, 180px) minmax(160px, 1fr);
+  align-items: center;
+  gap: 12px;
+  width: 100%;
+  height: 28px;
+  padding: 0 12px;
+  border: 0;
+  border-radius: 0;
+  background: transparent;
+  color: var(--stats-text);
+  font-size: 10px;
+  line-height: 14px;
+  text-align: left;
+}
+
+[data-page="stats"] button[data-component="cache-ratio-row"][data-active="true"] {
+  background: #0000000a;
+}
+
+[data-page="stats"] [data-component="cache-ratio-row"] strong {
+  color: var(--stats-text);
+  font-weight: 500;
+  white-space: nowrap;
+}
+
+[data-page="stats"] [data-component="cache-ratio-row"][data-active="true"] strong {
+  color: var(--stats-accent-text);
+}
+
+[data-page="stats"] [data-component="cache-ratio-row"] > span {
+  overflow: hidden;
+  color: var(--stats-muted);
+  font-weight: 400;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+[data-page="stats"] [data-component="cache-ratio-marker"] {
+  position: relative;
+  display: block;
+  min-width: 0;
+  height: 7px;
+  overflow: visible;
+  background:
+    linear-gradient(
+      90deg,
+      transparent calc(20% - 0.5px),
+      var(--stats-line) calc(20% - 0.5px) calc(20% + 0.5px),
+      transparent calc(20% + 0.5px) calc(40% - 0.5px),
+      var(--stats-line) calc(40% - 0.5px) calc(40% + 0.5px),
+      transparent calc(40% + 0.5px) calc(60% - 0.5px),
+      var(--stats-line) calc(60% - 0.5px) calc(60% + 0.5px),
+      transparent calc(60% + 0.5px) calc(80% - 0.5px),
+      var(--stats-line) calc(80% - 0.5px) calc(80% + 0.5px),
+      transparent calc(80% + 0.5px)
+    ),
+    linear-gradient(90deg, var(--stats-line) 0 1px, transparent 1px calc(100% - 1px), var(--stats-line) calc(100% - 1px)),
+    var(--stats-layer-2);
+  font-style: normal;
+}
+
+[data-page="stats"] [data-component="cache-ratio-marker"] em {
+  position: absolute;
+  top: 50%;
+  left: var(--cache-ratio-fill);
+  display: block;
+  width: 7px;
+  height: 13px;
+  transform: translate(-50%, -50%);
+  background: var(--stats-text);
+}
+
+[data-page="stats"] [data-component="cache-ratio-row"][data-active="true"] [data-component="cache-ratio-marker"] {
+  background: var(--stats-line-strong);
+}
+
+[data-page="stats"] [data-component="cache-ratio-row"][data-active="true"] [data-component="cache-ratio-marker"] em {
+  background: var(--stats-accent);
+}
+
+[data-page="stats"] [data-component="token-tooltip"][data-variant="cache-ratio"] {
+  left: 30%;
+}
+
 [data-page="stats"] [data-slot="token-footer"] {
   display: flex;
   align-items: center;
@@ -2407,6 +2517,13 @@
   opacity: 0.78;
 }
 
+[data-page="stats"][data-theme="dark"] button[data-component="cache-ratio-row"][data-active="true"],
+:root[data-stats-theme="dark"]
+  [data-page="stats"]:not([data-theme="light"])
+  button[data-component="cache-ratio-row"][data-active="true"] {
+  background: #ffffff0d;
+}
+
 [data-page="stats"][data-theme="dark"] [data-slot="header-button"][data-variant="neutral"],
 [data-page="stats"][data-theme="dark"] [data-slot="menu-button"],
 :root[data-stats-theme="dark"]
@@ -2756,6 +2873,12 @@
     font-size: 16px;
   }
 
+  [data-page="stats"] [data-slot="cache-ratio-heading"],
+  [data-page="stats"] button[data-component="cache-ratio-row"] {
+    grid-template-columns: 44px minmax(72px, 1fr) minmax(86px, 1.2fr);
+    gap: 8px;
+  }
+
   [data-page="stats"] [data-slot="top-models-mobile-controls"] {
     display: flex;
     gap: 8px;

+ 41 - 18
packages/stats/app/src/routes/index.tsx

@@ -1391,29 +1391,39 @@ function CacheRatioChart(props: {
   activeIndex: number
   onActiveIndexChange: (index: number) => void
 }) {
-  const max = createMemo(() => Math.max(0, ...props.data.map((item) => item.ratio)) || 100)
   const active = createMemo(() => props.data[props.activeIndex] ?? props.data[0])
 
   return (
-    <div data-component="cache-ratio">
-      <For each={props.data}>
-        {(item, index) => (
-          <button
-            type="button"
-            data-component="token-row"
-            data-active={props.activeIndex === index() ? "true" : undefined}
-            onClick={() => props.onActiveIndexChange(index())}
-            onPointerEnter={() => props.onActiveIndexChange(index())}
-          >
-            <strong>{formatRatio(item.ratio)}</strong>
-            <span>{item.model}</span>
-            <MetricBar value={item.ratio} max={max()} active={props.activeIndex === index()} />
-          </button>
-        )}
-      </For>
+    <div data-component="cache-ratio" data-variant="marker">
+      <div data-slot="cache-ratio-heading" aria-hidden="true">
+        <strong>Ratio</strong>
+        <span>Model</span>
+        <b>0-100%</b>
+      </div>
+      <div data-slot="cache-ratio-rows">
+        <For each={props.data}>
+          {(item, index) => (
+            <button
+              type="button"
+              data-component="cache-ratio-row"
+              data-active={props.activeIndex === index() ? "true" : undefined}
+              onClick={() => props.onActiveIndexChange(index())}
+              onPointerEnter={() => props.onActiveIndexChange(index())}
+            >
+              <strong>{formatRatio(item.ratio)}</strong>
+              <span>{item.model}</span>
+              <CacheRatioMarker ratio={item.ratio} active={props.activeIndex === index()} />
+            </button>
+          )}
+        </For>
+      </div>
       <Show when={active()}>
         {(item) => (
-          <div data-component="token-tooltip" style={{ top: `${props.activeIndex * 36 + 2}px` }}>
+          <div
+            data-component="token-tooltip"
+            data-variant="cache-ratio"
+            style={{ top: `${props.activeIndex * 36 + 28}px` }}
+          >
             <p>
               <span>Cache Ratio</span>
               <strong>{formatRatio(item().ratio)}</strong>
@@ -1433,6 +1443,19 @@ function CacheRatioChart(props: {
   )
 }
 
+function CacheRatioMarker(props: { ratio: number; active: boolean }) {
+  const fill = createMemo(() => Math.min(100, Math.max(0, props.ratio)))
+  return (
+    <i
+      data-component="cache-ratio-marker"
+      data-active={props.active ? "true" : undefined}
+      style={{ "--cache-ratio-fill": `${fill()}%` } as JSX.CSSProperties}
+    >
+      <em />
+    </i>
+  )
+}
+
 function formatRatio(value: number) {
   return `${value.toFixed(value > 0 && value < 10 ? 1 : 0)}%`
 }