Skip to content

feat: add help button to header#251

Merged
brian-smith-tcril merged 2 commits intoopenedx:mainfrom
brian-smith-tcril:help-button
Apr 29, 2026
Merged

feat: add help button to header#251
brian-smith-tcril merged 2 commits intoopenedx:mainfrom
brian-smith-tcril:help-button

Conversation

@brian-smith-tcril
Copy link
Copy Markdown
Contributor

@brian-smith-tcril brian-smith-tcril commented Apr 28, 2026

Summary

Frontend half of #245. Adds a reusable help button widget in the header so any app can opt in with one helper call. URL flows from runtime config (MFE_CONFIG / MFE_CONFIG_OVERRIDES, plus the help-tokens legacy fallback the backend provides for instructor-dashboard).

What this PR adds:

  • HelpButton component (renders a LinkMenuItem with variant="navLink" when its getUrl() callback returns a truthy URL, otherwise null)
  • helpButtonSlotOperation({ appId, role }) helper that builds a WidgetOperationTypes.APPEND op for secondaryLinks.v1, gated by condition.active: [role]
  • New header.help message
  • Public exports for both
  • Small SCSS fix that strips padding-left from the first .nav-link in SecondaryNavLinks so the cluster sits flush against neighboring widgets (e.g. the notifications bell) — separate commit, can be reviewed independently

Apps opt in with one line:

helpButtonSlotOperation({ appId, role: dashboardRole })

Companion PRs:

  • openedx/frontend-app-learner-dashboard (swaps existing per-app SupportLinkMenuItem to the helper)
  • openedx/frontend-app-instructor-dashboard (registers help button — instructor-dashboard had no help link before)
  • openedx/frontend-template-site (dev-only commonAppConfig.SUPPORT_URL for local verification)

Backend half (already merged) provides per-app SUPPORT_URL via the help-tokens legacy fallback for instructor-dashboard.

Test plan

  • cd packages/frontend-base && nvm use && npm run test — new HelpButton + helper tests, full suite green
  • cd packages/frontend-base && nvm use && npm run lint — clean
  • In a template-site dev, set commonAppConfig.SUPPORT_URL and verify Help renders on a learner-dashboard route, links to the URL, and disappears when SUPPORT_URL is empty
  • Set per-app override for instructor-dashboard, verify help link uses that URL when on instructor-dash routes
  • Confirm shell-only / auth routes (no app role active) render no help button

Follow-up (not in this PR)

Help button on mobile — current scope is desktop only, matching the prior learner-dashboard behavior. The non-frontend-base headers vary across apps; before adding mobile, worth deciding the intended pattern rather than literally matching any one legacy app.

🤖 Generated with Claude Code

Copy link
Copy Markdown
Contributor

@arbrandes arbrandes left a comment

Choose a reason for hiding this comment

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

Nice! I do have a couple of nits to bring up. (One more nitty than the other: I suspect I might have actual feelings about the const name.)

import { getAppConfig, WidgetAppendOperation, WidgetOperationTypes } from '../../runtime';
import HelpButton from './HelpButton';

export const HELP_WIDGET_ID = 'org.openedx.frontend.widget.header.help.v1';
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.

I've been trying to avoid screaming snake case for new constants, specially exported ones. The name and the fact they're a const should be more than enough for readers and consumers to understand their purpose.

Suggested change
export const HELP_WIDGET_ID = 'org.openedx.frontend.widget.header.help.v1';
export const helpWidgetId = 'org.openedx.frontend.widget.header.help.v1';

We're still going to see them in legacy configuration, but that makes for a neat indicator of what's properly typed vs a string-only MFE config var that requires casting (which is precisely what you had to do with SUPPORT_URL below).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment thread shell/header/app.scss Outdated

// Secondary-nav cluster sits flush against whatever's to its left
// (notifications bell, etc.) — those neighbors bring their own padding.
.secondary-nav-links > .nav-link:first-child {
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.

I realize this is extremely nitty, but do we need to limit ourselves to .nav-link?

Suggested change
.secondary-nav-links > .nav-link:first-child {
.secondary-nav-links > :first-child {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I went back and forth on this a bit. .nav-link was the only thing giving me trouble, so I figured limiting it might make sense, but it's probably better for consistency to not have it.

The only other example I've seen in here has been IconButton, which already doesn't have padding so it's a no-op for those.

Fixed.

Provides a reusable HelpButton widget and a helpButtonSlotOperation
helper. Apps opt in by calling helpButtonSlotOperation with their
appId and route role; the helper appends the button to the
secondaryLinks slot, gated by that role. The widget reads SUPPORT_URL
via getAppConfig at render time, so the value flows from runtime
MFE_CONFIG / MFE_CONFIG_OVERRIDES (or any legacy fallback the backend
provides) without rebuilding the apps. The widget returns null when
the URL is empty so the button only appears when configured.

Refs openedx#245

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Strips padding-left from the first .nav-link in SecondaryNavLinks so
the cluster sits flush against neighboring widgets in desktopRight
(e.g. the notifications bell). Inter-link padding within the cluster
is preserved.

Refs openedx#245

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@brian-smith-tcril brian-smith-tcril merged commit 4c2e90e into openedx:main Apr 29, 2026
5 checks passed
op: WidgetOperationTypes.APPEND,
element: (
<HelpButton
getUrl={() => getAppConfig(appId).SUPPORT_URL as string | undefined}
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.

for this one we will keep using as snake case or we will change in the future for supportUrl?

@openedx-semantic-release-bot
Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0-alpha.42 🎉

The release is available on:

Your semantic-release bot 📦🚀

@arbrandes arbrandes linked an issue Apr 29, 2026 that may be closed by this pull request
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.

Help button in the header

5 participants