diff --git a/packages/stats/app/src/routes/index.css b/packages/stats/app/src/routes/index.css index 72bbfadfe1..a12cc9296e 100644 --- a/packages/stats/app/src/routes/index.css +++ b/packages/stats/app/src/routes/index.css @@ -1065,10 +1065,66 @@ flex-direction: column; } +[data-page="stats"] [data-slot="top-models-axis"] > div[data-label-hidden="true"]:not([data-active="true"]) + [data-slot="axis-label"], +[data-page="stats"] [data-slot="market-labels"] button[data-label-hidden="true"]:not([data-active="true"]) + [data-slot="market-axis-label"] { + visibility: hidden; +} + [data-page="stats"] [data-slot="axis-date-mobile"] { display: none; } +[data-page="stats"] [data-component="top-models-chart"][data-dense-labels="true"] { + grid-template-rows: 40px minmax(0, 1fr); +} + +[data-page="stats"] [data-component="market-share"][data-dense-labels="true"] { + grid-template-rows: 40px minmax(0, 1fr); +} + +[data-page="stats"] [data-component="top-models-chart"][data-dense-labels="true"] + [data-slot="top-models-axis"] + > div { + position: relative; + display: flex; + align-items: center; + justify-content: center; + height: 40px; + font-weight: 600; +} + +[data-page="stats"] [data-component="market-share"][data-dense-labels="true"] [data-slot="market-labels"] button { + position: relative; + align-items: center; + justify-content: center; + height: 40px; + line-height: 1.2; +} + +[data-page="stats"] [data-component="top-models-chart"][data-dense-labels="true"] [data-slot="axis-label"], +[data-page="stats"] [data-component="market-share"][data-dense-labels="true"] [data-slot="market-axis-label"] { + position: absolute; + left: 50%; + width: max-content; + max-width: 72px; + transform: rotate(-90deg) translateX(-50%); + transform-origin: left center; +} + +[data-page="stats"] [data-component="top-models-chart"][data-dense-labels="true"] [data-slot="axis-total"], +[data-page="stats"] [data-component="top-models-chart"][data-dense-labels="true"] [data-slot="axis-date-full"], +[data-page="stats"] [data-component="market-share"][data-dense-labels="true"] [data-slot="market-total"], +[data-page="stats"] [data-component="market-share"][data-dense-labels="true"] [data-slot="market-date-full"] { + display: none; +} + +[data-page="stats"] [data-component="top-models-chart"][data-dense-labels="true"] [data-slot="axis-date-mobile"], +[data-page="stats"] [data-component="market-share"][data-dense-labels="true"] [data-slot="market-date-mobile"] { + display: block; +} + [data-page="stats"] [data-slot="top-models-bars"] { width: calc(100% + var(--top-models-bar-gap)); margin-inline: calc(var(--top-models-bar-gap) / -2); diff --git a/packages/stats/app/src/routes/index.tsx b/packages/stats/app/src/routes/index.tsx index f60dd51724..ee247fc8cf 100644 --- a/packages/stats/app/src/routes/index.tsx +++ b/packages/stats/app/src/routes/index.tsx @@ -370,7 +370,7 @@ function formatUpdatedAtLabel(value: { date: string; time: string }) { function TopModelsSection(props: { data: StatsHomeData["usage"] }) { const [product, setProduct] = createSignal("All Users") - const [range, setRange] = createSignal("1W") + const [range, setRange] = createSignal("2M") const [sheet, setSheet] = createSignal<"product" | "range">() const data = createMemo(() => props.data[product()][range()]) @@ -585,6 +585,7 @@ function TopModelsChart(props: { data: UsagePoint[]; range: UsageRange }) {
@@ -593,6 +594,7 @@ function TopModelsChart(props: { data: UsagePoint[]; range: UsageRange }) { {(day, index) => (
@@ -755,6 +757,16 @@ function isTopModelsMobileAxisHidden(index: number, count: number) { return count > 7 && index % 2 === 1 } +function isColumnLabelHidden(index: number, count: number) { + if (count <= 20) return false + const interval = Math.ceil(count / 8) + return index !== count - 1 && index % interval !== 0 +} + +function isDenseColumnRange(range: UsageRange) { + return range === "1M" || range === "2M" +} + function formatTopModelsMobileDate(label: string, range: UsageRange) { if (range === "1M" || range === "2M") return label.split(" - ")[0] ?? label return label @@ -771,7 +783,7 @@ function formatTokens(value: number) { function LeaderboardSection(props: { data: StatsHomeData["leaderboard"] }) { const [product, setProduct] = createSignal("All Users") - const [range, setRange] = createSignal("1W") + const [range, setRange] = createSignal("2M") const data = createMemo(() => props.data[product()][range()]) return ( @@ -870,7 +882,7 @@ function formatChange(value: number) { } function MarketShareSection(props: { data: StatsHomeData["market"] }) { - const [range, setRange] = createSignal("1W") + const [range, setRange] = createSignal("2M") const [activeIndex, setActiveIndex] = createSignal(2) const [activeAuthor, setActiveAuthor] = createSignal() const [inspecting, setInspecting] = createSignal(false) @@ -898,6 +910,7 @@ function MarketShareSection(props: { data: StatsHomeData["market"] }) { <> props.onActiveIndexChange(index())} onPointerEnter={() => props.onActiveIndexChange(index())} diff --git a/packages/stats/core/src/domain/home.ts b/packages/stats/core/src/domain/home.ts index 3ded66ea1f..db305a8ce8 100644 --- a/packages/stats/core/src/domain/home.ts +++ b/packages/stats/core/src/domain/home.ts @@ -330,13 +330,9 @@ function createBuckets(window: DateWindow, range: UsageRange): Bucket[] { const count = range === "1D" ? 1 - : range === "2W" - ? 14 - : range === "1M" - ? 4 - : range === "2M" - ? 8 - : Math.max(1, Math.min(7, Math.ceil(span / DAY_MS))) + : range === "1W" || range === "2W" || range === "1M" || range === "2M" || range === "3M" + ? Math.ceil(span / DAY_MS) + : Math.max(1, Math.min(7, Math.ceil(span / DAY_MS))) const size = span / count return Array.from({ length: count }, (_, index) => { const start = window.start + index * size @@ -443,14 +439,13 @@ function periodKeyTime(value: string) { return Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])) } -function formatBucketLabel(start: number, end: number, range: UsageRange) { +function formatBucketLabel(start: number, _end: number, range: UsageRange) { const date = new Date(start) if (range === "YTD") return months[date.getUTCMonth()] if (range === "ALL") return date.getUTCFullYear() === new Date().getUTCFullYear() ? months[date.getUTCMonth()] : String(date.getUTCFullYear()) - if (range === "1M" || range === "2M") return `${formatDay(start)} - ${formatDay(end - DAY_MS)}` return formatDay(start) }