Skip to content

fix(packages): client-side nav, sidebar button variants, typed icons, and ESM compat#50

Merged
zrosenbauer merged 9 commits intomainfrom
fix/styling-cleanup
Mar 19, 2026
Merged

fix(packages): client-side nav, sidebar button variants, typed icons, and ESM compat#50
zrosenbauer merged 9 commits intomainfrom
fix/styling-cleanup

Conversation

@zrosenbauer
Copy link
Member

@zrosenbauer zrosenbauer commented Mar 19, 2026

Summary

  • Fix full-page reloads on card/sidebar link clicks by using React Router <Link> for client-side navigation
  • Add configurable style (brand/alt/ghost) and shape (square/rounded/circle) options to sidebar links
  • Type IconId as ${IconPrefix}:${string} template literal restricting to installed @iconify-json sets
  • Fix ESM compatibility issues with rspress plugins and @rsbuild/core on Node 24

Changes

  • packages/ui: Replace <a> with <Link> in card.tsx and sidebar-links.tsx; add sidebar link button variant CSS and component props
  • packages/config: Add IconPrefix type, change IconId from string to template literal, add style/shape to SidebarLink schema and types, fix Feature.icon and ZpressConfig.icon types
  • packages/cli: Add require shim for Node 24 CJS compat
  • patches/: Add ESM compat patches for rspress-plugin-supersub, rspress-plugin-file-tree, rspress-plugin-mermaid
  • package.json: Override @rsbuild/core to beta.9, bump turbo
  • examples/kitchen-sink: Fix invalid icon names, add sidebar link variant examples
  • pnpm-workspace.yaml: Bump @rspress/core catalog to ^2.0.6

Testing

  • pnpm build — all 9 packages pass
  • Dev server starts and responds with HTTP 200
  • Invalid icon names fixed (verified against installed icon sets)
  • TypeScript catches invalid icon prefixes at compile time

Summary by CodeRabbit

  • New Features

    • Home config: configurable feature/workspace grids (1–4 columns) with per-item title/description truncation and a default two-column layout.
    • Added social links and a site footer rendered in the layout.
    • Sidebar entries expanded with styled variants (brand/alt/ghost) and shape options (square/rounded/circle).
  • Improvements

    • Standardized icon identifiers and stricter icon validation.
    • Renamed/namespace CSS classes, revamped responsive grids, and added multi-line truncation for cards.
    • Sidebar now renders links via client-side routing when possible.
  • Bug Fixes

    • Dependency bumps and ESM/runtime packaging patches for improved stability.

zrosenbauer and others added 2 commits March 18, 2026 20:36
…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-bot
Copy link

changeset-bot bot commented Mar 19, 2026

🦋 Changeset detected

Latest commit: e8a7c07

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@zpress/ui Minor
@zpress/config Minor
@zpress/cli Patch
@zpress/core Patch
@zpress/kit Patch

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

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds typed IconId and top-level config for home/socialLinks/footer; renames many UI classes to zp-*, adds line-clamping and sidebar style/shape variants, injects a SiteFooter into layout, provides an ESM require shim for the CLI, updates dependencies/patches, and applies multiple UI/stylesheet refactors.

Changes

