Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Notification Panel

Notification dropdown panel triggered by a button.

Components Notification Panel
feedback interactive
<arc-notification-panel>

Overview

NotificationPanel is a popover-style dropdown designed for displaying notifications, messages, and activity feeds. It pairs a trigger slot (typically a bell icon or button) with a floating panel that appears on click. The panel includes dedicated header, body, and footer regions, making it easy to compose a complete notification center with a title row, scrollable message list, and a "View all" action at the bottom. The panel opens and closes via click on the trigger element, and automatically dismisses when the user clicks outside the component boundary. It dispatches `arc-open` and `arc-close` custom events on state changes so you can synchronize badge counts, mark notifications as read, or fetch fresh data when the panel becomes visible. Positioning is controlled by the `position` prop, which accepts `top-right` (default) or `top-left` to align the dropdown relative to the trigger. The `max-height` prop caps the scrollable body area so long notification lists do not overflow the viewport. The panel uses a smooth fade-and-slide transition on open and close for a polished feel.

Guidelines

When to use

  • Place the trigger button (bell icon, badge) in the trigger slot for consistent click handling
  • Use the header slot for a title like "Notifications" and an optional unread count
  • Use the footer slot for a "View all notifications" link or "Mark all as read" action
  • Set max-height to prevent the panel from exceeding viewport bounds on mobile
  • Listen for arc-open to lazy-load or refresh notification data

When not to use

  • Do not use NotificationPanel for generic dropdown menus — use DropdownMenu or Select instead
  • Do not place complex interactive forms inside the panel — keep it to a list of actionable items
  • Do not forget to handle the arc-close event if you need to clean up or reset scroll position
  • Do not set position to top-left when the trigger is on the left edge of the screen — the panel may overflow
  • Do not nest NotificationPanel inside another popover or modal — stacking contexts will conflict

Features

  • Click-triggered popover with automatic outside-click dismissal
  • Dedicated header, body (default slot), and footer regions for structured content
  • Scrollable body with configurable max-height to prevent viewport overflow
  • Position prop (top-right, top-left) for trigger-relative alignment
  • Smooth opacity and translateY transition on open and close
  • `arc-open` and `arc-close` custom events for state synchronization
  • Shadow DOM parts (trigger, panel, header, body, footer) for targeted styling
  • z-index: 1000 overlay stacking for reliable layering above page content

Preview

Notifications
Deploy succeeded
Production build completed in 42s
New comment
Alice commented on PR #128

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<arc-notification-panel position="top-right">
  <!-- Trigger: bell icon-button with unread badge -->
  <div slot="trigger" style="position:relative;display:inline-block;">
    <arc-icon-button name="bell" variant="ghost" size="sm" label="Notifications"></arc-icon-button>
    <span id="badge" style="position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--color-error);pointer-events:none;"></span>
  </div>

  <div slot="header">
    <span>Notifications</span>
    <arc-badge variant="primary">3 new</arc-badge>
  </div>

  <!-- Notification items -->
  <div style="display:flex;flex-direction:column;">
    <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;align-items:flex-start;">
      <arc-icon name="check-circle" size="16" style="color:var(--color-success);margin-top:2px;flex-shrink:0;"></arc-icon>
      <div>
        <div style="font-weight:600;font-size:13px;color:var(--text-primary);">Deploy succeeded</div>
        <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Production build completed in 42s</div>
        <div style="font-size:11px;color:var(--text-tertiary);margin-top:4px;">2 min ago</div>
      </div>
    </div>
    <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;align-items:flex-start;">
      <arc-icon name="message-circle" size="16" style="color:var(--accent-primary);margin-top:2px;flex-shrink:0;"></arc-icon>
      <div>
        <div style="font-weight:600;font-size:13px;color:var(--text-primary);">Alice commented on PR #128</div>
        <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">"Looks good, just one nit on the error handling"</div>
        <div style="font-size:11px;color:var(--text-tertiary);margin-top:4px;">18 min ago</div>
      </div>
    </div>
    <div style="padding:12px 16px;display:flex;gap:10px;align-items:flex-start;">
      <arc-icon name="alert-triangle" size="16" style="color:var(--color-warning);margin-top:2px;flex-shrink:0;"></arc-icon>
      <div>
        <div style="font-weight:600;font-size:13px;color:var(--text-primary);">Build warning</div>
        <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Bundle size increased by 12% in staging</div>
        <div style="font-size:11px;color:var(--text-tertiary);margin-top:4px;">1 hour ago</div>
      </div>
    </div>
  </div>

  <div slot="footer">
    <arc-link href="/notifications">View all notifications</arc-link>
  </div>
</arc-notification-panel>

<script>
  const panel = document.querySelector('arc-notification-panel');
  panel.addEventListener('arc-open', () => console.log('opened'));
  panel.addEventListener('arc-close', () => console.log('closed'));
</script>
import { NotificationPanel, IconButton, Icon, Badge, Link } from '@arclux/arc-ui-react';

function AppHeader() {
  return (
    <NotificationPanel position="top-right">
      <div slot="trigger" style={{ position: 'relative', display: 'inline-block' }}>
        <IconButton name="bell" variant="ghost" size="sm" label="Notifications" />
        <span style={{
          position: 'absolute', top: 2, right: 2,
          width: 8, height: 8, borderRadius: '50%',
          background: 'var(--color-error)', pointerEvents: 'none'
        }} />
      </div>

      <div slot="header">
        <span>Notifications</span>
        <Badge variant="primary">3 new</Badge>
      </div>

      <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border-subtle)', display: 'flex', gap: 10 }}>
        <Icon name="check-circle" size="16" style={{ color: 'var(--color-success)', flexShrink: 0 }} />
        <div>
          <div style={{ fontWeight: 600, fontSize: 13 }}>Deploy succeeded</div>
          <div style={{ fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 }}>Production build completed in 42s</div>
        </div>
      </div>

      <div slot="footer">
        <Link href="/notifications">View all notifications</Link>
      </div>
    </NotificationPanel>
  );
}
<script setup>
import { NotificationPanel, IconButton, Icon, Badge, Link } from '@arclux/arc-ui-vue';
</script>

<template>
  <NotificationPanel position="top-right">
    <div slot="trigger" style="position:relative;display:inline-block;">
      <IconButton name="bell" variant="ghost" size="sm" label="Notifications" />
      <span style="position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--color-error);pointer-events:none;" />
    </div>

    <template #header>
      <span>Notifications</span>
      <Badge variant="primary">3 new</Badge>
    </template>

    <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;">
      <Icon name="check-circle" size="16" style="color:var(--color-success)" />
      <div>
        <div style="font-weight:600;font-size:13px;">Deploy succeeded</div>
        <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Production build completed in 42s</div>
      </div>
    </div>

    <template #footer>
      <Link href="/notifications">View all notifications</Link>
    </template>
  </NotificationPanel>
</template>
<script>
  import { NotificationPanel, IconButton, Icon, Badge, Link } from '@arclux/arc-ui-svelte';
</script>

<NotificationPanel position="top-right">
  <div slot="trigger" style="position:relative;display:inline-block;">
    <IconButton name="bell" variant="ghost" size="sm" label="Notifications" />
    <span style="position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--color-error);pointer-events:none;" />
  </div>

  <div slot="header">
    <span>Notifications</span>
    <Badge variant="primary">3 new</Badge>
  </div>

  <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;">
    <Icon name="check-circle" size="16" style="color:var(--color-success)" />
    <div>
      <div style="font-weight:600;font-size:13px;">Deploy succeeded</div>
      <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Production build completed in 42s</div>
    </div>
  </div>

  <div slot="footer">
    <Link href="/notifications">View all notifications</Link>
  </div>
</NotificationPanel>
import { Component } from '@angular/core';
import { NotificationPanel, IconButton, Icon, Badge, Link } from '@arclux/arc-ui-angular';

@Component({
  imports: [NotificationPanel, IconButton, Icon, Badge, Link],
  template: `
    <arc-notification-panel position="top-right">
      <div slot="trigger" style="position:relative;display:inline-block;">
        <arc-icon-button name="bell" variant="ghost" size="sm" label="Notifications" />
        <span style="position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--color-error);pointer-events:none;"></span>
      </div>
      <div slot="header">
        <span>Notifications</span>
        <arc-badge variant="primary">3 new</arc-badge>
      </div>
      <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;">
        <arc-icon name="check-circle" size="16" style="color:var(--color-success)" />
        <div>
          <div style="font-weight:600;font-size:13px;">Deploy succeeded</div>
          <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Production build completed in 42s</div>
        </div>
      </div>
      <div slot="footer">
        <arc-link href="/notifications">View all notifications</arc-link>
      </div>
    </arc-notification-panel>
  `,
})
export class AppHeaderComponent {}
import { NotificationPanel, IconButton, Icon, Badge, Link } from '@arclux/arc-ui-solid';

function AppHeader() {
  return (
    <NotificationPanel position="top-right">
      <div slot="trigger" style="position:relative;display:inline-block;">
        <IconButton name="bell" variant="ghost" size="sm" label="Notifications" />
        <span style="position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--color-error);pointer-events:none;" />
      </div>
      <div slot="header">
        <span>Notifications</span>
        <Badge variant="primary">3 new</Badge>
      </div>
      <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;">
        <Icon name="check-circle" size="16" style="color:var(--color-success)" />
        <div>
          <div style="font-weight:600;font-size:13px;">Deploy succeeded</div>
          <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Production build completed in 42s</div>
        </div>
      </div>
      <div slot="footer">
        <Link href="/notifications">View all notifications</Link>
      </div>
    </NotificationPanel>
  );
}
import { NotificationPanel, IconButton, Icon, Badge, Link } from '@arclux/arc-ui-preact';

function AppHeader() {
  return (
    <NotificationPanel position="top-right">
      <div slot="trigger" style="position:relative;display:inline-block;">
        <IconButton name="bell" variant="ghost" size="sm" label="Notifications" />
        <span style="position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--color-error);pointer-events:none;" />
      </div>
      <div slot="header">
        <span>Notifications</span>
        <Badge variant="primary">3 new</Badge>
      </div>
      <div style="padding:12px 16px;border-bottom:1px solid var(--border-subtle);display:flex;gap:10px;">
        <Icon name="check-circle" size="16" style="color:var(--color-success)" />
        <div>
          <div style="font-weight:600;font-size:13px;">Deploy succeeded</div>
          <div style="font-size:12px;color:var(--text-tertiary);margin-top:2px;">Production build completed in 42s</div>
        </div>
      </div>
      <div slot="footer">
        <Link href="/notifications">View all notifications</Link>
      </div>
    </NotificationPanel>
  );
}

API

open boolean false
Controls whether the notification panel is visible. Toggle this programmatically or let the built-in trigger click handler manage it.
position 'top-right' | 'top-left' 'top-right'
Horizontal alignment of the panel relative to the trigger element. Use top-right when the trigger is near the right edge of the viewport.
max-height string '400px'
Maximum height of the scrollable body area. Prevents long notification lists from overflowing the viewport.

Events

arc-open
Fired when the notification panel opens
arc-close
Fired when the notification panel closes

See Also