chore: upgrade packages and migrations#351
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 35 minutes and 58 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (15)
📝 WalkthroughWalkthroughComprehensive upgrade of ESLint configuration to flat config format, Tailwind CSS v3 to v4, and Next.js/React framework versions. Includes image import path conversions to aliases, SEO metadata consolidation via new helper function, and removal of TextReveal component. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser/Client
participant Page as Page Component
participant Meta as sitePageMetadata()
participant OG as og-image Handler
participant CDN as Image CDN/API
Browser->>Page: Request page
Page->>Page: getTranslations()
Page->>Meta: sitePageMetadata({title, description, alternates, openGraphImages?})
alt openGraphImages provided
Meta->>Meta: Normalize image URLs
Meta->>Meta: Build OpenGraph metadata
else no custom images
Meta->>OG: Generate default /api/og?title=...&description=...
OG->>CDN: Build 1200x630 image
CDN-->>OG: Image URL
OG-->>Meta: Return image URL
Meta->>Meta: Build OpenGraph with generated image
end
Meta-->>Page: Return Metadata object
Page-->>Browser: Send page + metadata headers
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #351 +/- ##
==========================================
- Coverage 81.66% 80.06% -1.61%
==========================================
Files 88 87 -1
Lines 960 963 +3
Branches 232 243 +11
==========================================
- Hits 784 771 -13
- Misses 176 192 +16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (1)
eslint.config.mjs (1)
40-45: Stylistic rules conflict with Prettier.
no-multi-spaces,object-curly-spacing, andquotesare exactly the kinds of stylistic rules thateslint-config-prettierdisables to avoid conflicts. Because this custom block is applied aftereslintConfigPrettierandprettierRecommended, these rules are re-enabled and will fight Prettier on autofix (e.g., single vs. double quotes in JSX attrs, spacing). Recommend removing them and letting Prettier own formatting.♻️ Proposed diff
rules: { 'no-console': 'warn', - 'no-multi-spaces': 'error', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-unused-vars': 'off', 'react/no-unescaped-entities': 'off', - 'object-curly-spacing': ['warn', 'always'], - quotes: ['warn', 'single', { avoidEscape: true }], 'react/display-name': 'off',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eslint.config.mjs` around lines 40 - 45, The listed stylistic ESLint rules ('no-multi-spaces', 'object-curly-spacing', and 'quotes') conflict with Prettier because this custom block runs after eslint-config-prettier and prettierRecommended; remove or disable those three rules (or set them to 'off') so Prettier controls formatting, leaving only non-formatting/semantic rules (e.g., keep '@typescript-eslint/explicit-module-boundary-types' or '@typescript-eslint/no-unused-vars' as appropriate) in the same config block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@eslint.config.mjs`:
- Around line 10-20: globalIgnores pattern currently only excludes '*.config.js'
so config files with other extensions are still linted; update the pattern
passed to globalIgnores (the globalIgnores([...]) call) to include other config
file extensions such as .cjs, .mjs, and .ts by replacing the single
'*.config.js' entry with a glob like '**/*.config.{js,cjs,mjs,ts}' so
tailwind.config.ts, sentry.*.config.ts, eslint.config.mjs, etc. are ignored by
ESLint.
In `@public/locales/en/imprint.json`:
- Around line 47-48: Update the "title" value in the imprint locale entry to use
the same separator style as other page titles (replace the em dash in the
"title" string "Legal notice — provider details and disclaimers" with a colon or
hyphen to match company.json); locate the "title" key in
public/locales/en/imprint.json and change the separator character only, keeping
the rest of the text identical so localization keys remain consistent.
In `@src/app/`[locale]/newsroom/[slug]/page.tsx:
- Around line 38-43: The page component still dereferences posts.data[0] and can
crash for invalid slugs; update the PostPage rendering logic to mirror
generateMetadata by checking for a missing post (inspect post or posts.data[0])
and call Next.js notFound() (or return the same site-level fallback) instead of
proceeding, ensuring PostPage (the component that uses posts/posts.data[0])
never dereferences when post is undefined.
In `@src/app/`[locale]/not-found.tsx:
- Around line 14-18: The not-found metadata currently sets alternates via
getAlternates('/', locale) which points hreflang links to the site root; update
the not-found.tsx metadata generation (sitePageMetadata call) to omit or clear
the alternates field for the 404 page (remove or set alternates to
undefined/null) so the generated not-found page does not advertise localized
home URLs, or alternatively supply a true routable 404-equivalent path if you
intend language-specific 404 pages; modify the sitePageMetadata(...) invocation
in not-found.tsx and remove/getAlternates usage accordingly.
In `@src/components/layout/Footer.tsx`:
- Line 170: The LanguagePicker's interactive element in Footer.tsx currently
suppresses all focus indicators by using className with focus:ring-0,
focus:ring-transparent, focus:ring-offset-0, focus:ring-offset-transparent,
focus:ring-inset and focus:outline-none; remove the redundant/conflicting
focus-suppression classes from that className and instead apply a clear visible
focus style (for example use Tailwind's focus-visible:ring and
focus-visible:ring-offset with an accessible color) either on the LanguagePicker
element itself or on its parent container so keyboard users see a focus
indicator; update the className string used for the LanguagePicker element to
drop the suppression classes and add the appropriate focus-visible utilities.
- Line 161: In the Footer component's language picker element (in
src/components/layout/Footer.tsx) replace the Tailwind class 'focus:outline-0'
with 'focus:outline-2' so the focus styling reads 'focus:outline-2
focus:outline-offset-4 focus:outline-gray-300 focus:outline-dashed'; update the
class string on the language picker/select element in the Footer component to
ensure a visible dashed focus ring for keyboard users.
In `@src/components/templates/Globe.tsx`:
- Around line 143-155: Replace the truthy check that uses
pointerInteracting.current with an explicit null/undefined check so a numeric 0
(valid drag state) doesn't slip through; specifically, in the tick function
change if (!pointerInteracting.current) { phiRef.current += 0.005; } to if
(pointerInteracting.current == null) { phiRef.current += 0.005; } so
auto-rotation only runs when pointerInteracting is truly unset, leaving symbols:
pointerInteracting, phiRef, tick, requestAnimationFrame, and globe.update
unchanged.
- Around line 184-198: The portals are being keyed on the child <div> instead of
on the portal itself, which prevents proper reconciliation; update the map over
anchorLabels so the key is passed as the third argument to createPortal (use
label.markerId as the key) and remove the key prop from the div element; modify
the call around createPortal(...) in the block that uses globeHost,
anchorLabels, createPortal, and anchorBadgeStyle so the portal receives the key
and the child div no longer has a key attribute.
In `@src/components/templates/NewsCard.tsx`:
- Line 39: The Tailwind v4 utility group-hover:bg-opacity-10 is removed; update
the div in NewsCard (the element with class 'group-hover:bg-opacity-10 absolute
top-0 left-0 h-full w-full group-hover:bg-white') to use the slash-based opacity
modifier by replacing the combined classes with a single color/opacity class
(e.g., use group-hover:bg-white/10) and remove the deprecated bg-opacity-*
token, and scan for any other usages of bg-opacity-*, text-opacity-* or
border-opacity-* and convert them to the color/opacity syntax (color/opacity) to
match Tailwind v4.
In `@src/components/ui/Accordion.tsx`:
- Line 14: The Accordion component is hardcoding a light border class in the JSX
where className is set (className={clsx('border-b border-gray-200',
className)}); change that to use the semantic/tokenized border class or omit the
explicit color so themes can control it — e.g., replace 'border-gray-200' with
'border-border' or just use 'border-b' and let the incoming/class-level styles
determine color; update the same className expression in Accordion.tsx
accordingly.
In `@src/styles/globals.css`:
- Around line 1-4: Stylelint is flagging Tailwind v4 at-rules (`@config` and
`@plugin`) as unknown; update your Stylelint config (.stylelintrc.json) to allow
these by adding "at-rule-no-unknown": [true, { "ignoreAtRules": ["config",
"plugin", "tailwind", "apply", "variants", "responsive", "screen"] }] or
alternatively switch to a Tailwind-aware preset; edit the at-rule-no-unknown
rule (or replace with a preset) so `@config` and `@plugin` used in
src/styles/globals.css are recognized.
---
Nitpick comments:
In `@eslint.config.mjs`:
- Around line 40-45: The listed stylistic ESLint rules ('no-multi-spaces',
'object-curly-spacing', and 'quotes') conflict with Prettier because this custom
block runs after eslint-config-prettier and prettierRecommended; remove or
disable those three rules (or set them to 'off') so Prettier controls
formatting, leaving only non-formatting/semantic rules (e.g., keep
'@typescript-eslint/explicit-module-boundary-types' or
'@typescript-eslint/no-unused-vars' as appropriate) in the same config block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 541952bf-2f55-4a03-84f1-27246e9c1444
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (119)
.eslintignore.eslintrc.jseslint.config.mjsnext.config.jspackage.jsonpostcss.config.jspublic/locales/de/company.jsonpublic/locales/de/contact.jsonpublic/locales/de/distribution.jsonpublic/locales/de/downloads.jsonpublic/locales/de/home.jsonpublic/locales/de/imprint.jsonpublic/locales/de/news.jsonpublic/locales/de/notFound.jsonpublic/locales/de/privacy.jsonpublic/locales/de/production.jsonpublic/locales/de/repair.jsonpublic/locales/de/services.jsonpublic/locales/de/termsAndConditions.jsonpublic/locales/en/company.jsonpublic/locales/en/contact.jsonpublic/locales/en/distribution.jsonpublic/locales/en/downloads.jsonpublic/locales/en/home.jsonpublic/locales/en/imprint.jsonpublic/locales/en/news.jsonpublic/locales/en/notFound.jsonpublic/locales/en/privacy.jsonpublic/locales/en/production.jsonpublic/locales/en/repair.jsonpublic/locales/en/services.jsonpublic/locales/en/termsAndConditions.jsonsrc/app/[locale]/agb/page.tsxsrc/app/[locale]/cookie-richtlinie/page.tsxsrc/app/[locale]/datenschutz/page.tsxsrc/app/[locale]/downloads/page.tsxsrc/app/[locale]/impressum/page.tsxsrc/app/[locale]/kontakt/page.tsxsrc/app/[locale]/leistungen/page.tsxsrc/app/[locale]/leistungen/produktion/page.tsxsrc/app/[locale]/leistungen/reparatur/page.tsxsrc/app/[locale]/leistungen/vertrieb/page.tsxsrc/app/[locale]/newsroom/[slug]/page.tsxsrc/app/[locale]/newsroom/page.tsxsrc/app/[locale]/not-found.tsxsrc/app/[locale]/page.tsxsrc/app/[locale]/unternehmen/page.tsxsrc/app/layout.tsxsrc/components/__tests__/Collapsible.test.tsxsrc/components/__tests__/CookieConsentConditional.test.tsxsrc/components/__tests__/TextReveal.test.tsxsrc/components/helpers/ConsentProvider.tsxsrc/components/helpers/consent/ConsentCategoryToggles.tsxsrc/components/helpers/consent/ConsentSurfaces.tsxsrc/components/layout/Footer.tsxsrc/components/layout/InfoBar.tsxsrc/components/layout/header/DesktopNav.tsxsrc/components/layout/header/Header.tsxsrc/components/layout/header/LeistungenMegaMenu.tsxsrc/components/layout/header/MobileNavDrawer.tsxsrc/components/templates/Bento.tsxsrc/components/templates/CallToAction.tsxsrc/components/templates/CompanyView.tsxsrc/components/templates/ContactDecorators.tsxsrc/components/templates/ContactForm.tsxsrc/components/templates/ContactInfo.tsxsrc/components/templates/ContactView.tsxsrc/components/templates/CookieControlCenter.tsxsrc/components/templates/CookiePolicyVendorList.tsxsrc/components/templates/DistributionConsult.tsxsrc/components/templates/DistributionIntro.tsxsrc/components/templates/DistributionOptic.tsxsrc/components/templates/DistributionProducts.tsxsrc/components/templates/DownloadCenter.tsxsrc/components/templates/Features.tsxsrc/components/templates/Globe.tsxsrc/components/templates/Hero.tsxsrc/components/templates/Marquee.tsxsrc/components/templates/NewsArticle.tsxsrc/components/templates/NewsCard.tsxsrc/components/templates/NewsSlider.tsxsrc/components/templates/NotFound.tsxsrc/components/templates/PrivacyContent.tsxsrc/components/templates/ProductionIntro.tsxsrc/components/templates/ProductionTiles.tsxsrc/components/templates/ProduktionLeistungenView.tsxsrc/components/templates/RepairSlideshow.tsxsrc/components/templates/ReparaturLeistungenView.tsxsrc/components/templates/ServicePageTiles.tsxsrc/components/templates/ServicesView.tsxsrc/components/templates/StickyScroll/StickyScroll.tsxsrc/components/templates/StickyScroll/StickyScrollTitle.tsxsrc/components/templates/TextReveal.tsxsrc/components/templates/distributionGlobeConfig.tssrc/components/ui/Accordion.tsxsrc/components/ui/Badges/AnimatedBadge.tsxsrc/components/ui/Badges/Badge.tsxsrc/components/ui/Buttons/Button.tsxsrc/components/ui/Buttons/IconButton.tsxsrc/components/ui/Buttons/MobileMenuButton.tsxsrc/components/ui/Buttons/SliderButton.tsxsrc/components/ui/Buttons/TextButton.tsxsrc/components/ui/Checkbox.tsxsrc/components/ui/Links/ButtonLink.tsxsrc/components/ui/Links/IconLink.tsxsrc/components/ui/Links/PrimaryLink.tsxsrc/components/ui/Links/UnderlineLink.tsxsrc/components/ui/RadixCheckbox.tsxsrc/components/ui/Switch.tsxsrc/components/ui/Typography/Title.tsxsrc/constants/services-page-hero.tssrc/lib/__tests__/helper.test.tssrc/lib/google-analytics.tssrc/lib/i18n-testing.tssrc/lib/site-page-metadata.tssrc/styles/globals.csssrc/types/globals.d.tstailwind.config.tstsconfig.json
💤 Files with no reviewable changes (9)
- .eslintignore
- src/components/tests/Collapsible.test.tsx
- src/components/helpers/ConsentProvider.tsx
- .eslintrc.js
- src/components/tests/TextReveal.test.tsx
- tailwind.config.ts
- next.config.js
- src/components/tests/CookieConsentConditional.test.tsx
- src/components/templates/TextReveal.tsx
| globalIgnores([ | ||
| '**/node_modules/**', | ||
| '.next/**', | ||
| 'out/**', | ||
| 'build/**', | ||
| 'coverage/**', | ||
| 'public/**', | ||
| 'next-env.d.ts', | ||
| '*.config.js', | ||
| 'next-sitemap.config.js', | ||
| ]), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
fd -H -t f -E node_modules -E .next '\.config\.(js|cjs|mjs|ts)$'Repository: dmnktoe/duecker-medizintechnik
Length of output: 272
Expand globalIgnores pattern to cover config files with non-.js extensions.
Config files with .ts and .mjs extensions exist in the repo (tailwind.config.ts, sentry.client.config.ts, sentry.edge.config.ts, sentry.server.config.ts, eslint.config.mjs), but the pattern '*.config.js' won't match them. Use **/*.config.{js,cjs,mjs,ts} to ensure all config files are excluded from linting.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eslint.config.mjs` around lines 10 - 20, globalIgnores pattern currently only
excludes '*.config.js' so config files with other extensions are still linted;
update the pattern passed to globalIgnores (the globalIgnores([...]) call) to
include other config file extensions such as .cjs, .mjs, and .ts by replacing
the single '*.config.js' entry with a glob like '**/*.config.{js,cjs,mjs,ts}' so
tailwind.config.ts, sentry.*.config.ts, eslint.config.mjs, etc. are ignored by
ESLint.
| "description": "Legal notice and provider information for Dücker Medizintechnik in Melsungen, Germany (German legal requirements).", | ||
| "title": "Legal notice — provider details and disclaimers" |
There was a problem hiding this comment.
Minor: em dash in <title> may render inconsistently.
The em dash (—) in "Legal notice — provider details and disclaimers" is fine semantically but some SERP snippets/social cards prefer a simple hyphen or colon for consistency with other page titles in this PR (which use : — see company.json). Consider aligning the separator style across locales for a uniform SEO presentation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@public/locales/en/imprint.json` around lines 47 - 48, Update the "title"
value in the imprint locale entry to use the same separator style as other page
titles (replace the em dash in the "title" string "Legal notice — provider
details and disclaimers" with a colon or hyphen to match company.json); locate
the "title" key in public/locales/en/imprint.json and change the separator
character only, keeping the rest of the text identical so localization keys
remain consistent.
| className={clsxm( | ||
| 'order-first items-center justify-center bg-gray-100 p-2 align-middle lg:order-last lg:p-3', | ||
| 'focus:outline-dashed focus:outline-0 focus:outline-offset-4 focus:outline-gray-300', | ||
| 'focus:outline-0 focus:outline-offset-4 focus:outline-gray-300 focus:outline-dashed', |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Tailwind CSS v4 outline utilities: does outline-0disableoutline-dashed?
💡 Result:
No, outline-0 does not disable outline-dashed in Tailwind CSS v4. Outline utilities are independent and target different CSS properties: outline-0 sets outline-width: 0px (from v3 docs, and v4 supports arbitrary/small widths via outline-[] or spacing scale), while outline-dashed sets outline-style: dashed. A zero-width outline with dashed style renders nothing visible, but the style is still applied and not disabled—other utilities like outline-offset-2 or outline-{color} would still function. Tailwind v4 uses CSS variables like --tw-outline-style (default solid) for composition, so later classes override earlier ones without disabling unrelated properties. Examples in official docs combine width (outline-2), style (outline-dashed), offset, and color without conflict.
Citations:
- 1: https://tailwindcss.com/docs/outline-style
- 2: https://tailwindcss.com/docs/outline-width
- 3: https://v3.tailwindcss.com/docs/outline-width
- 4: Replace
outline-nonewithoutline-hidden, add newoutline-nonetailwindlabs/tailwindcss#14926 - 5: [v4] :focus-visible no longer overrides default outline for some reason tailwindlabs/tailwindcss#15152
- 6:
outline-hiddenonly applies transparent outline whenforced-colorsis active? tailwindlabs/tailwindcss#16926 - 7: v3 -> v4 upgrade tool should replace
outlinewithoutline-solidtailwindlabs/tailwindcss#15861
🏁 Script executed:
# Check if the file exists and read the relevant section
if [ -f "src/components/layout/Footer.tsx" ]; then
echo "=== File exists, checking line 161 context ==="
sed -n '150,170p' src/components/layout/Footer.tsx
else
echo "File not found, checking for Footer files"
find . -name "Footer.tsx" -o -name "Footer.ts" -o -name "Footer.jsx" -o -name "Footer.js" 2>/dev/null | head -20
fiRepository: dmnktoe/duecker-medizintechnik
Length of output: 1037
Remove focus:outline-0 — it creates an invisible focus ring for keyboard users.
focus:outline-0 sets the outline width to 0, making the dashed outline (with offset and color) invisible on focus. This is a keyboard accessibility issue for the language picker. Replace with focus:outline-2 to render a visible dashed focus indicator:
Suggested fix
- 'focus:outline-0 focus:outline-offset-4 focus:outline-gray-300 focus:outline-dashed',
+ 'focus:outline-2 focus:outline-offset-4 focus:outline-gray-300 focus:outline-dashed',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'focus:outline-0 focus:outline-offset-4 focus:outline-gray-300 focus:outline-dashed', | |
| 'focus:outline-2 focus:outline-offset-4 focus:outline-gray-300 focus:outline-dashed', |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/layout/Footer.tsx` at line 161, In the Footer component's
language picker element (in src/components/layout/Footer.tsx) replace the
Tailwind class 'focus:outline-0' with 'focus:outline-2' so the focus styling
reads 'focus:outline-2 focus:outline-offset-4 focus:outline-gray-300
focus:outline-dashed'; update the class string on the language picker/select
element in the Footer component to ensure a visible dashed focus ring for
keyboard users.
| {globeHost && anchorLabels?.length | ||
| ? anchorLabels.map((label) => | ||
| createPortal( | ||
| <div | ||
| key={label.markerId} | ||
| style={anchorBadgeStyle(label.markerId)} | ||
| className={clsxm( | ||
| 'border-primary-300/40 bg-primary-950/80 text-primary-50 inline-block rounded-full border px-2.5 py-1 text-center text-[10px] leading-tight font-semibold whitespace-nowrap shadow-lg backdrop-blur-md sm:px-3 sm:text-xs', | ||
| )} | ||
| > | ||
| {label.children} | ||
| </div>, | ||
| globeHost, | ||
| ), | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's verify the file exists and check the code at those lines
head -198 src/components/templates/Globe.tsx | tail -30Repository: dmnktoe/duecker-medizintechnik
Length of output: 1269
🌐 Web query:
React createPortal API signature third argument key parameter
💡 Result:
The React createPortal API signature is createPortal(children, domNode, key?). The third argument is an optional key parameter, described as "optional key: A unique string or number to be used as the portal's key." This key helps React identify the portal for reconciliation purposes when multiple portals are rendered in the same parent component.
Citations:
- 1: https://react.dev/reference/react-dom/createPortal
- 2: https://beta.reactjs.org/reference/react-dom/createPortal
- 3: https://it.react.dev/reference/react-dom/createPortal
- 4: https://refine.dev/blog/react-createportal/
Move the key from the child element to createPortal's third argument.
When mapping portals, the key must be passed as createPortal's third argument, not on the child element. Per React's official API reference, the signature is createPortal(children, domNode, key?), and the key is used for proper portal reconciliation when rendering multiple portals.
♻️ Proposed fix
? anchorLabels.map((label) =>
createPortal(
<div
- key={label.markerId}
style={anchorBadgeStyle(label.markerId)}
className={clsxm(
'border-primary-300/40 bg-primary-950/80 text-primary-50 inline-block rounded-full border px-2.5 py-1 text-center text-[10px] leading-tight font-semibold whitespace-nowrap shadow-lg backdrop-blur-md sm:px-3 sm:text-xs',
)}
>
{label.children}
</div>,
globeHost,
+ label.markerId,
),
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {globeHost && anchorLabels?.length | |
| ? anchorLabels.map((label) => | |
| createPortal( | |
| <div | |
| key={label.markerId} | |
| style={anchorBadgeStyle(label.markerId)} | |
| className={clsxm( | |
| 'border-primary-300/40 bg-primary-950/80 text-primary-50 inline-block rounded-full border px-2.5 py-1 text-center text-[10px] leading-tight font-semibold whitespace-nowrap shadow-lg backdrop-blur-md sm:px-3 sm:text-xs', | |
| )} | |
| > | |
| {label.children} | |
| </div>, | |
| globeHost, | |
| ), | |
| ) | |
| {globeHost && anchorLabels?.length | |
| ? anchorLabels.map((label) => | |
| createPortal( | |
| <div | |
| style={anchorBadgeStyle(label.markerId)} | |
| className={clsxm( | |
| 'border-primary-300/40 bg-primary-950/80 text-primary-50 inline-block rounded-full border px-2.5 py-1 text-center text-[10px] leading-tight font-semibold whitespace-nowrap shadow-lg backdrop-blur-md sm:px-3 sm:text-xs', | |
| )} | |
| > | |
| {label.children} | |
| </div>, | |
| globeHost, | |
| label.markerId, | |
| ), | |
| ) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/templates/Globe.tsx` around lines 184 - 198, The portals are
being keyed on the child <div> instead of on the portal itself, which prevents
proper reconciliation; update the map over anchorLabels so the key is passed as
the third argument to createPortal (use label.markerId as the key) and remove
the key prop from the div element; modify the call around createPortal(...) in
the block that uses globeHost, anchorLabels, createPortal, and anchorBadgeStyle
so the portal receives the key and the child div no longer has a key attribute.
![Screenshot of /[locale]/agb](https://images.weserv.nl?url=https://sjc.microlink.io/pqvOcDHSm9AOptwKGezw-adFUefurLBn95yzREi2RyXkoCIqxlKY2iASDa2MAnitJJ0XU20Q_zMGNGkTRLXvuQ.png&w=600)
![Screenshot of /[locale]/cookie-richtlinie](https://images.weserv.nl?url=https://sjc.microlink.io/sT4-IhgPnW4kvgTt70_yu6p3TlwcCMtiyH73WXzmylVlmqdQH0itLwC9xPNVEooxno-Y7-5v-PtpvbDoLai5fA.png&w=600)
![Screenshot of /[locale]/datenschutz](https://images.weserv.nl?url=https://sjc.microlink.io/to3Zm7A989-oxSKYypgKNl1DQwisZ7r3ppANtvC-_WZzskajBQ8CmCdDqJmhoDXSaKoT4KSda2lP6bqbYhz81A.png&w=600)
![Screenshot of /[locale]/downloads](https://images.weserv.nl?url=https://sjc.microlink.io/Yq9HVXQesZnI-G8JNV2-g9FWsNQdxu63Y-R2ULnYFZ0igz0jIhRDXXgBm9oR10Z5_F8ip1X89EhfpDOkWJzlZg.png&w=600)
![Screenshot of /[locale]/impressum](https://images.weserv.nl?url=https://sjc.microlink.io/ilKgo-gexSgUdrS7_PkX0mOHdODejCpPrlL_NJpw6Lv0dj3JhG-Ds_9H-wKISIXv1te3Y0bgNZ75dpK-yaLZNg.png&w=600)
![Screenshot of /[locale]/kontakt](https://images.weserv.nl?url=https://sjc.microlink.io/13xVQRv1Tb9xlLoSiOMsxdDuhSj0aRWO8S4NrRoWypOiToBd11-X4ybrhtm3QG9rhOHUz5tiEItR23qNeY6dWA.png&w=600)
Description & Technical Solution
Describe problems, if any, clearly and concisely.
Summarize the impact to the system.
Please also include relevant motivation and context.
Please include a summary of the technical solution and how it solves the problem.
Checklist
Screenshots
Provide screenshots or videos of the changes made if any.
Summary by CodeRabbit
New Features
Improvements
Removed