| BLOCKING |
Code Review |
types.ts:12 |
Public prop shapes use type instead of interface — violates AGENTS.md convention |
Change type F0BigNumberProps → interface F0BigNumberProps |
| BLOCKING |
Code Review |
types.ts:17 |
comparison is required but Default story omits it; 5 tests use unknown as number cast |
Make comparison?: ... optional |
| BLOCKING |
Code Review |
F0BigNumber.tsx:11 |
Relative cross-component import "../tags/F0TagBalance" bypasses public @/components/ alias and imports pre-HOC component |
Replace with import { F0TagBalance } from "@/components/tags/F0TagBalance" |
| BLOCKING |
Code Review |
F0BigNumber.tsx:11 |
Imports raw F0TagBalance (no withDataTestId HOC) — dataTestId on the inner tag is silently non-functional |
Import via public barrel or apply HOC |
| BLOCKING |
Code Review |
F0BigNumber.tsx:49-55 |
Duplicate !comparisonValue guard in useMemo creates dead code — second branch is unreachable |
Remove duplicate guard; keep a single early-return |
| BLOCKING |
A11y |
F0BigNumber.tsx:61-62 |
Label rendered in a bare <div> with no programmatic association to the value <span> — WCAG 1.3.1 |
Wrap in <figure>/<figcaption> or add role="group" + aria-labelledby |
| BLOCKING |
A11y |
F0BigNumber.tsx:64 |
<span> for formattedValue has no programmatic context for screen readers — WCAG 1.3.1/1.3.2 |
Associate via aria-labelledby pointing to the label element |
| BLOCKING |
A11y |
F0BigNumber.tsx:78-88 |
Skeleton has no aria-busy="true", aria-live="polite", or accessible loading text — WCAG 4.1.3 |
Add aria-busy="true" aria-live="polite" to skeleton root; add <span className="sr-only">{t("loading")}</span> |
| BLOCKING |
A11y |
F0BigNumber.tsx:80 |
cursor-progress conveys loading state to sighted users only — WCAG 1.3.3, 4.1.2 |
Add sr-only loading text via useI18n() |
| BLOCKING |
A11y |
F0TagBalance.tsx:90 |
Trend icon is decorative but not aria-hidden="true" — exposed to AT — WCAG 1.1.1 |
Add aria-hidden="true" to the trend icon |
| BLOCKING |
Storybook |
F0BigNumber.stories.tsx:12 |
const meta: Meta<...> must be satisfies Meta<typeof F0BigNumber> — violates story conventions |
Change to const meta = { ... } satisfies Meta<typeof F0BigNumber> |
| BLOCKING |
Storybook |
F0BigNumber.stories.tsx:78 |
StoryObj<typeof F0BigNumber> must be StoryObj<typeof meta> |
Change every StoryObj<typeof F0BigNumber> → StoryObj<typeof meta> |
| BLOCKING |
Storybook |
F0BigNumber.stories.tsx:80-89 |
Default story omits the required comparison prop — story renders incorrectly |
Add comparison arg to Default story (or make prop optional first) |
| BLOCKING |
Storybook |
F0BigNumber.stories.tsx:169-176 |
Snapshot story uses withSnapshot({}) but also renders normal content — causes double Chromatic capture |
Move snapshot-only content inside withSnapshot; remove duplicate rendering |
| BLOCKING |
Test Coverage |
F0BigNumber.test.tsx:1 |
screen imported from @testing-library/react — must come from @/testing/test-utils |
import { screen, zeroRender } from "@/testing/test-utils" |
| BLOCKING |
Test Coverage |
F0BigNumber.test.tsx:2 |
Forbidden import "@testing-library/jest-dom/vitest" — globally provided via test setup |
Remove the import entirely |
| BLOCKING |
Test Coverage |
F0BigNumber.test.tsx:810-813 |
container.querySelector with CSS class selector — fragile and forbidden |
Replace with screen.getByRole / screen.getByTestId |
| BLOCKING |
Test Coverage |
F0BigNumber.test.tsx:204-208 |
container.querySelectorAll("div") for absence check — vacuous logic (always finds divs) |
Use screen.queryByRole or screen.queryByTestId with correct assertion |
Stability Audit — F0BigNumber
BLOCKING
types.ts:12typeinstead ofinterface— violates AGENTS.md conventiontype F0BigNumberProps→interface F0BigNumberPropstypes.ts:17comparisonis required but Default story omits it; 5 tests useunknown as numbercastcomparison?: ...optionalF0BigNumber.tsx:11"../tags/F0TagBalance"bypasses public@/components/alias and imports pre-HOC componentimport { F0TagBalance } from "@/components/tags/F0TagBalance"F0BigNumber.tsx:11F0TagBalance(nowithDataTestIdHOC) —dataTestIdon the inner tag is silently non-functionalF0BigNumber.tsx:49-55!comparisonValueguard inuseMemocreates dead code — second branch is unreachableF0BigNumber.tsx:61-62<div>with no programmatic association to the value<span>— WCAG 1.3.1<figure>/<figcaption>or addrole="group"+aria-labelledbyF0BigNumber.tsx:64<span>forformattedValuehas no programmatic context for screen readers — WCAG 1.3.1/1.3.2aria-labelledbypointing to the label elementF0BigNumber.tsx:78-88aria-busy="true",aria-live="polite", or accessible loading text — WCAG 4.1.3aria-busy="true" aria-live="polite"to skeleton root; add<span className="sr-only">{t("loading")}</span>F0BigNumber.tsx:80cursor-progressconveys loading state to sighted users only — WCAG 1.3.3, 4.1.2sr-onlyloading text viauseI18n()F0TagBalance.tsx:90aria-hidden="true"— exposed to AT — WCAG 1.1.1aria-hidden="true"to the trend iconF0BigNumber.stories.tsx:12const meta: Meta<...>must besatisfies Meta<typeof F0BigNumber>— violates story conventionsconst meta = { ... } satisfies Meta<typeof F0BigNumber>F0BigNumber.stories.tsx:78StoryObj<typeof F0BigNumber>must beStoryObj<typeof meta>StoryObj<typeof F0BigNumber>→StoryObj<typeof meta>F0BigNumber.stories.tsx:80-89Defaultstory omits the requiredcomparisonprop — story renders incorrectlycomparisonarg to Default story (or make prop optional first)F0BigNumber.stories.tsx:169-176Snapshotstory useswithSnapshot({})but also renders normal content — causes double Chromatic capturewithSnapshot; remove duplicate renderingF0BigNumber.test.tsx:1screenimported from@testing-library/react— must come from@/testing/test-utilsimport { screen, zeroRender } from "@/testing/test-utils"F0BigNumber.test.tsx:2import "@testing-library/jest-dom/vitest"— globally provided via test setupF0BigNumber.test.tsx:810-813container.querySelectorwith CSS class selector — fragile and forbiddenscreen.getByRole/screen.getByTestIdF0BigNumber.test.tsx:204-208container.querySelectorAll("div")for absence check — vacuous logic (always finds divs)screen.queryByRoleorscreen.queryByTestIdwith correct assertionSUGGESTION
F0BigNumber.tsx:48useMemowrapping primitive arithmetic — no measurable benefituseMemo; compute inlineindex.tsx:2export *leaksNumberWithFormatterinternal type into the public APIF0BigNumber.tsx:29forwardRef— ref accepted by HOC wrapper silently resolves tonullforwardRefsupportF0BigNumber.tsx:4-5@/lib/numeric/utils/…instead of barrel exportF0BigNumber.tsx:64font-bold text-2xlinstead ofF0Text/ design tokens<F0Text>with appropriate variantF0TagBalance.tsx:86"positive balance") — not i18n-safeuseI18n()translation keyF0BigNumber.tsx:62<div>lacks semantic element for screen reader grouping<figcaption>or semantic heading elementsr-onlyloading text must useuseI18n(), not hardcoded EnglishuseI18n()playfunction inline type annotation is redundant — inferred fromStoryObjplay: (args: ...) =>type annotationas BigNumberPropscast in Snapshot story masks potential type errorcomparisonHintwithout trend — untested combinationF0BigNumber.test.tsx:27-33vi.mockfor same component — symptom of wrong import pathanimatedprop onNumberWithFormatternever testedtrend: nullpath innormalizeTrendis never exercisednulltrend caseexpect(container).toBeInTheDocument()is always-true assertionunknown as numbercast used in 5 tests to work around requiredcomparisoncomparisonis made optionaltypes.ts— makingcomparisonoptional would eliminate 5unknown as numbercasts in testscomparison?: ...optionalReady-to-run agent fix prompt