fix(packages): client-side nav, sidebar button variants, typed icons, and ESM compat#50
fix(packages): client-side nav, sidebar button variants, typed icons, and ESM compat#50zrosenbauer merged 9 commits intomainfrom
Conversation
…d config - Rename all CSS classes to use `zp-` namespace with BEM conventions - Add HomeConfig, HomeGridConfig, TruncateConfig types and schemas - Support configurable columns and line-clamp truncation for home grids - Update feature cards, workspace cards, section cards, and tech tags Co-Authored-By: Claude <noreply@anthropic.com>
… and ESM compat
- Use Link from @rspress/core/runtime instead of <a> for client-side
navigation in card.tsx and sidebar-links.tsx
- Add configurable style (brand/alt/ghost) and shape (square/rounded/circle)
to sidebar links with full CSS variants
- Type IconId as template literal `${IconPrefix}:${string}` restricting to
installed @iconify-json sets, fix Feature.icon and ZpressConfig.icon types
- Fix invalid icon references in kitchen-sink example (devicon:hono → logos:hono,
devicon:stripe → logos:stripe, pixelarticons:integration → mdi:puzzle)
- Add ESM compat patches for rspress plugins (missing .js ext, __dirname shim)
- Add require shim for Node 24 CJS compat in CLI entry
- Override @rsbuild/core to 2.0.0-beta.9 to fix bare require() in bundled code
- Bump deps: turbo, @kidd-cli/core, @rspress/core catalog
Co-Authored-By: Claude <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: e8a7c07 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds typed IconId and top-level config for home/socialLinks/footer; renames many UI classes to Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Layout
participant SiteFooter
participant SocialLinks
Client->>Layout: render page
Layout->>SiteFooter: request footer (via useZpress)
SiteFooter->>SiteFooter: read zpressFooter & socials flag
alt footer present
SiteFooter->>SocialLinks: render socials (if enabled)
SocialLinks-->>SiteFooter: social items
SiteFooter-->>Layout: footer markup
else no footer
SiteFooter-->>Layout: null
end
Layout-->>Client: final rendered page
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (6)
packages/ui/src/config.ts (1)
288-297: Prefer a shared sidebar link type here.This inline return type is now a second copy of the sidebar contract, alongside
packages/ui/src/theme/hooks/use-zpress.ts, Lines 11-17. Reusing a shared type from@zpress/configwould keepstyle/shapeand icon typing from drifting.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/config.ts` around lines 288 - 297, The inline return type for resolveSidebarLinks duplicates the sidebar link contract; replace it with the shared type from `@zpress/config` (the SidebarLink or equivalent exported type) by importing that type and using it as the function return type for resolveSidebarLinks, ensuring the icon, style and shape fields match the canonical type used in use-zpress.ts so typings stay consistent across packages.packages/ui/src/theme/components/home/feature.tsx (1)
32-32: SwitchrenderFeatureto an object parameter.The helper now takes three positional arguments, which makes the call site harder to scan and misses the repo TS convention.
As per coding guidelines, "Use object parameters for functions with 2+ parameters and include explicit return types."♻️ Suggested refactor
- (items) => <FeatureGrid>{items.map((f, i) => renderFeature(f, i, gridConfig))}</FeatureGrid> + (items) => + <FeatureGrid> + {items.map((feature, index) => renderFeature({ feature, index, gridConfig }))} + </FeatureGrid> ) .otherwise(() => null) } @@ -function renderFeature( - feature: FeatureItem, - index: number, - gridConfig: HomeGridConfig | undefined -): React.ReactElement { +function renderFeature(params: { + readonly feature: FeatureItem + readonly index: number + readonly gridConfig: HomeGridConfig | undefined +}): React.ReactElement { + const { feature, index, gridConfig } = paramsAlso applies to: 51-55
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/theme/components/home/feature.tsx` at line 32, The helper renderFeature currently accepts three positional args (feature, index, gridConfig); refactor it to accept a single object parameter (e.g., { feature, index, gridConfig }) and add an explicit return type (e.g., JSX.Element) in its declaration, then update all call sites including the FeatureGrid map (the arrow at line showing (items) => <FeatureGrid>{items.map((f, i) => renderFeature(f, i, gridConfig))}</FeatureGrid>) and the other occurrences around lines 51-55 to call renderFeature({ feature: f, index: i, gridConfig }); ensure imports/types reflect the new shape if needed.packages/ui/src/theme/components/home/workspaces.tsx (1)
17-18: Prefer optional chaining for cleaner conditionals.The nested
&&chains can be simplified with optional chaining for improved readability:♻️ Suggested simplification
- const { workspaces, home } = useZpress() - const gridConfig = home && home.workspaces + const { workspaces, home } = useZpress() + const gridConfig = home?.workspaces- const titleLines = gridConfig && gridConfig.truncate && gridConfig.truncate.title - const descLines = gridConfig && gridConfig.truncate && gridConfig.truncate.description + const titleLines = gridConfig?.truncate?.title + const descLines = gridConfig?.truncate?.description- columns={gridConfig && gridConfig.columns ? gridConfig.columns : undefined} + columns={gridConfig?.columns}Also applies to: 49-50, 57-57
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/theme/components/home/workspaces.tsx` around lines 17 - 18, Replace the boolean-AND style null checks with optional chaining to simplify access to nested properties: where the code currently does `const { workspaces, home } = useZpress(); const gridConfig = home && home.workspaces`, change to using `home?.workspaces` (or directly access via `useZpress().home?.workspaces`) and apply the same replacement for the other occurrences referenced around lines 49-50 and 57 (replace patterns like `foo && foo.bar` with `foo?.bar`), ensuring you update uses in functions/components that reference `gridConfig`, `workspaces`, or `home` accordingly so null/undefined safety is preserved.packages/ui/src/theme/components/home/feature-card.tsx (1)
111-116: Consider extracting shared clamping utilities.The
clampClassandclampStylehelpers are duplicated verbatim inworkspaces/card.tsx. Consider extracting them to a shared utility (e.g.,../shared/clamp-utils.ts) to reduce duplication.Also applies to: 125-130
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/theme/components/home/feature-card.tsx` around lines 111 - 116, Extract the duplicated helpers clampClass and clampStyle into a shared module (e.g., create a new ../shared/clamp-utils.ts) that exports both functions with the same signatures, then replace the local implementations in feature-card.tsx (functions clampClass and clampStyle) and in workspaces/card.tsx with imports from that shared module; ensure you export the functions (named exports) and update the import statements and any relative paths so both files use the single shared implementation.packages/ui/src/theme/components/sidebar/sidebar-links.tsx (1)
70-72: Consider handling protocol-relative URLs.The
isExternalcheck only matcheshttp://andhttps://prefixes. Protocol-relative URLs like//example.com/pathwould be treated as internal routes, which may cause unexpected behavior with the<Link>component.♻️ Optional enhancement
function isExternal(link: string): boolean { - return link.startsWith('http://') || link.startsWith('https://') + return link.startsWith('http://') || link.startsWith('https://') || link.startsWith('//') }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/theme/components/sidebar/sidebar-links.tsx` around lines 70 - 72, The isExternal(link: string) helper currently only checks for 'http://' and 'https://', so protocol-relative URLs like '//example.com/...' are treated as internal; update the isExternal function to also return true for links that start with '//' (and consider trimming the input and guarding against empty/null strings) so protocol-relative URLs are correctly classified as external by components that use isExternal.packages/config/src/types.ts (1)
10-27: CentralizeIconPrefix/IconIdgeneration.
packages/core/src/icons.generated.tsalready emits the same union from the installed icon sets. Re-declaring it here creates a second public source of truth, so@zpress/configand@zpress/corecan drift on the next icon-package change. Prefer re-exporting or generating both from the same source.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/config/src/types.ts` around lines 10 - 27, Replace the local duplicate type definitions by reusing the generated types: remove the IconPrefix and IconId declarations in types.ts and import/re-export them from the generated icons module (icons.generated.ts) used by core so there is a single source of truth; update any references in this module to use the re-exported IconPrefix and IconId symbols to avoid drift when icon packages change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@package.json`:
- Around line 71-73: The package.json currently pins the dependency via the
"overrides" entry for "@rsbuild/core" to "2.0.0-beta.9"; update the repo before
release by either (a) reverting the override to a known stable version (e.g.,
"1.7.3") in the "overrides" block or (b) adding a documented stability plan:
create/update the release checklist/CONTRIBUTING note referencing the
"overrides" key and "@rsbuild/core" so that once a stable 2.0.0 is published we
replace "2.0.0-beta.9" with "2.0.0" and run full compatibility tests; implement
one of these two actions and commit the change along with a short commit message
referencing the "overrides" entry and "@rsbuild/core".
In `@packages/ui/src/theme/components/home/feature.tsx`:
- Around line 19-20: The HomeGridConfig.columns value is never used because
gridConfig (from useZpress().home.features) is only used for truncation and
FeatureGrid (in feature-card.tsx) does not accept or apply any layout props;
update the code so the grid layout is driven by HomeGridConfig.columns: add a
prop (e.g., columns or gridConfig) to the FeatureGrid component and consume it
when rendering the grid (apply to the Grid/SimpleGrid component via
templateColumns/columns or compute responsive column counts), then pass the
gridConfig (or gridConfig.columns) from where FeatureGrid is instantiated (the
file with const { home } = useZpress() and gridConfig) so the
HomeGridConfig.columns field actually controls the rendered layout.
In `@packages/ui/src/theme/components/sidebar/sidebar-links.css`:
- Around line 90-96: The circle variant CSS (.zp-sidebar-link--circle) forces a
fixed 36×36px icon-only layout but sidebar-links.tsx still renders the label
span (zp-sidebar-link-text) unconditionally; update the implementation so the
circle variant is truly icon-only: in sidebar-links.tsx detect when the link has
class .zp-sidebar-link--circle and require/provide an icon and move the visible
label out of the DOM while exposing it via aria-label (or title) on the
interactive element (use item.text for the aria-label), or alternatively remove
the fixed width/height from .zp-sidebar-link--circle so the container can grow
to accommodate zp-sidebar-link-text; choose one approach and apply it
consistently (adjust CSS .zp-sidebar-link--circle and the render logic around
zp-sidebar-link-text and item.text accordingly).
In `@packages/ui/src/theme/components/workspaces/grid.tsx`:
- Around line 61-66: columnsStyle currently uses a truthiness check (if
(columns)) which treats columns=0 as falsy and skips setting the CSS variable;
update the function (columnsStyle) to check explicitly for undefined (e.g., if
(columns !== undefined)) so a value of 0 will be converted to String(columns)
and the '--zp-workspace-cols' CSS variable is set accordingly, otherwise return
undefined.
In `@packages/ui/src/theme/styles/overrides/home.css`:
- Around line 117-122: The Stylelint rule failure for .zp-feature-grid is caused
by missing an empty line before the first non-custom-property declaration;
update the .zp-feature-grid block (selector .zp-feature-grid) so there is a
blank line between the custom property declaration (--feature-grid-gap: 12px;)
and the next declaration (display: flex;) to satisfy
declaration-empty-line-before.
- Around line 135-166: The two-column width calculation for
.zp-feature-grid__item--span-2, .zp-feature-grid__item--span-4, and
.zp-feature-grid__item--span-6 uses calc(50% - var(--feature-grid-gap)) which
double-subtracts the gap; change those 2-column cases to calc((100% -
var(--feature-grid-gap)) / 2) so the single gap between columns is accounted for
correctly in the media queries where 2-column layout appears (look for the
selectors .zp-feature-grid__item--span-2, .zp-feature-grid__item--span-4,
.zp-feature-grid__item--span-6 in the CSS blocks).
In `@packages/ui/src/theme/styles/themes/arcade-fx.css`:
- Around line 65-73: Add keyboard-focus support by mirroring the hover rules to
focus-visible: update the selectors that target html[data-zp-theme='arcade']
.zp-card:hover and html[data-zp-theme='arcade'] .zp-section-card:hover
(including their ::before pseudo-element rules) to also include :focus-visible
(e.g., .zp-card:focus-visible and .zp-section-card:focus-visible) so the same
opacity, animation (arcade-border-spin), and glow/shadow styles are applied when
cards receive keyboard focus; ensure both the ::before border-spin rule and the
glow-shadow rule use the identical declarations for :hover and :focus-visible to
provide equivalent affordance.
---
Nitpick comments:
In `@packages/config/src/types.ts`:
- Around line 10-27: Replace the local duplicate type definitions by reusing the
generated types: remove the IconPrefix and IconId declarations in types.ts and
import/re-export them from the generated icons module (icons.generated.ts) used
by core so there is a single source of truth; update any references in this
module to use the re-exported IconPrefix and IconId symbols to avoid drift when
icon packages change.
In `@packages/ui/src/config.ts`:
- Around line 288-297: The inline return type for resolveSidebarLinks duplicates
the sidebar link contract; replace it with the shared type from `@zpress/config`
(the SidebarLink or equivalent exported type) by importing that type and using
it as the function return type for resolveSidebarLinks, ensuring the icon, style
and shape fields match the canonical type used in use-zpress.ts so typings stay
consistent across packages.
In `@packages/ui/src/theme/components/home/feature-card.tsx`:
- Around line 111-116: Extract the duplicated helpers clampClass and clampStyle
into a shared module (e.g., create a new ../shared/clamp-utils.ts) that exports
both functions with the same signatures, then replace the local implementations
in feature-card.tsx (functions clampClass and clampStyle) and in
workspaces/card.tsx with imports from that shared module; ensure you export the
functions (named exports) and update the import statements and any relative
paths so both files use the single shared implementation.
In `@packages/ui/src/theme/components/home/feature.tsx`:
- Line 32: The helper renderFeature currently accepts three positional args
(feature, index, gridConfig); refactor it to accept a single object parameter
(e.g., { feature, index, gridConfig }) and add an explicit return type (e.g.,
JSX.Element) in its declaration, then update all call sites including the
FeatureGrid map (the arrow at line showing (items) =>
<FeatureGrid>{items.map((f, i) => renderFeature(f, i,
gridConfig))}</FeatureGrid>) and the other occurrences around lines 51-55 to
call renderFeature({ feature: f, index: i, gridConfig }); ensure imports/types
reflect the new shape if needed.
In `@packages/ui/src/theme/components/home/workspaces.tsx`:
- Around line 17-18: Replace the boolean-AND style null checks with optional
chaining to simplify access to nested properties: where the code currently does
`const { workspaces, home } = useZpress(); const gridConfig = home &&
home.workspaces`, change to using `home?.workspaces` (or directly access via
`useZpress().home?.workspaces`) and apply the same replacement for the other
occurrences referenced around lines 49-50 and 57 (replace patterns like `foo &&
foo.bar` with `foo?.bar`), ensuring you update uses in functions/components that
reference `gridConfig`, `workspaces`, or `home` accordingly so null/undefined
safety is preserved.
In `@packages/ui/src/theme/components/sidebar/sidebar-links.tsx`:
- Around line 70-72: The isExternal(link: string) helper currently only checks
for 'http://' and 'https://', so protocol-relative URLs like '//example.com/...'
are treated as internal; update the isExternal function to also return true for
links that start with '//' (and consider trimming the input and guarding against
empty/null strings) so protocol-relative URLs are correctly classified as
external by components that use isExternal.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 97fcd83c-4a23-4246-a270-54f28c281073
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (35)
examples/kitchen-sink/zpress.config.tspackage.jsonpackages/cli/package.jsonpackages/cli/src/index.tspackages/cli/src/shims/require.tspackages/config/schemas/schema.jsonpackages/config/src/index.tspackages/config/src/schema.tspackages/config/src/types.tspackages/core/src/sync/workspace.tspackages/ui/package.jsonpackages/ui/src/config.tspackages/ui/src/theme/components/home/feature-card.csspackages/ui/src/theme/components/home/feature-card.tsxpackages/ui/src/theme/components/home/feature.tsxpackages/ui/src/theme/components/home/workspaces.tsxpackages/ui/src/theme/components/shared/card.tsxpackages/ui/src/theme/components/shared/section-card.tsxpackages/ui/src/theme/components/shared/section-grid.tsxpackages/ui/src/theme/components/shared/tech-tag.tsxpackages/ui/src/theme/components/sidebar/sidebar-links.csspackages/ui/src/theme/components/sidebar/sidebar-links.tsxpackages/ui/src/theme/components/workspaces/card.csspackages/ui/src/theme/components/workspaces/card.tsxpackages/ui/src/theme/components/workspaces/grid.tsxpackages/ui/src/theme/hooks/use-zpress.tspackages/ui/src/theme/styles/overrides/home-card.csspackages/ui/src/theme/styles/overrides/home.csspackages/ui/src/theme/styles/overrides/section-card.csspackages/ui/src/theme/styles/themes/arcade-fx.csspatches/rspress-plugin-file-tree@1.0.4.patchpatches/rspress-plugin-mermaid@1.0.1.patchpatches/rspress-plugin-supersub@1.0.0.patchpnpm-workspace.yamlzpress.config.ts
- Add socialLinks config that passes through to Rspress nav bar (supports github, discord, x, npm, etc.) - Add footer config with optional message and copyright text, rendered via SiteFooter component in the Layout bottom slot - Increase sidebar link icon-to-text gap from 4px to 8px - Add social links and footer to kitchen-sink example and root config Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/ui/src/config.ts (1)
293-305: Consider addingreadonlymodifiers to return type properties.The inline return type properties (
text,link,icon,style,shape) lackreadonlymodifiers, while the correspondingSidebarLinkinterface inpackages/config/src/types.tsusesreadonlythroughout. For consistency with the codebase conventions:♻️ Optional: Add readonly modifiers
function resolveSidebarLinks(params: { readonly config: ZpressConfig readonly position: 'above' | 'below' }): readonly { - text: string - link: string - icon?: string | { id: string; color: string } - style?: 'brand' | 'alt' | 'ghost' - shape?: 'square' | 'rounded' | 'circle' + readonly text: string + readonly link: string + readonly icon?: string | { readonly id: string; readonly color: string } + readonly style?: 'brand' | 'alt' | 'ghost' + readonly shape?: 'square' | 'rounded' | 'circle' }[] {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/config.ts` around lines 293 - 305, The inline return type for the function that reads params.config.sidebar[params.position] lacks readonly modifiers on properties (text, link, icon, style, shape) and should match the project's readonly SidebarLink shape; update the return type to either add readonly to each property or, better, import and use the existing SidebarLink type (and return readonly SidebarLink[] or the equivalent) so the returned items (variable items) are typed consistently with SidebarLink.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/ui/src/theme/components/footer/site-footer.tsx`:
- Around line 19-34: The component currently uses match(footer) and then renders
<footer className="zp-site-footer"> even when f.message and f.copyright are both
undefined, producing an empty element; update the SiteFooter rendering so that
if footer is falsy or both f.message and f.copyright are falsy it returns null
(i.e., short-circuit before rendering the <footer>), and only render the footer
when at least one of f.message or f.copyright exists, keeping the existing match
checks (match(f.message) and match(f.copyright)) or replacing them with simple
conditional checks as needed.
---
Nitpick comments:
In `@packages/ui/src/config.ts`:
- Around line 293-305: The inline return type for the function that reads
params.config.sidebar[params.position] lacks readonly modifiers on properties
(text, link, icon, style, shape) and should match the project's readonly
SidebarLink shape; update the return type to either add readonly to each
property or, better, import and use the existing SidebarLink type (and return
readonly SidebarLink[] or the equivalent) so the returned items (variable items)
are typed consistently with SidebarLink.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 27ecfd9b-7121-404e-8cc3-76ef447de2cd
📒 Files selected for processing (11)
examples/kitchen-sink/zpress.config.tspackages/config/src/index.tspackages/config/src/schema.tspackages/config/src/types.tspackages/ui/src/config.tspackages/ui/src/theme/components/footer/site-footer.csspackages/ui/src/theme/components/footer/site-footer.tsxpackages/ui/src/theme/components/nav/layout.tsxpackages/ui/src/theme/components/sidebar/sidebar-links.csspackages/ui/src/theme/hooks/use-zpress.tszpress.config.ts
✅ Files skipped from review due to trivial changes (2)
- packages/ui/src/theme/components/nav/layout.tsx
- packages/ui/src/theme/components/footer/site-footer.css
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/config/src/index.ts
- examples/kitchen-sink/zpress.config.ts
- zpress.config.ts
- packages/config/src/schema.ts
- packages/ui/src/theme/components/sidebar/sidebar-links.css
The plugin uses bare `require.resolve('katex/dist/katex.min.css')` which
fails in ESM because the global require shim resolves from the CLI's
dist directory, not the plugin's location. Patch replaces it with
`createRequire(import.meta.url)` so resolution uses the plugin's own
node_modules.
Co-Authored-By: Claude <noreply@anthropic.com>
- Add `socials` boolean to FooterConfig schema and types - Render SocialLinks in site footer when socials is true - Rename themeConfig key from `footer` to `zpressFooter` to avoid collision with Rspress built-in HomeFooter - Update schema.json with socialLinks and footer definitions Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/config/src/types.ts (2)
6-27: Avoid maintaining a secondIconPrefix/IconIdsource.
packages/core/src/icons.generated.tsalready derives these from the installed Iconify sets, andpackages/config/src/index.tsalready re-exports the core types. Keeping a handwritten copy here means the config package can silently drift the next time an icon set is added or removed.♻️ Suggested refactor
+import type { + IconId as CoreIconId, + IconPrefix as CoreIconPrefix, +} from '@zpress/core' import type { ThemeConfig, ThemeName, ColorMode, ThemeColors, IconColor } from '@zpress/theme' /** * Installed Iconify icon-set prefixes. * * Must stay in sync with `@iconify-json/*` packages in root `package.json`. */ -export type IconPrefix = - | 'catppuccin' - | 'devicon' - | 'logos' - | 'material-icon-theme' - | 'mdi' - | 'pixelarticons' - | 'simple-icons' - | 'skill-icons' - | 'vscode-icons' +export type IconPrefix = CoreIconPrefix /** * Iconify icon identifier — `"prefix:name"` where prefix matches an installed set. * * `@example` `"devicon:hono"`, `"pixelarticons:device-mobile"` * `@see` https://icon-sets.iconify.design/ */ -export type IconId = `${IconPrefix}:${string}` +export type IconId = CoreIconId🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/config/src/types.ts` around lines 6 - 27, The duplicate handwritten IconPrefix and IconId definitions should be removed and replaced by importing/re-exporting the canonical types generated in core (derived from icons.generated.ts) to avoid drift; update this file to import IconPrefix and IconId from the core package's types (the same place packages/config/src/index.ts already re-exports from) and re-export them (or remove this file and rely on the existing re-export), ensuring all references use the single source of truth: IconPrefix and IconId from core.
223-228: Share sidebar variant literals instead of copying them.These unions are now duplicated here, in
packages/ui/src/config.ts, and inpackages/ui/src/theme/hooks/use-zpress.ts. Exporting aliases once will keep config, runtime plumbing, and hook types from drifting on the next variant change.♻️ Suggested refactor
+export type SidebarLinkStyle = 'brand' | 'alt' | 'ghost' +export type SidebarLinkShape = 'square' | 'rounded' | 'circle' + export interface SidebarLink { readonly text: string readonly link: string readonly icon?: IconConfig - readonly style?: 'brand' | 'alt' | 'ghost' - readonly shape?: 'square' | 'rounded' | 'circle' + readonly style?: SidebarLinkStyle + readonly shape?: SidebarLinkShape }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/config/src/types.ts` around lines 223 - 228, The literal unions for link style and shape are duplicated; instead export shared aliases (e.g., LinkStyle and LinkShape) from the central UI config module and replace the inline unions in SidebarLink with those imported types; update the other locations that currently duplicate the literals (packages that define variant types and use-zpress hook) to import the same exported LinkStyle and LinkShape so all three consumers (SidebarLink interface, runtime plumbing, and hook) reference the single source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/config/schemas/schema.json`:
- Line 89: The "icon" schema was weakened to an empty object ({}) which makes
all $ref targets (workspace icons, feature icons, and card.icon.id) accept
anything; restore validation by replacing that node with at least a string
schema (e.g., set the "icon" definition to type: "string" or a string pattern
that matches your prefix union) so all $ref consumers continue to validate as
strings rather than any type.
---
Nitpick comments:
In `@packages/config/src/types.ts`:
- Around line 6-27: The duplicate handwritten IconPrefix and IconId definitions
should be removed and replaced by importing/re-exporting the canonical types
generated in core (derived from icons.generated.ts) to avoid drift; update this
file to import IconPrefix and IconId from the core package's types (the same
place packages/config/src/index.ts already re-exports from) and re-export them
(or remove this file and rely on the existing re-export), ensuring all
references use the single source of truth: IconPrefix and IconId from core.
- Around line 223-228: The literal unions for link style and shape are
duplicated; instead export shared aliases (e.g., LinkStyle and LinkShape) from
the central UI config module and replace the inline unions in SidebarLink with
those imported types; update the other locations that currently duplicate the
literals (packages that define variant types and use-zpress hook) to import the
same exported LinkStyle and LinkShape so all three consumers (SidebarLink
interface, runtime plumbing, and hook) reference the single source of truth.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8f31cf38-29e6-46fb-98da-818561ab69f2
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (21)
docs/references/icons/colors.mdxdocs/references/icons/overview.mdxdocs/references/icons/technology/databases.mdxdocs/references/icons/technology/frameworks.mdxdocs/references/icons/technology/infrastructure.mdxdocs/references/icons/technology/integrations.mdxdocs/references/icons/technology/languages.mdxdocs/references/icons/technology/overview.mdxdocs/references/icons/technology/tooling.mdxexamples/kitchen-sink/zpress.config.tspackage.jsonpackages/config/schemas/schema.jsonpackages/config/src/schema.tspackages/config/src/types.tspackages/ui/package.jsonpackages/ui/src/config.tspackages/ui/src/theme/components/footer/site-footer.csspackages/ui/src/theme/components/footer/site-footer.tsxpackages/ui/src/theme/hooks/use-zpress.tspatches/rspress-plugin-katex@1.0.0.patchzpress.config.ts
✅ Files skipped from review due to trivial changes (8)
- docs/references/icons/technology/overview.mdx
- docs/references/icons/technology/databases.mdx
- docs/references/icons/technology/languages.mdx
- docs/references/icons/colors.mdx
- docs/references/icons/technology/tooling.mdx
- docs/references/icons/technology/frameworks.mdx
- docs/references/icons/overview.mdx
- packages/config/src/schema.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/ui/package.json
- packages/ui/src/theme/components/footer/site-footer.css
- packages/ui/src/theme/components/footer/site-footer.tsx
- examples/kitchen-sink/zpress.config.ts
- zpress.config.ts
- Add changeset for styling cleanup changes across all four packages - Suppress no-unassigned-import for ESM require shim (side-effect import) - Replace ternary with logical AND in workspace grid columns prop Co-Authored-By: Claude <noreply@anthropic.com>
- Fix columns=0 falsy check in workspace grid (use !== undefined) - Fix two-column width calc in feature grid (correct gap math) - Add empty line before display in .zp-feature-grid (stylelint) - Add :focus-visible alongside :hover for arcade card glow effects - Prevent empty footer when all fields are undefined - Hide text label on circle sidebar links, expose via aria-label - Use z.string().refine() for iconIdSchema so JSON Schema emits type:"string" instead of empty object - Regenerate schema.json Co-Authored-By: Claude <noreply@anthropic.com>
Summary
<Link>for client-side navigationstyle(brand/alt/ghost) andshape(square/rounded/circle) options to sidebar linksIconIdas${IconPrefix}:${string}template literal restricting to installed@iconify-jsonsets@rsbuild/coreon Node 24Changes
packages/ui: Replace<a>with<Link>incard.tsxandsidebar-links.tsx; add sidebar link button variant CSS and component propspackages/config: AddIconPrefixtype, changeIconIdfromstringto template literal, addstyle/shapetoSidebarLinkschema and types, fixFeature.iconandZpressConfig.icontypespackages/cli: Addrequireshim for Node 24 CJS compatpatches/: Add ESM compat patches forrspress-plugin-supersub,rspress-plugin-file-tree,rspress-plugin-mermaidpackage.json: Override@rsbuild/coretobeta.9, bumpturboexamples/kitchen-sink: Fix invalid icon names, add sidebar link variant examplespnpm-workspace.yaml: Bump@rspress/corecatalog to^2.0.6Testing
pnpm build— all 9 packages passSummary by CodeRabbit
New Features
Improvements
Bug Fixes