113 lines
4.1 KiB
TypeScript
113 lines
4.1 KiB
TypeScript
import { For, Show, type JSX } from "solid-js";
|
||
import { Bell, Settings } from "../../../lib/icons";
|
||
import { notificationItems, unreadNotificationCount } from "../data/shell.data";
|
||
import styles from "./NotificationsMenu.module.scss";
|
||
|
||
type NotificationsMenuProps = {
|
||
id: string;
|
||
menuRef: (element: HTMLDivElement) => void;
|
||
onSelect: () => void;
|
||
};
|
||
|
||
export const NotificationsMenu = (props: NotificationsMenuProps): JSX.Element => {
|
||
const unreadItems = notificationItems.filter((item) => item.unread);
|
||
const earlierItems = notificationItems.filter((item) => !item.unread);
|
||
const hasNotifications = notificationItems.length > 0;
|
||
const isCaughtUp = unreadItems.length === 0 && hasNotifications;
|
||
|
||
return (
|
||
<div id={props.id} class={styles.menu} role="menu" aria-label="Notifications" ref={props.menuRef}>
|
||
<div class={styles.header}>
|
||
<div class={styles.headerCopy}>
|
||
<strong class={styles.title}>Notifications</strong>
|
||
<span class={styles.subtitle}>
|
||
{unreadNotificationCount > 0
|
||
? `You have ${unreadNotificationCount} unread`
|
||
: "You’re all caught up"}
|
||
</span>
|
||
</div>
|
||
|
||
<Show when={unreadNotificationCount > 0}>
|
||
<button type="button" role="menuitem" class={styles.headerAction} onClick={props.onSelect}>
|
||
Mark all read
|
||
</button>
|
||
</Show>
|
||
</div>
|
||
|
||
<div class={styles.listWrap}>
|
||
<Show when={!hasNotifications}>
|
||
<div class={styles.stateCard}>
|
||
<span class={styles.stateIcon} aria-hidden="true">
|
||
<Bell size={18} strokeWidth={2} />
|
||
</span>
|
||
<strong class={styles.stateTitle}>No notifications yet</strong>
|
||
<span class={styles.stateCopy}>When activity starts across your workspace, it’ll show up here.</span>
|
||
</div>
|
||
</Show>
|
||
|
||
<Show when={isCaughtUp}>
|
||
<div class={styles.stateCard}>
|
||
<span class={styles.stateIcon} aria-hidden="true">
|
||
<Bell size={18} strokeWidth={2} />
|
||
</span>
|
||
<strong class={styles.stateTitle}>You’re all caught up</strong>
|
||
<span class={styles.stateCopy}>No unread notifications right now. Earlier activity is still available below.</span>
|
||
</div>
|
||
</Show>
|
||
|
||
<Show when={unreadItems.length > 0}>
|
||
<section class={styles.section} aria-label="Unread notifications">
|
||
<span class={styles.sectionLabel}>Unread</span>
|
||
<div class={styles.list}>
|
||
<For each={unreadItems}>
|
||
{(item): JSX.Element => (
|
||
<button type="button" role="menuitem" classList={{ [styles.item]: true, [styles.itemUnread]: true }} onClick={props.onSelect}>
|
||
<span class={styles.itemMarker} aria-hidden="true" />
|
||
<div class={styles.itemBody}>
|
||
<span class={styles.itemTitle}>{item.title}</span>
|
||
<span class={styles.itemMeta}>{item.contextLabel}</span>
|
||
</div>
|
||
<span class={styles.itemTime}>{item.timeLabel}</span>
|
||
</button>
|
||
)}
|
||
</For>
|
||
</div>
|
||
</section>
|
||
</Show>
|
||
|
||
<Show when={earlierItems.length > 0}>
|
||
<section class={styles.section} aria-label="Earlier notifications">
|
||
<span class={styles.sectionLabel}>Earlier</span>
|
||
<div class={styles.list}>
|
||
<For each={earlierItems}>
|
||
{(item): JSX.Element => (
|
||
<button type="button" role="menuitem" class={styles.item} onClick={props.onSelect}>
|
||
<span class={styles.itemMarkerMuted} aria-hidden="true" />
|
||
<div class={styles.itemBody}>
|
||
<span class={styles.itemTitle}>{item.title}</span>
|
||
<span class={styles.itemMeta}>{item.contextLabel}</span>
|
||
</div>
|
||
<span class={styles.itemTime}>{item.timeLabel}</span>
|
||
</button>
|
||
)}
|
||
</For>
|
||
</div>
|
||
</section>
|
||
</Show>
|
||
</div>
|
||
|
||
<div class={styles.footer}>
|
||
<button type="button" role="menuitem" class={styles.footerAction} onClick={props.onSelect}>
|
||
<Settings size={16} strokeWidth={2} />
|
||
<span>Notification settings</span>
|
||
</button>
|
||
|
||
<button type="button" role="menuitem" class={styles.footerAction} onClick={props.onSelect}>
|
||
<Bell size={16} strokeWidth={2} />
|
||
<span>View all notifications</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|