diff --git a/packages/console/app/src/routes/workspace/[id]/graph-section.module.css b/packages/console/app/src/routes/workspace/[id]/graph-section.module.css index d31dad59..24b85be7 100644 --- a/packages/console/app/src/routes/workspace/[id]/graph-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/graph-section.module.css @@ -1,141 +1,145 @@ -[data-component="empty-state"] { - padding: var(--space-20) var(--space-6); - text-align: center; - border: 1px dashed var(--color-border); - border-radius: var(--border-radius-sm); - height: 400px; - display: flex; - align-items: center; - justify-content: center; -} - -[data-component="empty-state"] p { - font-size: var(--font-size-sm); - color: var(--color-text-muted); -} - -[data-slot="filter-container"] { - margin-bottom: 0; - display: flex; - align-items: center; - gap: var(--space-3); -} - -[data-slot="month-picker"] { - display: flex; - align-items: center; - background-color: var(--color-bg); - border: 1px solid var(--color-border); - border-radius: var(--border-radius-sm); - padding: 0; -} - -[data-slot="month-button"] { - display: flex; - align-items: center; - justify-content: center; - background: none; - border: none !important; - color: var(--color-text); - cursor: pointer; - padding: var(--space-2) var(--space-3); - border-radius: var(--border-radius-xs); - transition: background-color 0.2s; - line-height: 1; -} - -[data-slot="month-button"]:hover { - background-color: var(--color-bg-hover); -} - -[data-slot="month-button"] svg { - display: block; - width: 16px; - height: 16px; - stroke-width: 2; -} - -[data-slot="month-label"] { - font-size: var(--font-size-sm); - font-weight: 500; - color: var(--color-text); - line-height: 1.5; - min-width: 140px; - text-align: center; - white-space: nowrap; -} - -[data-slot="filter-container"] [data-component="dropdown"] [data-slot="trigger"] { - border: 1px solid var(--color-border); - background-color: var(--color-bg); - padding: var(--space-2) var(--space-3); - border-radius: var(--border-radius-sm); - color: var(--color-text); - font-size: var(--font-size-sm); - line-height: 1.5; - - &:hover { - border-color: var(--color-accent); - } - - &:focus { - outline: none; - border-color: var(--color-accent); - box-shadow: 0 0 0 3px var(--color-accent-alpha); - } -} - -[data-slot="filter-container"] [data-component="dropdown"] [data-slot="chevron"] { - opacity: 0.6; -} - -[data-slot="filter-container"] [data-component="dropdown"] [data-slot="dropdown"] { - min-width: 200px; - max-height: 300px; - overflow-y: auto; - padding: var(--space-1); -} - -[data-slot="model-item"] { - display: flex; - align-items: center; - gap: var(--space-2); - padding: var(--space-2) var(--space-3); - cursor: pointer; - transition: background-color 0.2s; - font-size: var(--font-size-sm); - color: var(--color-text); - border: none !important; - background: none; - width: 100%; - text-align: left; - white-space: nowrap; -} - -[data-slot="model-item"]:hover { - background: var(--color-bg-hover); -} - -[data-slot="model-item"] span { - flex: 1; - user-select: none; -} - -[data-slot="chart-container"] { - padding: var(--space-6); - background: var(--color-bg-secondary); - border: 1px solid var(--color-border); - border-radius: var(--border-radius-sm); - height: 400px; -} - -@media (max-width: 40rem) { - [data-slot="chart-container"] { - height: 300px; - padding: var(--space-4); - } - +.root { [data-component="empty-state"] { - height: 300px; + padding: var(--space-20) var(--space-6); + text-align: center; + border: 1px dashed var(--color-border); + border-radius: var(--border-radius-sm); + height: 400px; + display: flex; + align-items: center; + justify-content: center; + + p { + font-size: var(--font-size-sm); + color: var(--color-text-muted); + } + } + + [data-slot="filter-container"] { + margin-bottom: 0; + display: flex; + align-items: center; + gap: var(--space-3); + + [data-component="dropdown"] { + [data-slot="trigger"] { + border: 1px solid var(--color-border); + background-color: var(--color-bg); + padding: var(--space-2) var(--space-3); + border-radius: var(--border-radius-sm); + color: var(--color-text); + font-size: var(--font-size-sm); + line-height: 1.5; + + &:hover { + border-color: var(--color-accent); + } + + &:focus { + outline: none; + border-color: var(--color-accent); + box-shadow: 0 0 0 3px var(--color-accent-alpha); + } + } + + [data-slot="chevron"] { + opacity: 0.6; + } + + [data-slot="dropdown"] { + min-width: 200px; + max-height: 300px; + overflow-y: auto; + padding: var(--space-1); + } + } + } + + [data-slot="month-picker"] { + display: flex; + align-items: center; + background-color: var(--color-bg); + border: 1px solid var(--color-border); + border-radius: var(--border-radius-sm); + padding: 0; + } + + [data-slot="month-button"] { + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none !important; + color: var(--color-text); + cursor: pointer; + padding: var(--space-2) var(--space-3); + border-radius: var(--border-radius-xs); + transition: background-color 0.2s; + line-height: 1; + + &:hover { + background-color: var(--color-bg-hover); + } + + svg { + display: block; + width: 16px; + height: 16px; + stroke-width: 2; + } + } + + [data-slot="month-label"] { + font-size: var(--font-size-sm); + font-weight: 500; + color: var(--color-text); + line-height: 1.5; + min-width: 140px; + text-align: center; + white-space: nowrap; + } + + [data-slot="model-item"] { + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-2) var(--space-3); + cursor: pointer; + transition: background-color 0.2s; + font-size: var(--font-size-sm); + color: var(--color-text); + border: none !important; + background: none; + width: 100%; + text-align: left; + white-space: nowrap; + + &:hover { + background: var(--color-bg-hover); + } + + span { + flex: 1; + user-select: none; + } + } + + [data-slot="chart-container"] { + padding: var(--space-6); + background: var(--color-bg-secondary); + border: 1px solid var(--color-border); + border-radius: var(--border-radius-sm); + height: 400px; + } + + @media (max-width: 40rem) { + [data-slot="chart-container"] { + height: 300px; + padding: var(--space-4); + } + + [data-component="empty-state"] { + height: 300px; + } } } diff --git a/packages/console/app/src/routes/workspace/[id]/graph-section.tsx b/packages/console/app/src/routes/workspace/[id]/graph-section.tsx index 0fa298ff..cbcd1a62 100644 --- a/packages/console/app/src/routes/workspace/[id]/graph-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/graph-section.tsx @@ -9,7 +9,7 @@ import { createStore } from "solid-js/store" import { withActor } from "~/context/auth.withActor" import { Dropdown } from "~/component/dropdown" import { IconChevronLeft, IconChevronRight } from "~/component/icon" -import "./graph-section.module.css" +import styles from "./graph-section.module.css" import { Chart, BarController, @@ -346,7 +346,7 @@ export function GraphSection() { onCleanup(() => chartInstance?.destroy()) return ( -
+

Cost

Usage costs broken down by model.

diff --git a/packages/console/app/src/routes/workspace/[id]/usage-section.module.css b/packages/console/app/src/routes/workspace/[id]/usage-section.module.css index 31092a7e..f11e00b2 100644 --- a/packages/console/app/src/routes/workspace/[id]/usage-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/usage-section.module.css @@ -1,117 +1,119 @@ -/* Empty state */ -[data-component="empty-state"] { - padding: var(--space-20) var(--space-6); - text-align: center; - border: 1px dashed var(--color-border); - border-radius: var(--border-radius-sm); - - p { - font-size: var(--font-size-sm); - color: var(--color-text-muted); - } -} - -/* Table container */ -[data-slot="usage-table"] { - overflow-x: auto; -} - -/* Table element */ -[data-slot="usage-table-element"] { - width: 100%; - border-collapse: collapse; - font-size: var(--font-size-sm); - - thead { - border-bottom: 1px solid var(--color-border); - } - - th { - padding: var(--space-3) var(--space-4); - text-align: left; - font-weight: normal; - color: var(--color-text-muted); - text-transform: uppercase; - } - - td { - padding: var(--space-3) var(--space-4); - border-bottom: 1px solid var(--color-border-muted); - color: var(--color-text-muted); - font-family: var(--font-mono); - - &[data-slot="usage-date"] { - color: var(--color-text); - } - - &[data-slot="usage-model"] { - font-family: var(--font-sans); - color: var(--color-text-secondary); - max-width: 200px; - word-break: break-word; - } - - &[data-slot="usage-cost"] { - color: var(--color-text); - font-weight: 500; - } - } - - tbody tr:last-child td { - border-bottom: none; - } -} - -/* Pagination */ -[data-slot="pagination"] { - display: flex; - justify-content: flex-end; - gap: var(--space-2); - padding: var(--space-4) 0; - border-top: 1px solid var(--color-border-muted); - margin-top: var(--space-2); - - button { - padding: var(--space-2) var(--space-4); - background: var(--color-bg-secondary); - border: 1px solid var(--color-border); +.root { + /* Empty state */ + [data-component="empty-state"] { + padding: var(--space-20) var(--space-6); + text-align: center; + border: 1px dashed var(--color-border); border-radius: var(--border-radius-sm); - color: var(--color-text); - font-size: var(--font-size-sm); - cursor: pointer; - transition: all 0.15s ease; - svg { - width: 16px; - height: 16px; - stroke-width: 2; - } - - &:hover:not(:disabled) { - background: var(--color-bg-tertiary); - border-color: var(--color-border-hover); - } - - &:disabled { - opacity: 0.5; - cursor: not-allowed; + p { + font-size: var(--font-size-sm); + color: var(--color-text-muted); } } -} -/* Mobile responsive */ -@media (max-width: 40rem) { + /* Table container */ + [data-slot="usage-table"] { + overflow-x: auto; + } + + /* Table element */ [data-slot="usage-table-element"] { - th, - td { - padding: var(--space-2) var(--space-3); - font-size: var(--font-size-xs); + width: 100%; + border-collapse: collapse; + font-size: var(--font-size-sm); + + thead { + border-bottom: 1px solid var(--color-border); } - /* Hide Model column on mobile */ - th:nth-child(2), - td:nth-child(2) { - display: none; + th { + padding: var(--space-3) var(--space-4); + text-align: left; + font-weight: normal; + color: var(--color-text-muted); + text-transform: uppercase; + } + + td { + padding: var(--space-3) var(--space-4); + border-bottom: 1px solid var(--color-border-muted); + color: var(--color-text-muted); + font-family: var(--font-mono); + + &[data-slot="usage-date"] { + color: var(--color-text); + } + + &[data-slot="usage-model"] { + font-family: var(--font-sans); + color: var(--color-text-secondary); + max-width: 200px; + word-break: break-word; + } + + &[data-slot="usage-cost"] { + color: var(--color-text); + font-weight: 500; + } + } + + tbody tr:last-child td { + border-bottom: none; + } + } + + /* Pagination */ + [data-slot="pagination"] { + display: flex; + justify-content: flex-end; + gap: var(--space-2); + padding: var(--space-4) 0; + border-top: 1px solid var(--color-border-muted); + margin-top: var(--space-2); + + button { + padding: var(--space-2) var(--space-4); + background: var(--color-bg-secondary); + border: 1px solid var(--color-border); + border-radius: var(--border-radius-sm); + color: var(--color-text); + font-size: var(--font-size-sm); + cursor: pointer; + transition: all 0.15s ease; + + svg { + width: 16px; + height: 16px; + stroke-width: 2; + } + + &:hover:not(:disabled) { + background: var(--color-bg-tertiary); + border-color: var(--color-border-hover); + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + } + } + + /* Mobile responsive */ + @media (max-width: 40rem) { + [data-slot="usage-table-element"] { + th, + td { + padding: var(--space-2) var(--space-3); + font-size: var(--font-size-xs); + } + + /* Hide Model column on mobile */ + th:nth-child(2), + td:nth-child(2) { + display: none; + } } } } diff --git a/packages/console/app/src/routes/workspace/[id]/usage-section.tsx b/packages/console/app/src/routes/workspace/[id]/usage-section.tsx index b97bc53d..d9aa7251 100644 --- a/packages/console/app/src/routes/workspace/[id]/usage-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/usage-section.tsx @@ -4,7 +4,7 @@ import { createMemo, For, Show, createEffect } from "solid-js" import { formatDateUTC, formatDateForTable } from "../common" import { withActor } from "~/context/auth.withActor" import { IconChevronLeft, IconChevronRight } from "~/component/icon" -import "./usage-section.module.css" +import styles from "./usage-section.module.css" import { createStore } from "solid-js/store" const PAGE_SIZE = 50 @@ -47,7 +47,7 @@ export function UsageSection() { } return ( -
+

Usage History

Recent API usage and costs.