Skip to content
Merged
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
Next Next commit
feat(mock-plugin): enhance mock plugin output and update progress labels
- Updated the mock plugin's JSON configuration to include new progress labels for various pacing statuses.
- Modified the App component to generate mock output with detailed progress metrics for testing purposes.
- Improved CSS variables for color consistency across themes, including new definitions for green, yellow, and red colors.
- Adjusted side navigation styles to ensure proper contrast in light and dark modes.
- Enhanced progress component styling for better visual representation in dark mode.
  • Loading branch information
robinebers committed Feb 7, 2026
commit aaedd82c4d4eeca2b07581c0011e4486e7c6cbbc
22 changes: 16 additions & 6 deletions plugins/mock/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,21 @@
"icon": "icon.svg",
"brandColor": "#EF4444",
"lines": [
{ "type": "text", "label": "Config", "scope": "overview" },
{ "type": "badge", "label": "Case", "scope": "overview" },
{ "type": "progress", "label": "Percent", "scope": "overview", "primaryOrder": 1 },
{ "type": "progress", "label": "Dollars", "scope": "detail" },
{ "type": "text", "label": "Now", "scope": "detail" },
{ "type": "badge", "label": "Warning", "scope": "detail" }
{ "type": "progress", "label": "Ahead pace", "scope": "overview", "primaryOrder": 1 },
{ "type": "progress", "label": "On Track pace", "scope": "overview", "primaryOrder": 2 },
{ "type": "progress", "label": "Behind pace", "scope": "overview", "primaryOrder": 3 },
{ "type": "progress", "label": "Empty bar", "scope": "overview", "primaryOrder": 4 },
{ "type": "progress", "label": "Exactly full", "scope": "overview", "primaryOrder": 5 },
{ "type": "progress", "label": "Over limit!", "scope": "overview", "primaryOrder": 6 },
{ "type": "progress", "label": "Huge numbers", "scope": "overview", "primaryOrder": 7 },
{ "type": "progress", "label": "Tiny sliver", "scope": "overview", "primaryOrder": 8 },
{ "type": "progress", "label": "Almost full", "scope": "overview", "primaryOrder": 9 },
{ "type": "progress", "label": "Expired reset", "scope": "overview", "primaryOrder": 10 },
{ "type": "text", "label": "Status", "scope": "overview" },
{ "type": "text", "label": "Very long value", "scope": "overview" },
{ "type": "text", "label": "", "scope": "overview" },
{ "type": "badge", "label": "Tier", "scope": "overview" },
{ "type": "badge", "label": "Alert", "scope": "overview" },
{ "type": "badge", "label": "Region", "scope": "overview" }
]
}
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "openusage"
version = "0.4.2"
description = "OpenUsage is an open source AI subscription limit tracker"
authors = ["Robin Ebers"]
edition = "2026"
edition = "2024"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
39 changes: 39 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,45 @@ function App() {

const handleProbeResult = useCallback(
(output: PluginOutput) => {
// DEBUG: stress-test mock plugin only — remove after visual QA
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
if (output.providerId === "mock") {
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Outdated
const _15d = 15 * 24 * 60 * 60 * 1000
const _30d = _15d * 2
const _resets = new Date(Date.now() + _15d).toISOString()
const _pastReset = new Date(Date.now() - 60_000).toISOString()
output = {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove mock output override from probe handling

In handleProbeResult, the new debug block replaces every probe response from the "mock" provider with hard-coded demo lines, so any real mock plugin data or error output is discarded. This means anyone using the mock plugin (including automated tests or manual verification) will never see actual probe results, which can hide regressions and break workflows that depend on the mock provider’s real output. This only occurs when the providerId is "mock", but it affects all environments where the mock plugin is enabled.

Useful? React with 👍 / 👎.

...output,
lines: [
// Pace statuses
{ type: "progress", label: "Ahead pace", used: 30, limit: 100, format: { kind: "percent" }, resetsAt: _resets, periodDurationMs: _30d },
{ type: "progress", label: "On Track pace", used: 45, limit: 100, format: { kind: "percent" }, resetsAt: _resets, periodDurationMs: _30d },
{ type: "progress", label: "Behind pace", used: 65, limit: 100, format: { kind: "percent" }, resetsAt: _resets, periodDurationMs: _30d },
// Edge: 0% used
{ type: "progress", label: "Empty bar", used: 0, limit: 500, format: { kind: "dollars" } },
// Edge: 100% used (exactly at limit)
{ type: "progress", label: "Exactly full", used: 1000, limit: 1000, format: { kind: "count", suffix: "tokens" } },
// Edge: over limit
{ type: "progress", label: "Over limit!", used: 1337, limit: 1000, format: { kind: "count", suffix: "requests" } },
// Edge: huge numbers
{ type: "progress", label: "Huge numbers", used: 8_429_301, limit: 10_000_000, format: { kind: "count", suffix: "tokens" } },
// Edge: tiny sliver
{ type: "progress", label: "Tiny sliver", used: 1, limit: 10000, format: { kind: "percent" } },
// Edge: nearly full
{ type: "progress", label: "Almost full", used: 9999, limit: 10000, format: { kind: "percent" } },
// Edge: reset already passed
{ type: "progress", label: "Expired reset", used: 42, limit: 100, format: { kind: "percent" }, resetsAt: _pastReset, periodDurationMs: _30d },
// Text lines
{ type: "text", label: "Status", value: "Active" },
{ type: "text", label: "Very long value", value: "This is an extremely long value string that should test text overflow and wrapping behavior in the card layout" },
{ type: "text", label: "", value: "Empty label" },
// Badge lines
{ type: "badge", label: "Tier", text: "Enterprise", color: "#8B5CF6" },
{ type: "badge", label: "Alert", text: "Rate limited", color: "#ef4444" },
{ type: "badge", label: "Region", text: "us-east-1" },
],
}
}
// END DEBUG
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated
const errorMessage = getErrorMessage(output)
const isManual = manualRefreshIdsRef.current.has(output.providerId)
if (isManual) {
Expand Down
6 changes: 3 additions & 3 deletions src/components/side-nav.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("SideNav", () => {
expect(icon).toHaveStyle({ backgroundColor: "#ff0000" })
})

it("falls back to currentColor for extremely light/dark brand colors", () => {
it("falls back to currentColor (light) or white (dark) for low-contrast brand colors", () => {
const onViewChange = vi.fn()

// Light mode + very light color => currentColor
Expand All @@ -58,7 +58,7 @@ describe("SideNav", () => {
const pStyle = screen.getByRole("img", { name: "P" }).getAttribute("style") ?? ""
expect(pStyle).toMatch(/background-color:\s*currentcolor/i)

// Dark mode + very dark color => currentColor
// Dark mode + very dark color => white
darkModeState.useDarkModeMock.mockReturnValueOnce(true)
rerender(
<SideNav
Expand All @@ -68,7 +68,7 @@ describe("SideNav", () => {
/>
)
const p2Style = screen.getByRole("img", { name: "P2" }).getAttribute("style") ?? ""
expect(p2Style).toMatch(/background-color:\s*currentcolor/i)
expect(p2Style).toContain("rgb(255, 255, 255)")
})
})

4 changes: 2 additions & 2 deletions src/components/side-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function NavButton({ isActive, onClick, children, "aria-label": ariaLabel }: Nav
"relative flex items-center justify-center w-full p-2.5 transition-colors",
"hover:bg-accent",
isActive
? "text-foreground before:absolute before:left-0 before:top-1.5 before:bottom-1.5 before:w-0.5 before:bg-primary before:rounded-full"
? "text-foreground before:absolute before:left-0 before:top-1.5 before:bottom-1.5 before:w-0.5 before:bg-primary dark:before:bg-page-accent before:rounded-full"
: "text-muted-foreground"
)}
>
Expand All @@ -57,7 +57,7 @@ function NavButton({ isActive, onClick, children, "aria-label": ariaLabel }: Nav
function getIconColor(brandColor: string | undefined, isDark: boolean): string {
if (!brandColor) return "currentColor"
const luminance = getRelativeLuminance(brandColor)
if (isDark && luminance < 0.15) return "currentColor"
if (isDark && luminance < 0.15) return "#ffffff"
if (!isDark && luminance > 0.85) return "currentColor"
return brandColor
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(
aria-valuenow={clamped}
aria-valuemin={0}
aria-valuemax={100}
className={cn("relative h-3 w-full overflow-hidden rounded-full bg-muted", className)}
className={cn("relative h-3 w-full overflow-hidden rounded-full bg-muted dark:bg-[#353537]", className)}
{...props}
>
<div
Expand Down
30 changes: 22 additions & 8 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--color-page-accent: var(--page-accent);
--color-green-500: var(--green-500);
--color-yellow-500: var(--yellow-500);
--color-red-500: var(--red-500);
}

:root {
Expand Down Expand Up @@ -78,22 +81,27 @@
--sidebar-accent-foreground: oklch(0.21 0.034 264.665);
--sidebar-border: oklch(0.928 0.006 264.531);
--sidebar-ring: oklch(0.707 0.022 261.325);

/* Tailwind green/yellow/red-500 (light: stock defaults) */
--green-500: oklch(0.723 0.219 142.37);
--yellow-500: oklch(0.795 0.184 86.047);
--red-500: oklch(0.637 0.237 25.331);
}

:root.dark {
--background: #0a0a0a;
--background: #1c1c1e;
--foreground: #ededed;
--card: #0a0a0a;
--card: #1c1c1e;
--card-foreground: #ededed;
--popover: #262626;
--popover: #2c2c2e;
--popover-foreground: #ededed;
--primary: #ededed;
--primary-foreground: #0a0a0a;
--secondary: #1a1a1a;
--secondary: #252527;
--secondary-foreground: #ededed;
--muted: #1a1a1a;
--muted: #2a2a2c;
--muted-foreground: #888888;
--accent: #1a1a1a;
--accent: #252527;
--accent-foreground: #ededed;
--destructive: #ef4444;
--border: rgba(255, 255, 255, 0.08);
Expand All @@ -104,17 +112,23 @@
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: #0a0a0a;
--sidebar: #2a2a2c;
--sidebar-foreground: #ededed;
--sidebar-primary: #ededed;
--sidebar-primary-foreground: #0a0a0a;
--sidebar-accent: #1a1a1a;
--sidebar-accent: #2a2a2c;
--sidebar-accent-foreground: #ededed;
--sidebar-border: rgba(255, 255, 255, 0.08);
--sidebar-ring: #555555;

/* Accent highlight (lime) */
--page-accent: #BFFF00;

/* Tailwind green/yellow/red-500 derived from page-accent lime
#BFFF00 ≈ oklch(0.93 0.27 128) — hue-rotate, keep chroma family */
--green-500: oklch(0.93 0.27 128);
--yellow-500: oklch(0.90 0.21 85);
--red-500: oklch(0.70 0.24 29);
}

@layer base {
Expand Down