Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
530535e
feat: add react-doctor for frontend React performance analysis
malinskibeniamin Mar 4, 2026
b910225
frontend: fix some react doctor issues
malinskibeniamin Mar 4, 2026
c372b24
frontend: apply PR feedback
malinskibeniamin Mar 6, 2026
20e2de6
frontend: fix react-doctor errors in topic-produce
malinskibeniamin Mar 10, 2026
a34ce0f
frontend: react-doctor config and reduced-motion CSS
malinskibeniamin Mar 10, 2026
635b413
frontend: phase 1 mechanical react-doctor fixes
malinskibeniamin Mar 10, 2026
e5ba0ac
frontend: fix React Compiler errors (immutability, hooks, refs, memoi…
malinskibeniamin Mar 10, 2026
6c3b312
frontend: fix try/catch value blocks and immutability compiler errors
malinskibeniamin Mar 10, 2026
14ad852
frontend: refactor payload-component and fix ref write pattern
malinskibeniamin Mar 10, 2026
9e348bf
frontend: align react-doctor config with cloudv2 PR #24811
malinskibeniamin Mar 10, 2026
9047023
frontend: fix payload-component type error in json render data
malinskibeniamin Mar 10, 2026
dfb2b5b
frontend: add use-no-memo directives and React Compiler source filter
malinskibeniamin Mar 10, 2026
22e4db9
frontend: fix Phase 3 warnings (a11y, array-keys, async-parallel)
malinskibeniamin Mar 10, 2026
1d92073
frontend: fix array-index-as-key in principal-group-editor
malinskibeniamin Mar 10, 2026
16dcb15
ci: update react-doctor workflow fail-on to warning level
malinskibeniamin Mar 10, 2026
273db6b
ci: use bun run doctor instead of millionco GitHub Action
malinskibeniamin Mar 10, 2026
fe913a0
frontend: ignore React Compiler rules in react-doctor config
malinskibeniamin Mar 10, 2026
0a35200
frontend: fix remaining no-array-index-as-key warnings for 100/100 re…
malinskibeniamin Mar 10, 2026
aaa45ae
frontend: enable react-hooks/rules-of-hooks in react-doctor
malinskibeniamin Mar 10, 2026
4db841b
ci: align react-doctor workflow with cloudv2 pattern
malinskibeniamin Mar 10, 2026
1d344f4
frontend: add diff: false to react-doctor config
malinskibeniamin Mar 10, 2026
c511c4b
frontend: enable react-hooks-js/error-boundaries and preserve-manual-…
malinskibeniamin Mar 11, 2026
8a2b6e6
frontend: enable react-doctor/no-prevent-default rule
malinskibeniamin Mar 11, 2026
8eca4b9
frontend: enable react-doctor/no-derived-useState rule
malinskibeniamin Mar 11, 2026
7bc8bcc
frontend: enable react-hooks-js/static-components rule
malinskibeniamin Mar 11, 2026
3454947
frontend: enable react-hooks-js/purity rule
malinskibeniamin Mar 11, 2026
aa19030
frontend: enable react-hooks-js/hooks rule
malinskibeniamin Mar 11, 2026
2a739e6
frontend: enable react-hooks-js/immutability rule
malinskibeniamin Mar 11, 2026
d2a138b
frontend: enable react-doctor/no-effect-event-handler rule
malinskibeniamin Mar 11, 2026
b6bfb96
frontend: enable react-doctor/no-cascading-set-state rule
malinskibeniamin Mar 11, 2026
3382858
frontend: enable react-hooks-js/todo rule
malinskibeniamin Mar 11, 2026
7559561
frontend: enable react-hooks-js/refs rule
malinskibeniamin Mar 11, 2026
4403e03
frontend: enable react-hooks-js/set-state-in-effect rule
malinskibeniamin Mar 11, 2026
3479763
frontend: enable react-hooks-js/incompatible-library rule
malinskibeniamin Mar 11, 2026
981d33d
frontend: enable react-doctor/prefer-dynamic-import rule
malinskibeniamin Mar 11, 2026
33b8acc
frontend: enable react-doctor/prefer-useReducer rule
malinskibeniamin Mar 11, 2026
0990b57
frontend: enable react-doctor/no-render-in-render rule
malinskibeniamin Mar 11, 2026
f0d363b
frontend: fix react-doctor regressions from type-fix agent
malinskibeniamin Mar 11, 2026
4d9e6b9
frontend: fix type errors
malinskibeniamin Mar 11, 2026
af8878b
frontend: fix useApiStore type errors with useApiStoreHook wrapper
malinskibeniamin Mar 11, 2026
0c86164
frontend: restore useStore import in backend-api.ts
malinskibeniamin Mar 11, 2026
cccdb3c
frontend: fix useApiStoreHook selector type to match raw store state
malinskibeniamin Mar 11, 2026
9d2dcf7
frontend: enable knowledgebase files in react-doctor config
malinskibeniamin Mar 11, 2026
7a7657a
frontend: enable agents list page in react-doctor config
malinskibeniamin Mar 11, 2026
192202b
frontend: enable mcp-servers list page in react-doctor config
malinskibeniamin Mar 11, 2026
ab0d891
frontend: enable secrets-store list page in react-doctor config
malinskibeniamin Mar 11, 2026
a38670e
frontend: enable observability metric-chart in react-doctor config
malinskibeniamin Mar 11, 2026
d2595fd
frontend: enable transcripts table in react-doctor config
malinskibeniamin Mar 11, 2026
7db49e2
ci: remove pull_request trigger from react-doctor workflow
malinskibeniamin Mar 11, 2026
16b26d0
frontend: ignore prefer-dynamic-import rule in react-doctor config
malinskibeniamin Mar 11, 2026
074c3cd
ci: remove reviewdog frontend review workflow
malinskibeniamin Mar 11, 2026
0378f14
frontend: enable shadowlinks files in react-doctor config
malinskibeniamin Mar 11, 2026
999ef9f
frontend: enable remaining files in react-doctor config
malinskibeniamin Mar 11, 2026
9fd505a
frontend: fix react-doctor warnings for 100/100 score
malinskibeniamin Mar 11, 2026
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
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
name: "Frontend Review"
---
name: "Frontend React Doctor"
on:
pull_request:
push:
paths:
- "frontend/**"
- ".github/workflows/frontend-review.yml"
env:
CI: true
- ".github/workflows/frontend-react-doctor.yml"
jobs:
biome:
name: runner / Biome
react-doctor:
timeout-minutes: 5
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
contents: read
defaults:
run:
working-directory: frontend
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v5
Expand All @@ -32,16 +30,5 @@ jobs:
${{ runner.os }}-bun-frontend-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Get Biome version
id: biome-version
run: echo "version=$(jq -r '.devDependencies["@biomejs/biome"]' package.json)" >> $GITHUB_OUTPUT
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: ${{ steps.biome-version.outputs.version }}
- name: Setup Reviewdog Biome action
uses: mongolyy/reviewdog-action-biome@v1
with:
github_token: ${{ secrets.github_token }}
workdir: frontend
reporter: github-pr-review
- name: Run React Doctor
run: bun run doctor
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ https://user-images.githubusercontent.com/23424570/220130537-7b0b8596-0a06-4132-
- **Kafka connect:** Manage connectors from multiple connect clusters, patch configs, view their current state or restart tasks.
- **Redpanda Transforms:** Manage and monitor data transforms deployed in your Redpanda cluster.

## Code Quality

The frontend uses [react-doctor](https://github.com/aidenybai/react-doctor) to statically analyze React components for performance anti-patterns. Run `bun run doctor` in the `frontend/` directory for a local scan. React Doctor also runs automatically in CI on every push and pull request.

## Getting Started

### Prerequisites
Expand Down
326 changes: 321 additions & 5 deletions frontend/bun.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
"format:check": "biome format src/*",
"format": "biome format src/* --write",
"load-git-hooks": "cd .. && git config core.hooksPath \"./.git-hooks\"",
"doctor": "bunx react-doctor . -y --fail-on error",
"quality:gate": "bun run lint && bun run doctor && bun run type:check && bun run build && bun run test:unit && bun run test:integration",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍 maybe even check or something we'd definitely remember before committing?

Copy link
Copy Markdown
Contributor Author

@malinskibeniamin malinskibeniamin Mar 6, 2026

Choose a reason for hiding this comment

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

We already have "check" used across various repos for other purposes.

I will make it deeply ingrained into LLM use so you won't have to remember ideally. Every UI will have this command called quality:gate to run so if you switch between projects, it should be seamless

"analyze": "RSDOCTOR=true npm run build",
"prepare": "lefthook install"
},
Expand Down Expand Up @@ -176,6 +178,7 @@
"babel-plugin-react-compiler": "^1.0.0",
"lefthook": "^2.0.12",
"node-fetch": "^3.3.2",
"react-doctor": "^0.0.29",
"rsbuild-plugin-devtools-json": "^0.2.5",
"tar-stream": "^3.1.7",
"testcontainers": "^11.10.0",
Expand Down
15 changes: 15 additions & 0 deletions frontend/react-doctor.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"diff": false,
"deadCode": false,
"ignore": {
"files": [
"src/components/ui/**",
"src/components/redpanda-ui/**",
"src/components/ai-elements/**",
"src/hooks/use-mobile.ts",
"src/globals.css",
"src/components/pages/connect/dynamic-ui/components.tsx"
],
"rules": ["react-doctor/use-lazy-motion", "react-doctor/no-giant-component", "react-doctor/require-reduced-motion", "react-hooks-js/incompatible-library", "react-doctor/prefer-useReducer", "react-doctor/prefer-dynamic-import"]
Comment thread
malinskibeniamin marked this conversation as resolved.
}
}
19 changes: 18 additions & 1 deletion frontend/rsbuild.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,24 @@ export default defineConfig({
include: /\.(?:ts|tsx)$/,
babelLoaderOptions(opts) {
opts.plugins ??= [];
opts.plugins.unshift(['babel-plugin-react-compiler', { target: '18' }]);
opts.plugins.unshift([
'babel-plugin-react-compiler',
{
target: '18',
sources: (filename: string) => {
if (filename.includes('/lib/redpanda-ui/')) {
return false;
}
if (filename.includes('/gen/')) {
return false;
}
if (filename.includes('node_modules')) {
return false;
}
return true;
},
},
]);
},
}),
pluginSvgr({ mixedImport: true }),
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/assets/connectors/logos/authzed-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export const AuthzedLogo = (props: React.SVGProps<SVGSVGElement>) => (
fill="#FB5B62"
/>
<path
clip-rule="evenodd"
clipRule="evenodd"
d="M25.3806 20.2627C25.9119 19.6964 25.4439 18.7788 24.6708 18.8709L11.1529 20.4817C10.744 20.5304 10.4038 20.8236 10.3212 21.225C9.80139 23.7533 10.0088 26.2995 10.9869 28.8481C11.3532 29.8029 11.3761 29.8304 10.3874 29.9513C10.2584 29.9671 10.1293 29.9845 9.99985 30.002C9.25441 30.1025 8.50194 30.204 7.75191 29.9922C5.93886 29.4783 8.7274 27.7695 8.93794 27.0394C9.09342 26.5002 8.35683 26.2983 7.8963 26.6219C6.4206 27.6588 5.01567 28.8688 4.14448 30.4689C3.95831 30.8394 3.98134 31.3025 4.05138 31.553C4.56722 33.3971 8.56098 33.0623 9.87676 32.8272C11.6009 32.5192 12.8458 32.4074 14.5209 31.8981C14.9777 31.7592 14.9862 31.713 15.6842 30.9974C19.2205 27.7315 22.4568 23.2786 25.3806 20.2627Z"
fill="#EFA16D"
fill-rule="evenodd"
fillRule="evenodd"
/>
</svg>
);
4 changes: 2 additions & 2 deletions frontend/src/assets/connectors/logos/aws-dynamo-db.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const AWSDynamoDbLogo = (props: React.SVGProps<SVGSVGElement>) => (
<title>AWS DynamoDB</title>
<defs>
<linearGradient id="linearGradient-1" x1="0%" x2="100%" y1="100%" y2="0%">
<stop offset="0%" stop-color="#2E27AD" />
<stop offset="100%" stop-color="#527FFF" />
<stop offset="0%" stopColor="#2E27AD" />
<stop offset="100%" stopColor="#527FFF" />
</linearGradient>
</defs>
<g>
Expand Down
16 changes: 8 additions & 8 deletions frontend/src/assets/connectors/logos/memcached-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ export const MemcachedLogo = (props: React.SVGProps<SVGSVGElement>) => (
<title>Memcached</title>
<defs>
<linearGradient gradientUnits="userSpaceOnUse" id="A" x1="255.894" x2="255.894" y1="59.789" y2="-452">
<stop offset="0%" stop-color="#574c4a" />
<stop offset="100%" stop-color="#80716d" />
<stop offset="0%" stopColor="#574c4a" />
<stop offset="100%" stopColor="#80716d" />
</linearGradient>
<linearGradient gradientUnits="userSpaceOnUse" id="B" x1="380.442" x2="191.971" y1="-51.758" y2="-382.305">
<stop offset="0%" stop-color="#268d83" />
<stop offset="100%" stop-color="#2ea19e" />
<stop offset="0%" stopColor="#268d83" />
<stop offset="100%" stopColor="#2ea19e" />
</linearGradient>
<radialGradient
cx="62.417"
Expand All @@ -22,8 +22,8 @@ export const MemcachedLogo = (props: React.SVGProps<SVGSVGElement>) => (
id="C"
r="9.213"
>
<stop offset="0%" stop-color="#db7c7c" />
<stop offset="100%" stop-color="#c83737" />
<stop offset="0%" stopColor="#db7c7c" />
<stop offset="100%" stopColor="#c83737" />
</radialGradient>
<radialGradient
cx="96.726"
Expand All @@ -35,8 +35,8 @@ export const MemcachedLogo = (props: React.SVGProps<SVGSVGElement>) => (
id="D"
r="9.213"
>
<stop offset="0%" stop-color="#db7c7c" />
<stop offset="100%" stop-color="#c83737" />
<stop offset="0%" stopColor="#db7c7c" />
<stop offset="100%" stopColor="#c83737" />
</radialGradient>
</defs>
<g transform="matrix(.125052 0 0 .125052 .000001 56.523492)">
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/assets/connectors/logos/microsoft-azure-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const MicrosoftazureLogo = (props: React.SVGProps<SVGSVGElement>) => (
y1="145.31"
y2="65.43"
>
<stop offset="0" stop-color="#114a8b" />
<stop offset="1" stop-color="#0669bc" />
<stop offset="0" stopColor="#114a8b" />
<stop offset="1" stopColor="#0669bc" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1 0 0 -1 1075 158)"
Expand All @@ -25,11 +25,11 @@ export const MicrosoftazureLogo = (props: React.SVGProps<SVGSVGElement>) => (
y1="108.08"
y2="105.97"
>
<stop offset="0" stop-opacity=".3" />
<stop offset=".07" stop-opacity=".2" />
<stop offset=".32" stop-opacity=".1" />
<stop offset=".62" stop-opacity=".05" />
<stop offset="1" stop-opacity="0" />
<stop offset="0" stopOpacity=".3" />
<stop offset=".07" stopOpacity=".2" />
<stop offset=".32" stopOpacity=".1" />
<stop offset=".62" stopOpacity=".05" />
<stop offset="1" stopOpacity="0" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1 0 0 -1 1075 158)"
Expand All @@ -40,8 +40,8 @@ export const MicrosoftazureLogo = (props: React.SVGProps<SVGSVGElement>) => (
y1="147.64"
y2="68.56"
>
<stop offset="0" stop-color="#3ccbf4" />
<stop offset="1" stop-color="#2892df" />
<stop offset="0" stopColor="#3ccbf4" />
<stop offset="1" stopColor="#2892df" />
</linearGradient>
</defs>
<path
Expand Down
50 changes: 25 additions & 25 deletions frontend/src/assets/connectors/logos/pinecone-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,44 @@ export const PineconeLogo = (props: React.SVGProps<SVGSVGElement>) => (
<svg fill="currentColor" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" {...props}>
<title>Pinecone</title>
<g fill="none" fillRule="evenodd" transform="translate(0 1)">
<path d="m14.58 5.24.7-3.89" stroke="#201d1e" stroke-linecap="square" stroke-width="1.77" />
<path d="m14.58 5.24.7-3.89" stroke="#201d1e" strokeLinecap="square" strokeWidth="1.77" />
<path
d="m17.8 3.86-2.44-2.98-3.32 1.94"
stroke="#201d1e"
stroke-linecap="square"
stroke-linejoin="round"
stroke-width="1.77"
strokeLinecap="square"
strokeLinejoin="round"
strokeWidth="1.77"
/>
<path d="m11.66 21.84.68-3.89" stroke="#201d1e" stroke-linecap="square" stroke-width="1.77" />
<path d="m11.66 21.84.68-3.89" stroke="#201d1e" strokeLinecap="square" strokeWidth="1.77" />
<path
d="m14.88 20.45-2.46-2.97-3.31 1.95"
stroke="#201d1e"
stroke-linecap="square"
stroke-linejoin="round"
stroke-width="1.77"
strokeLinecap="square"
strokeLinejoin="round"
strokeWidth="1.77"
/>
<path d="m13.07 13.82.68-3.89" stroke="#201d1e" stroke-linecap="square" stroke-width="1.77" />
<path d="m13.07 13.82.68-3.89" stroke="#201d1e" strokeLinecap="square" strokeWidth="1.77" />
<path
d="m16.29 12.43-2.45-2.96-3.31 1.94"
stroke="#201d1e"
stroke-linecap="square"
stroke-linejoin="round"
stroke-width="1.77"
strokeLinecap="square"
strokeLinejoin="round"
strokeWidth="1.77"
/>
<circle cx="10.77" cy="26.85" fill="#201d1e" fillRule="nonzero" r="1.63" />
<g stroke="#201d1e" stroke-linecap="square">
<path d="m6.15 21.5-2.99 2.08" stroke-width="1.68" />
<path d="m6.33 24.87-3.53-1.04.26-3.67" stroke-linejoin="round" stroke-width="1.68" />
<path d="m17.01 23.45 2.08 3" stroke-width="1.68" />
<path d="m15.67 26.55 3.67.25 1.04-3.51" stroke-linejoin="round" stroke-width="1.68" />
<path d="m20.42 17.36 3.66.66" stroke-width="1.72" />
<path d="m21.68 20.57 2.84-2.47-1.79-3.29" stroke-linejoin="round" stroke-width="1.72" />
<path d="m19.35 10.1 3.26-1.8" stroke-width="1.72" />
<path d="m19.53 6.65 3.47 1.44-.65 3.69" stroke-linejoin="round" stroke-width="1.72" />
<path d="m4.97 14.64-3.67-.64" stroke-width="1.72" />
<path d="m2.68 17.22-1.82-3.29 2.81-2.48" stroke-linejoin="round" stroke-width="1.72" />
<path d="m8.45 8.17-2.45-2.8" stroke-width="1.72" />
<path d="m9.46 4.88-3.75.16-.66 3.69" stroke-linejoin="round" stroke-width="1.72" />
<g stroke="#201d1e" strokeLinecap="square">
<path d="m6.15 21.5-2.99 2.08" strokeWidth="1.68" />
<path d="m6.33 24.87-3.53-1.04.26-3.67" strokeLinejoin="round" strokeWidth="1.68" />
<path d="m17.01 23.45 2.08 3" strokeWidth="1.68" />
<path d="m15.67 26.55 3.67.25 1.04-3.51" strokeLinejoin="round" strokeWidth="1.68" />
<path d="m20.42 17.36 3.66.66" strokeWidth="1.72" />
<path d="m21.68 20.57 2.84-2.47-1.79-3.29" strokeLinejoin="round" strokeWidth="1.72" />
<path d="m19.35 10.1 3.26-1.8" strokeWidth="1.72" />
<path d="m19.53 6.65 3.47 1.44-.65 3.69" strokeLinejoin="round" strokeWidth="1.72" />
<path d="m4.97 14.64-3.67-.64" strokeWidth="1.72" />
<path d="m2.68 17.22-1.82-3.29 2.81-2.48" strokeLinejoin="round" strokeWidth="1.72" />
<path d="m8.45 8.17-2.45-2.8" strokeWidth="1.72" />
<path d="m9.46 4.88-3.75.16-.66 3.69" strokeLinejoin="round" strokeWidth="1.72" />
</g>
</g>
</svg>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/assets/connectors/logos/qdrant-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type React from 'react';
export const QdrantLogo = (props: React.SVGProps<SVGSVGElement>) => (
<svg fill="currentColor" viewBox="0 0 57 64" xmlns="http://www.w3.org/2000/svg" {...props}>
<title>Qdrant</title>
<g clip-path="url(#a)">
<g clipPath="url(#a)">
<path
d="M28.335 0 .62 16v32l27.714 16 10.392-6V46l-10.392 6-17.32-10V22l17.32-10 17.32 10v40l10.393-6V16z"
fill="#dc244c"
Expand Down
20 changes: 9 additions & 11 deletions frontend/src/components/builder-io/nurture-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ export default function NurturePanel() {
const platform = api.isRedpanda ? 'redpanda' : 'kafka';
const MODEL_NAME = `console-nurture-panel-${platform}`;

const [content, setContent] = useState<BuilderContent | null>(null);
const [isLoading, setIsLoading] = useState(!embedded);
const [hasError, setHasError] = useState(false);
const [fetchState, setFetchState] = useState<{
content: BuilderContent | null;
isLoading: boolean;
hasError: boolean;
}>({ content: null, isLoading: !embedded, hasError: false });

const { content, isLoading, hasError } = fetchState;

useEffect(() => {
if (embedded) {
Expand All @@ -42,16 +46,10 @@ export default function NurturePanel() {
},
})
.then((fetchedContent) => {
if (fetchedContent) {
setContent(fetchedContent);
}
setHasError(false);
setFetchState({ content: fetchedContent ?? null, isLoading: false, hasError: false });
})
.catch(() => {
setHasError(true);
})
.finally(() => {
setIsLoading(false);
setFetchState((prev) => ({ ...prev, isLoading: false, hasError: true }));
});
}, [platform, MODEL_NAME, embedded]);

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/form/error-info/error-info-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export const ErrorInfoField = ({ field }: ErrorInfoFieldProps) => {
return (
<FormErrorMessage>
<UnorderedList>
{filteredErrors.map((error, index) => (
<ListItem key={`${field.name}-${index}`}>
{filteredErrors.map((error) => (
<ListItem key={`${field.name}-${error.message}`}>
<Text>{error.message}</Text>
</ListItem>
))}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/form/key-value/key-value-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const KeyValueField = ({ label, helperText, showAddButton = true, ...rest
)}
</Stack>
{field?.state?.value?.map((pair, index) => (
<KeyValuePairField index={index} key={`${pair.key}-${pair.value}-${index}`} {...rest} />
<KeyValuePairField index={index} key={`kv-${pair.key}-${pair.value}`} {...rest} />
))}

{Boolean(showAddButton) && (
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/components/layout/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
* by the Apache License, Version 2.0
*/

'use no memo';

import { Box, Button, ColorModeSwitch, CopyButton, Flex } from '@redpanda-data/ui';
import { Link, useLocation, useMatchRoute } from '@tanstack/react-router';
import { Heading } from 'components/redpanda-ui/components/typography';
import { cn } from 'components/redpanda-ui/lib/utils';
import { Fragment, useMemo } from 'react';
import { useStore } from 'zustand';

import { isEmbedded } from '../../config';
import { api, useApiStore } from '../../state/backend-api';
import { api, useApiStoreHook } from '../../state/backend-api';
import { type BreadcrumbEntry, useUIStateStore } from '../../state/ui-state';
import { IsDev } from '../../utils/env';
import DataRefreshButton from '../misc/buttons/data-refresh/component';
Expand Down Expand Up @@ -69,7 +70,7 @@ function BreadcrumbHeaderRow({ useNewSidebar, breadcrumbItems }: BreadcrumbHeade
}

function AppPageHeader() {
useStore(useApiStore, (s) => s.userData); // re-render when userData changes
useApiStoreHook((s) => s.userData); // re-render when userData changes
const showRefresh = useShouldShowRefresh();
const shouldHideHeader = useShouldHideHeader();
const useNewSidebar = !isEmbedded();
Expand Down
Loading
Loading