Skip to content

[ENG - 506] Add support for custom links in the left sidebar#16472

Open
yash-learner wants to merge 10 commits into
developfrom
ENG-506-support-for-inserting-links-in-left-nav
Open

[ENG - 506] Add support for custom links in the left sidebar#16472
yash-learner wants to merge 10 commits into
developfrom
ENG-506-support-for-inserting-links-in-left-nav

Conversation

@yash-learner

@yash-learner yash-learner commented Jun 22, 2026

Copy link
Copy Markdown
Member

Proposed Changes

Fixes https://openhealthcarenetwork.atlassian.net/browse/ENG-506

Demo_.Add.custom.links.to.sidebar.mp4

Add support for custom links in the left sidebar

Lets deployments and plugins inject custom navigation links into the sidebar, scoped per nav context, with build-time and runtime URL safety.

How it's implemented

Config & schema

  • customNavLink.ts — zod CustomNavLink schema: title, url, optional icon, external, openInNewTab, and placement[] (which nav contexts it appears in; defaults to ["all"]).
  • Two sources are merged: deployment env REACT_CUSTOM_NAV_LINKS (parsed in care.config.ts → careConfig.customNavLinks) and plugin manifests (customNavLinks in pluginTypes.ts). Env format documented in .example.env; typed via vite-env.d.ts.

Resolution (useCustomNavLinks.tsx)

  • useCustomNavLinks(scope) concatenates env + plugin links, filters by placement (matching scope or "all") and by nav-URL safety, then maps to NavigationLink[].
  • Icons are resolved through a fixed iconMap allow-list (not arbitrary strings) to keep the bundle bounded and avoid injection.

Rendering (sidebar)

  • custom-nav-links.tsx (<CustomNavLinks scope>) feeds resolved links into NavMain; app-sidebar.tsx mounts it with the active scope.
  • nav-main.tsx renderNavLink returns a DOM element directly (for Radix asChild): internal links → raviger ActiveLink (same-tab SPA nav); external / new-tab links → sanitized <a target="_blank" rel="noopener noreferrer">. isRenderableNavLink drops anything failing URL safety.