Cohort / File(s) Summary
Config types & schema
packages/config/src/types.ts, packages/config/src/schema.ts, packages/config/schemas/schema.json, packages/config/src/index.ts
Introduce IconPrefix/IconId typed icon system; tighten icon fields to IconId; add home, socialLinks, footer types and schema; add sidebar style/shape enums; JSON formatting changes.
UI config wiring & hooks
packages/ui/src/config.ts, packages/ui/src/theme/hooks/use-zpress.ts
Expose home/footer into theme config, add resolveHomeConfig() defaulting workspace columns, and extend sidebar link typing to include style/shape.
Home features & cards
packages/ui/src/theme/components/home/feature-card.tsx, .../feature.tsx, .../workspaces.tsx, packages/ui/src/theme/components/home/feature-card.css
Add titleLines/descriptionLines props and WebKit clamping; rename classes to .zp-*; wire grid truncation into feature/workspace rendering; remove old card-grid span CSS.
Workspaces grid & cards
packages/ui/src/theme/components/workspaces/grid.tsx, .../card.tsx, .../card.css
Add columns prop to WorkspaceGrid; add titleLines/descriptionLines to WorkspaceCard; apply --zp-workspace-cols via inline style; add truncation utilities; rename selectors to .zp-*.
Sidebar links & styling
packages/ui/src/theme/components/sidebar/sidebar-links.tsx, .../sidebar-links.css
Add style and shape options; render internal links via client Link and external links with target=_blank; introduce variant/shape CSS modifiers and spacing/transition changes.
Shared components & styles rename
packages/ui/src/theme/components/shared/*, packages/ui/src/theme/styles/overrides/*, packages/ui/src/theme/styles/themes/arcade-fx.css
Rename many selectors to zp-* across cards, section cards, tags; retarget theme hover/border effects; adjust responsive paddings and layout wrappers.
Footer & layout integration
packages/ui/src/theme/components/footer/site-footer.tsx, .../site-footer.css, packages/ui/src/theme/components/nav/layout.tsx
Add SiteFooter component and styles; read zpressFooter from theme config and inject into OriginalLayout bottom slot; render socials/message/copyright conditionally.
CLI ESM shim & CLI entry
packages/cli/src/shims/require.ts, packages/cli/src/index.ts, packages/cli/package.json
Add side-effect ESM shim setting globalThis.require via createRequire(import.meta.url) and import it at CLI entry; bump @kidd-cli/core version.
Dependency, pnpm & patches
package.json, packages/ui/package.json, pnpm-workspace.yaml, patches/*
Bump iconify/devicon and turbo; add pnpm patchedDependencies and overrides (@rsbuild/core); workspace range update; add patches fixing ESM __dirname, explicit .js imports, and KaTeX resolution.
Examples & root config updates
examples/kitchen-sink/zpress.config.ts, zpress.config.ts
Add/adjust top-level home truncate/columns, expand sidebar.above/below entries with style/shape, update icon ids, and add socialLinks + footer.
Minor render/class updates
packages/core/src/sync/workspace.ts, packages/ui/src/theme/components/shared/card.tsx, .../section-grid.tsx, .../tech-tag.tsx
Rename generated container classes to zp-*, switch Card internal links to runtime <Link>, and small className adjustments.
Docs formatting only
docs/references/icons/*
Condense MDX/JSX table/array formatting to compact single-line representations (no content 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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I nibble code where icons align,
zp- classes hop into fine design,
grids that clamp and sidebars dressed,
a footer tucked where pages rest,
patches stitched — the build feels blessed 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically summarizes the main changes: client-side navigation fix, sidebar button variants, typed icons, and ESM compatibility improvements across multiple packages.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/styling-cleanup
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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/config would keep style/shape and 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: Switch renderFeature to an object parameter.

The helper now takes three positional arguments, which makes the call site harder to scan and misses the repo TS convention.

♻️ 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 } = params
As per coding guidelines, "Use object parameters for functions with 2+ parameters and include explicit return types."

Also 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 clampClass and clampStyle helpers are duplicated verbatim in workspaces/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 isExternal check only matches http:// and https:// prefixes. Protocol-relative URLs like //example.com/path would 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: Centralize IconPrefix/IconId generation.

packages/core/src/icons.generated.ts already emits the same union from the installed icon sets. Re-declaring it here creates a second public source of truth, so @zpress/config and @zpress/core can 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1f6b8c1 and 4468c94.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (35)
  • examples/kitchen-sink/zpress.config.ts
  • package.json
  • packages/cli/package.json
  • packages/cli/src/index.ts
  • packages/cli/src/shims/require.ts
  • packages/config/schemas/schema.json
  • packages/config/src/index.ts
  • packages/config/src/schema.ts
  • packages/config/src/types.ts
  • packages/core/src/sync/workspace.ts
  • packages/ui/package.json
  • packages/ui/src/config.ts
  • packages/ui/src/theme/components/home/feature-card.css
  • packages/ui/src/theme/components/home/feature-card.tsx
  • packages/ui/src/theme/components/home/feature.tsx
  • packages/ui/src/theme/components/home/workspaces.tsx
  • packages/ui/src/theme/components/shared/card.tsx
  • packages/ui/src/theme/components/shared/section-card.tsx
  • packages/ui/src/theme/components/shared/section-grid.tsx
  • packages/ui/src/theme/components/shared/tech-tag.tsx
  • packages/ui/src/theme/components/sidebar/sidebar-links.css
  • packages/ui/src/theme/components/sidebar/sidebar-links.tsx
  • packages/ui/src/theme/components/workspaces/card.css
  • packages/ui/src/theme/components/workspaces/card.tsx
  • packages/ui/src/theme/components/workspaces/grid.tsx
  • packages/ui/src/theme/hooks/use-zpress.ts
  • packages/ui/src/theme/styles/overrides/home-card.css
  • packages/ui/src/theme/styles/overrides/home.css
  • packages/ui/src/theme/styles/overrides/section-card.css
  • packages/ui/src/theme/styles/themes/arcade-fx.css
  • patches/rspress-plugin-file-tree@1.0.4.patch
  • patches/rspress-plugin-mermaid@1.0.1.patch
  • patches/rspress-plugin-supersub@1.0.0.patch
  • pnpm-workspace.yaml
  • zpress.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>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/ui/src/config.ts (1)

293-305: Consider adding readonly modifiers to return type properties.

The inline return type properties (text, link, icon, style, shape) lack readonly modifiers, while the corresponding SidebarLink interface in packages/config/src/types.ts uses readonly throughout. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 4468c94 and f3245c2.

📒 Files selected for processing (11)
  • examples/kitchen-sink/zpress.config.ts
  • packages/config/src/index.ts
  • packages/config/src/schema.ts
  • packages/config/src/types.ts
  • packages/ui/src/config.ts
  • packages/ui/src/theme/components/footer/site-footer.css
  • packages/ui/src/theme/components/footer/site-footer.tsx
  • packages/ui/src/theme/components/nav/layout.tsx
  • packages/ui/src/theme/components/sidebar/sidebar-links.css
  • packages/ui/src/theme/hooks/use-zpress.ts
  • zpress.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

zrosenbauer and others added 4 commits March 18, 2026 22:52
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>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/config/src/types.ts (2)

6-27: Avoid maintaining a second IconPrefix / IconId source.

packages/core/src/icons.generated.ts already derives these from the installed Iconify sets, and packages/config/src/index.ts already 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 in packages/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

📥 Commits

Reviewing files that changed from the base of the PR and between f3245c2 and ab55e42.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (21)
  • docs/references/icons/colors.mdx
  • docs/references/icons/overview.mdx
  • docs/references/icons/technology/databases.mdx
  • docs/references/icons/technology/frameworks.mdx
  • docs/references/icons/technology/infrastructure.mdx
  • docs/references/icons/technology/integrations.mdx
  • docs/references/icons/technology/languages.mdx
  • docs/references/icons/technology/overview.mdx
  • docs/references/icons/technology/tooling.mdx
  • examples/kitchen-sink/zpress.config.ts
  • package.json
  • packages/config/schemas/schema.json
  • packages/config/src/schema.ts
  • packages/config/src/types.ts
  • packages/ui/package.json
  • packages/ui/src/config.ts
  • packages/ui/src/theme/components/footer/site-footer.css
  • packages/ui/src/theme/components/footer/site-footer.tsx
  • packages/ui/src/theme/hooks/use-zpress.ts
  • patches/rspress-plugin-katex@1.0.0.patch
  • zpress.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

zrosenbauer and others added 2 commits March 18, 2026 23:04
- 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>
@zrosenbauer zrosenbauer merged commit 179ae48 into main Mar 19, 2026
3 checks passed
@zrosenbauer zrosenbauer deleted the fix/styling-cleanup branch March 19, 2026 03:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant