NotificationBell
A bell with the unread count on its corner: a link, or a button that opens any panel.
Demo
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/notification_bell.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/notification_bell.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/notification_bell.qwe
component NotificationBellDemoLive() { state unread = 2 <div.demo-row> <NotificationBell id="notification-bell-demo-live" count={unread} on_click={() => { unread = 0 }}/> <Button size="sm" variant="outline" id="notification-bell-demo-more" on_click={() => { unread += 1 }}>New notification</Button> <span.demo-note>{unread == 0 ? "All read (the bell was clicked)." : `${unread} unread; click the bell to read them.`}</span> </div>}view NotificationBellDemo() = <div.demo-stack> <div.demo-row style="gap: 20px"> <NotificationBell id="notification-bell-demo" count={3} href="#notification_bell"/> <NotificationBell count={0} href="#notification_bell"/> <NotificationBell id="notification-bell-demo-many" count={120}/> <NotificationBell id="notification-bell-demo-dot" count={1} dot={true}/> <NotificationBell count={7} size="sm"/> <NotificationBell count={7} size="lg"/> </div> <div.demo-row> <NotificationBell id="notification-bell-demo-panel" count={2} target="notification-bell-demo-pop"/> <div id="notification-bell-demo-pop" popover="auto" style="margin: auto; padding: 14px 16px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-surface); color: var(--ui-fg); box-shadow: var(--ui-shadow-lg); font: 14px/1.5 var(--ui-font)"> <b>2 notifications</b><br/>Ana replied to your comment.<br/>The build finished. </div> <span.demo-note>This one opens a popover by its id.</span> </div> <NotificationBellDemoLive/> </div>Source
ui/notification_bell.qwe
// NotificationBell: a bell with the number of unread notifications on its corner, for// a navbar. It opens nothing itself: it is a link to the notifications page, or a// button that opens any panel (a popover by its id, or your own component's state).//// <NotificationBell count={3} href="/notifications"/>// <NotificationBell count={12} target="alerts-panel"/> opens <div id="alerts-panel" popover>…</div>// <NotificationBell count={n} on_click={() => { open = !open }}/>//// count: how many are unread; 0 shows no badge. limit: past it the badge says "99+"// (99). dot: a dot instead of the number, for when the count is unknown. href: makes it// a link. target: the id of a popover it opens (popovertarget). label: its name// ("Notifications"); screen readers hear "Notifications, 3 unread". size: "sm", "md"// (default) or "lg". ring: the bell swings once when the count goes up (CSS, on the// badge appearing; still for people who ask for less motion). on_click(): inside one// of your components, what a click does.import ui/theme.qwe use ui_clslet notification_bell_css = css`.ui-bell { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; padding: 0; border: 0; border-radius: var(--ui-radius-sm); background: transparent; color: var(--ui-fg); cursor: pointer; text-decoration: none; transition: background .12s;}.ui-bell:hover { background: var(--ui-subtle); }.ui-bell:focus-visible { outline: none; box-shadow: var(--ui-focus); }.ui-bell svg { width: 22px; height: 22px; transform-origin: 50% 4px; }.ui-bell-ring:has(.ui-bell-count) svg { animation: ui-bell-swing .8s ease-in-out 1; }@keyframes ui-bell-swing { 20% { transform: rotate(14deg); } 40% { transform: rotate(-12deg); } 60% { transform: rotate(8deg); } 80% { transform: rotate(-5deg); } }.ui-bell-count { position: absolute; top: 4px; left: 50%; margin-left: 2px; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px; border: 2px solid var(--ui-bg); background: var(--ui-danger); color: #fff; font: 700 10px/13px var(--ui-font); text-align: center; font-variant-numeric: tabular-nums;}.ui-bell-dot { min-width: 10px; height: 10px; padding: 0; margin-left: 4px; top: 6px; }.ui-bell-sm { width: 30px; height: 30px; }.ui-bell-sm svg { width: 18px; height: 18px; }.ui-bell-sm .ui-bell-count { top: 1px; margin-left: 0; }.ui-bell-lg { width: 46px; height: 46px; }.ui-bell-lg svg { width: 26px; height: 26px; }.ui-bell-lg .ui-bell-count { top: 6px; margin-left: 4px; }@media (prefers-reduced-motion: reduce) { .ui-bell { transition: none; } .ui-bell-ring:has(.ui-bell-count) svg { animation: none; } }`view NotificationBell(count: int = 0, limit: int = 99, dot: bool = false, href: str? = null, target: str? = null, label: str = "Notifications", size: str = "md", ring: bool = true, id: str? = null, on_click = null, class: str? = null) { style global notification_bell_css let cls = ui_cls(["ui-bell", size != "md" && `ui-bell-${size}`, ring && "ui-bell-ring", class]) let said = count > 0 ? `${label}, ${count} unread` : label let body = [ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 16V11a6 6 0 0 1 12 0v5l2 2H4zM10 21h4"/></svg>, count > 0 && <span class={ui_cls(["ui-bell-count", dot && "ui-bell-dot"])} aria-hidden="true">{dot ? "" : count > limit ? `${limit}+` : count}</span>, ] href != null ? <a class={cls} id={id} href={href} aria-label={said} title={label}>{body}</a> : <button class={cls} id={id} type="button" aria-label={said} title={label} popovertarget={target} @click={() => { on_click && on_click() }}>{body}</button>}Related
BackToTopA button in the corner that shows once the page is scrolled down and takes it back to the top.6 views · 8 downloadsBottomNavA fixed bar of icon tabs along the bottom of a phone's screen, with counts and the current one marked.6 views · 7 downloadsIconTabsTabs with an icon above each label and a count on its corner, the arrow keys moving between them.5 views · 6 downloadsDockA floating bar of icon buttons fixed to the bottom or a side of the page, with badges and the current one marked.6 views · 7 downloadsIconButtonA square button with an icon, labelled for screen readers and on hover; built-in icons or your own.6 views · 10 downloadsAccordionSections that open under their titles, on the browser's own <details>: exclusive with a group.5 views · 7 downloads
Thread
Thread 0 posts
On NotificationBell: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.