Components

Header

The 40px fixed top app bar from header-fe, exposed as the MFE remote rvn_mfe_header/Header — brand-blue bar with hamburger and app/page title on the left, language selector, notifications and user menu on the right.

Source in the MFEs
header-fe Header.tsxheader-fe index.scssNotificationBell.tsxLanguageSelector.tsxmodule-federation.config.tsappshell-fe App.tsx (consumer)

Live example

A representative mock of the bar: 40px tall, background hsl(212, 94%, 42%) (#0664d0), white text. Hamburger + grid icon + app title on the left, a reserved centre slot, and the user menu (Avatar + Popover) on the right. In production it is position: fixed with z-index: 1000; here it sits inline so it fits the preview.

Preview
Raffles Data & Analytics
L
linhtd@raffles.com.vnRAFFLES VN CO. LTD
Click the hamburger to toggle the module menu; click the avatar for the user menu.
<RemoteMicroHeader
  title="Raffles Data & Analytics"
  user={user}
/>

<!-- In appshell-fe/src/App.tsx: -->
const RemoteMicroHeader = React.lazy(() => import('rvn_mfe_header/Header'));

{isAuthenticated ? (
  <>
    <Suspense fallback={<Skeleton active />}>
      <RemoteMicroHeader title="Raffles Data & Analytics" user={user} />
      <div style={{ height: '40px' }}></div>  {/* padding for fixed header */}
    </Suspense>
    <Shell />
  </>
) : null}

Markup

The real component from header-fe. Three zones: .header-left-group (hamburger, grid icon, title), a flexible centre reserved for search/actions (max-width 500px), and a right Space holding the extra slot, language selector, the Connect-only notification bell and the user menu.

// Header component (lines 41-478 of header-fe/src/components/Header.tsx)
const Header: React.FC<HeaderProps> = ({ className, title = 'Micro Header', extra, user }) => {
  const [pageTitle, setPageTitle] = useState('');
  useMessageBus<{ title?: string }>(KEY_MESSAGE_BUS.activePageTitle, (payload) =>
    setPageTitle(payload?.title ?? '')
  );

  return (
    <div
      className={clsx('rvn-header-bg text-white d-flex justify-content-between align-items-center px-2 py-1 fixed-header', className)}
      style={{
        height: '40px',
        position: 'fixed',
        zIndex: 1000,
        width: '100%',
      }}
    >
      {/* LEFT: hamburger + grid icon + title */}
      <div style={{ display: 'flex', alignItems: 'center' }} className="header-left-group">
        <Button type="text" className="text-white header-module-menu-toggle"
          icon={<MenuOutlined className="text-white" />}
          onClick={handleOpenModuleMenu} />
        <ProductOutlined className="text-white header-module-menu-toggle-app"
          style={{ fontSize: 16, cursor: 'pointer' }}
          onClick={handleDispatchEventDrawer} />
        <span className="font-size-13 header-app-title" onClick={() =>
          emitMessage(KEY_MESSAGE_BUS.navigateHome, {})}>
          {title}
        </span>
      </div>

      {/* CENTER: reserved for search/actions */}
      <div style={{ flex: 1, maxWidth: 500 }} className="mx-2">
        <Flex gap={5}>{/* reserved */}</Flex>
      </div>

      {/* RIGHT: language, notification, user menu */}
      <Space size="middle">
        {extra}
        <LanguageSelector />
        {isConnectPlatform ? <NotificationBell user={user} /> : null}
        <Popover content={userMenu} placement="bottomRight" overlayStyle={{ borderRadius: 8 }}>
          <Flex style={{ cursor: 'pointer' }}>
            <Avatar style={{ backgroundColor: '#1890ff' }}>
              {user?.email ? user.email.charAt(0).toUpperCase() : 'R'}
            </Avatar>
            <div className="d-flex flex-column ms-2 text-white">
              <span style={{ fontSize: 12 }}>{user?.email}</span>
              <span style={{ fontSize: 10 }}>RAFFLES VN CO. LTD</span>
            </div>
          </Flex>
        </Popover>
      </Space>
    </div>
  );
};

SCSS

The bar’s styling lives in header-fe/src/assets/scss/index.scss. Desktop shows the static app title with a 9px left inset; the mobile media query swaps the title for the broadcast page name and reveals the hamburger.

// SCSS (header-fe/src/assets/scss/index.scss)
$banner-rvn-bg: hsl(212, 94%, 42%);  // #0664d0
$banner-rvn-fg: hsl(212, 0%, 100%);  // white

.fixed-header {
  position: fixed !important;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
}

.rvn-header-bg {
  background-color: $banner-rvn-bg !important;
}

.rvn-header-bg .header-left-group {
  padding-left: 9px;  // Desktop inset
}

.header-module-menu-toggle,
.header-page-title {
  display: none;  // Hidden on desktop
}

@media (max-width: 767.98px) {
  .header-app-title {
    display: none;  // Show page title instead
  }
  .header-module-menu-toggle {
    display: inline-flex;  // Show hamburger
  }
  .header-page-title {
    display: inline;
  }
  .rvn-header-bg .header-left-group {
    padding-left: 0 !important;
    margin-left: -8px !important;
  }
}

Props

NameTypeDefaultDescription
titlestring'Micro Header'App name shown on desktop — appshell passes "Raffles Data & Analytics". Clicking it emits KEY_MESSAGE_BUS.navigateHome. On mobile the broadcast page title replaces it.
userHeaderUserUser object with id, email, username, firstName, lastName, groups. Drives the avatar initial, the email line and the notification bell.
classNamestringOptional extra CSS classes merged onto the bar via clsx.
extraReact.ReactNodeOptional content slot rendered in the right group, before the language selector.

Classes

NameTypeDefaultDescription
fixed-headerclassposition: fixed at the top, full width, z-index 1000.
rvn-header-bgclassBrand background — $banner-rvn-bg: hsl(212, 94%, 42%) (#0664d0), white foreground.
header-left-groupclassLeft zone wrapper. 9px left padding on desktop; the mobile query removes it and pulls the group left by 8px.
header-app-titleclassStatic app title, font-size-13. Visible on desktop, hidden below 768px.
header-page-titleclassThe active page name (from the rvn-active-page-title broadcast). Hidden on desktop, shown on mobile in place of the app title.
header-module-menu-toggleclassThe hamburger Button. Hidden on desktop, inline-flex below 768px — opens the module menu.
header-content .page-titleclassThe page heading rendered in the content area below the bar: 20px, weight 600, colour #323130.

Mobile behaviour

Below 768px the bar changes role: the static app title (.header-app-title) is hidden and the current page name (.header-page-title) shows instead, fed by the modules’ breadcrumb broadcast on KEY_MESSAGE_BUS.activePageTitle — the in-content breadcrumb is hidden at the same breakpoint. The hamburger (.header-module-menu-toggle) appears to open the module menu. The grid icon (ProductOutlined, 16px) stays visible on all sizes and triggers the app drawer.

Desktop keeps the breadcrumb
On desktop the page name never renders in the header — the breadcrumb inside the content area carries it. The two are complementary halves of the same rvn-active-page-title contract (see Components → Breadcrumb).

Notes

Always add the 40px spacer
The bar is position: fixed and 40px tall. The parent layout must render a <div style={{ height: '40px' }}/> immediately after it (as appshell does) or the page content slides underneath.
Exposed as an MFE remote
header-fe (port 3001) exposes the component as rvn_mfe_header/Header via Module Federation; appshell-fe consumes it with React.lazy(() => import('rvn_mfe_header/Header')) inside a Suspense boundary.
Platform variants
The notification bell renders on the CONNECT platform only (REACT_APP_PLATFORM); HUB builds omit it. The user menu Popover opens bottomRight and currently contains Logout only.
z-index 1000
The bar sits at z-index: 1000. Drawers, modals and dropdowns from remote modules can collide with it if their z-indexes are not scoped — check stacking when adding overlays near the top of the viewport.