URL safety (url.ts)

  • Dependency-free predicates isSafeExternalUrl (absolute http(s) only), isInternalNavPath (/… but not protocol-relative //), and isSafeNavUrl.
  • Reused in two layers: runtime (hook filter + renderer) and build time — validate-env.ts adds a superRefine on REACT_CUSTOM_NAV_LINKS so a misconfigured/unsafe URL fails the build instead of silently rendering.

i18n — link titles are translated; English keys added to en.json.

Notes

  • Safety is enforced at build time (env) and runtime (env + plugin links), so the unsafe path is unreachable in a shipped bundle.

Tagging: @ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate the bug or test the new feature.
  • Update product documentation.
  • Ensure that UI text is placed in I18n files.
  • Prepare a screenshot or demo video for the changelog entry and attach it to the issue.
  • Request peer reviews.
  • Complete QA on mobile devices.
  • Complete QA on desktop devices.
  • Add or update Playwright tests for related changes

Summary by CodeRabbit

  • New Features
    • Custom navigation links can now be added to the sidebar via the REACT_CUSTOM_NAV_LINKS configuration
    • Links support context-specific placement (facility, location, service, admin, patient scopes)
    • External URLs are handled safely, with optional “open in new tab” behavior
    • Plugins can declare custom navigation links
  • Documentation / Localization
    • Updated environment docs for the new config option
    • Added/updated the “Opens in new tab” sidebar label text

Copilot AI review requested due to automatic review settings June 22, 2026 18:35
@netlify

netlify Bot commented Jun 22, 2026

Copy link
Copy Markdown

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit 8a17625
🔍 Latest deploy log https://app.netlify.com/projects/care-ohc/deploys/6a3b9128180510000818f088
😎 Deploy Preview https://deploy-preview-16472.preview.ohc.network
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 87dcc74c-ad3c-4330-b674-ef9e3bf91034

📥 Commits

Reviewing files that changed from the base of the PR and between b0dedca and 8a17625.

📒 Files selected for processing (2)
  • public/locale/en.json
  • src/components/ui/sidebar/nav-main.tsx

Walkthrough

Adds a REACT_CUSTOM_NAV_LINKS environment variable for custom sidebar navigation links. The PR adds shared URL and schema validation, merges config and plugin sources into scoped nav items, updates sidebar link rendering for internal and external URLs, and wires the custom links into the app sidebar.

Changes

Custom Navigation Links Pipeline

Layer / File(s) Summary
URL helpers and nav schema
src/Utils/url.ts, src/types/nav/customNavLink.ts
Adds URL safety helpers and defines the custom navigation link schemas, scopes, and inferred types used across the feature.
Env config and validation
.example.env, src/vite-env.d.ts, care.config.ts, scripts/validate-env.ts
Declares REACT_CUSTOM_NAV_LINKS, documents the variable in the example env file, reads it into careConfig, and validates it in the env schema with JSON parsing and per-link URL checks.
Plugin manifest and custom nav hook
src/pluginTypes.ts, src/hooks/useCustomNavLinks.tsx
Extends plugin manifests with custom navigation links and adds a hook that combines config and plugin links, filters them by scope and URL safety, and maps them into sidebar navigation items.
Sidebar link rendering
src/components/ui/sidebar/nav-main.tsx, public/locale/en.json
Updates sidebar navigation rendering to filter unsafe links, render internal links with ActiveLink, render external or new-tab links with anchors, and add the new-tab accessibility label.
Custom nav sidebar integration
src/components/ui/sidebar/custom-nav-links.tsx, src/components/ui/sidebar/app-sidebar.tsx
Adds the CustomNavLinks component and wires it into the app sidebar by computing a nav scope from sidebar state and passing that scope into the custom link renderer.

Suggested reviewers

  • bodhish
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding custom left-sidebar links.
Description check ✅ Passed The description covers the proposed changes and merge checklist and includes relevant implementation details.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ENG-506-support-for-inserting-links-in-left-nav

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

@yash-learner yash-learner changed the title feat: add support for custom links in the left sidebar Add support for custom links in the left sidebar Jun 22, 2026
@github-actions

Copy link
Copy Markdown

⚠️ Merge Checklist Incomplete

Thank you for your contribution! To help us review your PR efficiently, please complete the merge checklist in your PR description.

Your PR will be reviewed once you have marked the appropriate checklist items.

To update the checklist:

  • Change - [ ] to - [x] for completed items
  • Only check items that are relevant to your PR
  • Leave items unchecked if they don't apply

The checklist helps ensure code quality, testing coverage, and documentation are properly addressed.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 22, 2026

Copy link
Copy Markdown

Deploying care-preview with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8a17625
Status: ✅  Deploy successful!
Preview URL: https://40085126.care-preview-a7w.pages.dev
Branch Preview URL: https://eng-506-support-for-insertin.care-preview-a7w.pages.dev

View logs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new configuration surface for injecting custom navigation links into the left sidebar (via REACT_CUSTOM_NAV_LINKS and plugin manifests), including optional icons, placement scoping, and external/new-tab behavior.

Changes:

  • Introduces CustomNavLink zod schema/types and wires REACT_CUSTOM_NAV_LINKS through env typing, validation, and careConfig.
  • Adds useCustomNavLinks + CustomNavLinks to resolve and render configured links per sidebar context.
  • Updates NavMain to support external/new-tab links by rendering anchors (instead of only raviger ActiveLink) and filtering unsafe external URLs.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/vite-env.d.ts Adds REACT_CUSTOM_NAV_LINKS to Vite env typings.
src/Utils/utils.ts Adds isSafeExternalUrl() helper for http(s)-only external URL checks.
src/types/nav/customNavLink.ts New zod schema/types for custom sidebar links + placement scopes.
src/pluginTypes.ts Extends plugin manifest type to allow plugins to contribute customNavLinks.
src/hooks/useCustomNavLinks.tsx New hook to merge env + plugin links, filter, and map to NavigationLink.
src/components/ui/sidebar/nav-main.tsx Adds support for rendering anchors for external/new-tab links + URL filtering.
src/components/ui/sidebar/custom-nav-links.tsx New component to render resolved custom links via NavMain.
src/components/ui/sidebar/app-sidebar.tsx Computes current nav scope and mounts CustomNavLinks in the sidebar.
scripts/validate-env.ts Adds parsing/validation for REACT_CUSTOM_NAV_LINKS.
care.config.ts Adds customNavLinks to runtime config from REACT_CUSTOM_NAV_LINKS.
.example.env Documents REACT_CUSTOM_NAV_LINKS format and examples.

Comment thread src/components/ui/sidebar/nav-main.tsx Outdated
Comment thread src/hooks/useCustomNavLinks.tsx Outdated
Comment thread scripts/validate-env.ts Outdated
Comment thread src/hooks/useCustomNavLinks.tsx Outdated
Comment thread src/components/ui/sidebar/app-sidebar.tsx
Comment thread src/pluginTypes.ts Outdated
Comment thread src/components/ui/sidebar/custom-nav-links.tsx Outdated
Comment thread src/components/ui/sidebar/app-sidebar.tsx Outdated
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

🎭 Playwright Test Results

Status: ✅ Passed
Test Shards: 3

Metric Count
Total Tests 325
✅ Passed 325
❌ Failed 0
⏭️ Skipped 0

📊 Detailed results are available in the playwright-final-report artifact.

Run: #9719

@yash-learner yash-learner changed the title Add support for custom links in the left sidebar [ENG - 506] Add support for custom links in the left sidebar Jun 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.

Comment thread src/hooks/useCustomNavLinks.tsx
Comment thread scripts/validate-env.ts
Comment thread .example.env
Comment thread src/components/ui/sidebar/app-sidebar.tsx
Copilot AI review requested due to automatic review settings June 23, 2026 13:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

Comment thread src/hooks/useCustomNavLinks.tsx

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.

Comment thread src/hooks/useCustomNavLinks.tsx Outdated
Comment thread src/components/ui/sidebar/nav-main.tsx Outdated
which is causing complex code and more review comments from copilot
@yash-learner

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yash-learner yash-learner marked this pull request as ready for review June 23, 2026 17:09
@yash-learner yash-learner requested review from a team June 23, 2026 17:09
@yash-learner yash-learner requested a review from a team as a code owner June 23, 2026 17:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/ui/sidebar/nav-main.tsx`:
- Around line 78-90: The anchor element that renders when isExternal or
link.openInNewTab is true lacks accessibility information for screen readers.
Add an aria-label attribute to the <a> tag that indicates the link opens in a
new tab or a new window. The aria-label should combine the link's purpose with a
clear indication that it opens externally, using the openInNewTab variable to
conditionally include this text when a new tab will be opened. This ensures
assistive technology users are informed about the navigation behavior before
activating the link.

In `@src/hooks/useCustomNavLinks.tsx`:
- Around line 78-104: The useCustomNavLinks hook returns a new array reference
on every render due to the filter and map operations, causing unnecessary
re-renders of consuming components. Wrap the entire computation (from the
envLinks and pluginLinks declaration through the final return statement with all
the filter and map operations) in a useMemo hook, and include the appropriate
dependencies: t from useTranslation, careApps from useCareApps, and
careConfig.customNavLinks to ensure the memoized value is recalculated only when
these dependencies change.

In `@src/Utils/url.ts`:
- Around line 14-21: The isSafeExternalUrl function has a security vulnerability
where protocol-relative URLs like "//evil.com" are accepted in browser contexts
because they inherit the page protocol. To fix this, add an explicit check at
the beginning of the isSafeExternalUrl function to reject any URLs that start
with "//" (protocol-relative URLs) by returning false before attempting to parse
with new URL(). This ensures that protocol-relative URLs are blocked regardless
of runtime context.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 33a5ad17-c8f8-42ce-a016-cacff3a77d64

📥 Commits

Reviewing files that changed from the base of the PR and between 71cd55b and b0dedca.

📒 Files selected for processing (11)
  • .example.env
  • care.config.ts
  • scripts/validate-env.ts
  • src/Utils/url.ts
  • src/components/ui/sidebar/app-sidebar.tsx
  • src/components/ui/sidebar/custom-nav-links.tsx
  • src/components/ui/sidebar/nav-main.tsx
  • src/hooks/useCustomNavLinks.tsx
  • src/pluginTypes.ts
  • src/types/nav/customNavLink.ts
  • src/vite-env.d.ts

Comment thread src/components/ui/sidebar/nav-main.tsx
Comment thread src/hooks/useCustomNavLinks.tsx
Comment thread src/Utils/url.ts
@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds support for custom navigation links in the left sidebar, sourced from the REACT_CUSTOM_NAV_LINKS environment variable and plugin manifests. URL safety is enforced at both build time (via a Zod superRefine in validate-env.ts) and runtime (hook filter + renderer), and icons are restricted to an explicit allow-list.

  • useCustomNavLinks(scope) merges env + plugin links, filters by placement scope and URL safety, resolves icons through a bounded iconMap, and returns typed NavigationLink[] ready for NavMain.
  • renderNavLink in nav-main.tsx replaces all ActiveLink usages to handle both internal SPA navigation and external/new-tab anchors with proper rel=\"noopener noreferrer\", with an sr-only accessibility label for new-tab links.
  • navScope in app-sidebar.tsx maps the current URL context to a NavScope and passes it to <CustomNavLinks>, which renders nothing when no matching links exist.

Confidence Score: 5/5

Safe to merge — the URL safety checks are layered correctly, no data mutations or auth boundaries are touched, and the feature is purely additive to the sidebar.

The change is well-contained: new files introduce URL predicates, a Zod schema, a hook, and a thin wrapper component. Existing sidebar code is refactored only to replace ActiveLink with renderNavLink, which preserves the same rendering for internal paths.

No files require special attention; the minor t-import concern in nav-main.tsx is isolated to screen-reader text.

Important Files Changed

Filename Overview
src/Utils/url.ts New dependency-free URL safety predicates — logic is correct and well-commented.
src/types/nav/customNavLink.ts Zod schema for CustomNavLink and NavScope — clean, well-typed, placement defaults correctly to all.
src/hooks/useCustomNavLinks.tsx Merges env + plugin links, filters by placement/URL safety, maps through icon allow-list — logic is sound.
src/components/ui/sidebar/nav-main.tsx Adds renderNavLink and isRenderableNavLink helpers; t is imported from i18next module level rather than useTranslation, so the screen-reader label won't react to runtime language switches.
src/components/ui/sidebar/app-sidebar.tsx Adds navScope IIFE and mounts CustomNavLinks; scope computation is correct for all defined contexts.
src/components/ui/sidebar/custom-nav-links.tsx Thin wrapper — resolves links and renders NavMain; early-returns cleanly when no links exist.
scripts/validate-env.ts Build-time validation for REACT_CUSTOM_NAV_LINKS using the same URL-safety predicate as the runtime — solid defense-in-depth.
src/pluginTypes.ts Adds optional customNavLinks field to PluginManifest — minimal, correct.
care.config.ts Parses REACT_CUSTOM_NAV_LINKS via JSON.parse — consistent with the customShortcuts precedent; build-time validation guards against malformed input.

Reviews (3): Last reviewed commit: "Merge branch 'develop' into ENG-506-supp..." | Re-trigger Greptile

Comment thread src/hooks/useCustomNavLinks.tsx
Comment thread src/components/ui/sidebar/nav-main.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants