@htmlbricks/hb-layout-mobile
v0.76.5
Published
Mobile layout with optional offcanvas sidebar navigation, top navbar, main page slot, optional cookie-law banner, and footer. The host is fixed to the viewport height (100dvh). By default the main area scrolls and includes the cookie banner and footer aft
Readme
hb-layout-mobile
Category: layout · Tags: layout, shell, responsive · Package: @htmlbricks/hb-layout-mobile
Overview
hb-layout-mobile is a mobile-first application shell: optional offcanvas navigation (hb-offcanvas + hb-sidebar-desktop), a top hb-navbar, a primary page slot, an optional hb-cookie-law-banner, and hb-footer. It forwards navbar, footer, and navigation-related custom events to the host.
The host element is a fixed-height viewport column (100vh / 100dvh, overflow: hidden). The inner .hb-layout-mobile__shell is a flex column that stacks navbar, scrollable page region, and—depending on mode—cookie banner and footer.
Scroll modes
- Default (
single_screenoff or"no"): The main band (partpage) scrolls vertically. Inside it, the slot sits in a flex column with the cookie banner and footer so the slot grows when content is short, keeping the footer at the bottom of the scroll area (see.hb-layout-mobile__page--footer-insidein styles). Whenfooter.typeis"auto", the embedded footer uses theregularsize. single_screenon (any string except"no", or boolean true): Cookie banner and footer sit outside the scroll area at the bottom of the shell; only the page slot scrolls. Whenfooter.typeis"auto", the footer uses thesmallsize.
If you embed the host in a sized container instead of the full viewport, give ancestors a defined height and set height: 100% on hb-layout-mobile so the flex chain resolves.
Dependencies
The bundle registers nested packages (see extra/docs.ts): hb-footer (with hb-contact-item), hb-offcanvas (with hb-sidenav-link, hb-sidebar-desktop), hb-navbar (with hb-dropdown-simple), hb-cookie-law-banner, and hb-sidebar-desktop. Nested components ship their own Bulma scopes; theme tokens on the document still apply where shared.
Styling
Host and layout (SCSS)
styles/webcomponent.scss pins :host to full dynamic viewport height, hides overflow, and uses flex for the shell. The page area uses overflow-y: auto where scrolling applies. Bootstrap Icons are loaded for nested UI. styles/bulma.scss forwards Bulma flex helpers and host-scoped theme tokens so the shell can align with the Bulma variable system.
Theme variables (--bulma-*)
Set public Bulma CSS variables on :root / body (or any ancestor) so nested shadow roots that read them stay on-brand. Documented in extra/docs.ts:
| Variable | Role |
|----------|------|
| --hb-layout-navbar-background | Optional hb-navbar background (set on this host, hb-layout, or an ancestor). |
| --hb-layout-sidebar-background | Optional hb-sidebar-desktop background in offcanvas / shell. |
| --bulma-scheme-main | Default surfaces inside nested chrome. |
| --bulma-text | Primary text in navbar and footer. |
| --bulma-navbar-background-color | Bulma token consumed by hb-navbar (after optional layout / --hb-navbar-background-color). |
| --bulma-scheme-main-bis, --bulma-scheme-main-ter | Default hb-sidebar-desktop host background chain when layout sidebar override is unset. |
| --bulma-navbar-item-color | Navbar links and controls. |
| --bulma-footer-background-color | Footer background when hb-footer is used. |
| --bulma-link | Interactive accents (dropdowns, links). |
See Bulma CSS variables.
CSS parts
| Part | Description |
|------|-------------|
| container | Outer flex column stacking navbar, page, and (in single-screen mode) fixed cookie/footer. |
| navbar | Wrapper around hb-navbar for shell alignment. |
| page | Main column: scrollable viewport for content (and in default mode, cookie + footer inside the same scroll stack). |
| footer | Wrapper around the embedded hb-footer. |
HTML slots
| Slot | Description |
|------|-------------|
| nav-header-slot | Rendered in hb-offcanvas header span (only when navlinks is non-empty). |
| nav-left-slot | Forwarded to hb-navbar left-slot. |
| nav-center-slot | Forwarded to hb-navbar center-slot. |
| nav-right-slot | Forwarded to hb-navbar right-slot. |
| page | Primary content between navbar and footer/cookie stack. |
Custom element
hb-layout-mobile
Attributes (HTML)
Web component attributes use snake_case and string values. Objects and arrays must be JSON strings. Booleans from HTML are typically "yes" / "no" (this repo’s convention); some props also accept "true" / "false" where noted.
| Attribute | Description |
|-----------|-------------|
| id | Optional host identifier (typed on Component). |
| style | Optional inline style string (typed on Component). |
| company | JSON: company / brand payload for navbar and footer (ICompany). |
| contacts | JSON: footer contacts (IContacts). |
| socials | JSON: footer social links (ISocials). |
| navlinks | JSON: INavLink[]. When the array is non-empty, hb-offcanvas is rendered and the navbar shows the menu control; when empty or omitted, offcanvas is omitted and noburger is set on the navbar. |
| sidebar | JSON: offcanvas chrome — title, logo, type, optional enablefooter, enablethemeswitch ("yes" / "no" / "false" / empty). Passed through to hb-offcanvas / sidebar where used. |
| usermenu | JSON: IUserMenu for the navbar avatar dropdown. |
| pagename | Active navigation key for offcanvas (navpage on hb-offcanvas). |
| page_title | Navbar brand text (overrides company.siteName when set). |
| footer | JSON: { type?: "auto" \| "small" \| "regular" \| "large"; disable_expanding_small?: boolean }. Defaults to { type: "auto", disable_expanding_small: false } when coerced from string. |
| columns | JSON: IColumn[] for hb-footer. |
| policies | JSON: IPolicies[] for hb-footer. |
| cookielaw | "yes" / "true" (and other typed literals) — part of cookie banner visibility. |
| cookielawuri4more | Policy link URI string for the cookie banner. |
| cookielawlanguage | Language string for the cookie banner. |
| cookielawallowdecline | "yes" / "true" / "no" / "false" — banner decline behavior. |
| single_screen | String "no" disables single-screen mode; any other non-empty string enables it (coerced to boolean). Controls fixed footer/cookie vs scrolling layout (see above). |
| i18nlang | Language code passed into nested widgets (e.g. en, it). |
| i18nlanguages | JSON array { code, label }[] or string — language options for the offcanvas/sidebar path. |
Cookie banner visibility
hb-cookie-law-banner is rendered when any of the following holds: cookielaw is "yes" or "true", cookielawallowdecline is "yes" or "no", cookielawlanguage is a non-empty string, or cookielawuri4more is a non-empty string. The banner receives language from cookielawlanguage or i18nlang, plus allowdecline and cookielawuri4more.
Events
Custom events bubble from the host as declared in types/webcomponent.type.d.ts:
| Event | detail |
|-------|----------|
| offcanvasswitch | { isOpen: boolean } — from offcanvas or navbar menu switch. |
| pageChange | { page: string } — offcanvas page selection. |
| navbarDropDownClick | { key: string } — navbar dropdown entry. |
| footerClick | { elClick: string } — footer interaction key. |
| navbarSlotClick | { side: "left" \| "right" \| "center" } — navbar slot area click. |
| languageChange | Same shape as hb-sidebar-desktop languageChange (e.g. { code: string }). |
| themeChange | Same shape as hb-sidebar-desktop themeChange (theme preference). |
Usage notes
- Navigation icons:
navlinksentries use Bootstrap Icons names without thebi-prefix (e.g.house-door), consistent with other layout/nav components. - JSON props: At runtime,
footer,sidebar, andcompanymay be parsed from JSON strings in effects when passed as strings from attributes.
TypeScript (types/webcomponent.type.d.ts)
import type {
IContacts,
ISocials,
ICompany,
IColumn,
IPolicies,
} from "../../footer/types/webcomponent.type";
import type { IUserMenu } from "../../navbar/types/webcomponent.type";
import type { INavLink } from "../../sidenav-link/types/webcomponent.type";
import type { Events as SidebarDesktopEvents } from "../../sidebar-desktop/types/webcomponent.type";
export type I18nLanguageOption = { code: string; label: string };
export type Component = {
id?: string;
style?: string;
socials?: ISocials;
contacts?: IContacts;
company?: ICompany;
navlinks?: INavLink[];
pagename?: string;
page_title?: string;
usermenu?: IUserMenu;
cookielaw?: "yes" | "true" | "no" | "false" | null | "" | undefined;
columns?: IColumn[];
single_screen?: boolean;
cookielawuri4more?: string;
cookielawallowdecline?: "yes" | "true" | "no" | "false" | null | "" | undefined;
cookielawlanguage?: string;
sidebar?: {
title?: string;
logo?: string;
type?: string;
enablefooter?: "yes" | "no" | "false" | null | "" | undefined;
enablethemeswitch?: "yes" | "no" | "false" | null | "" | undefined;
};
footer?: {
type?: "auto" | "small" | "regular" | "large";
disable_expanding_small?: boolean;
};
policies?: IPolicies[];
i18nlang?: string;
i18nlanguages?: I18nLanguageOption[] | string;
};
export type Events = {
offcanvasswitch: { isOpen: boolean };
pageChange: { page: string };
navbarDropDownClick: { key: string };
footerClick: { elClick: string };
navbarSlotClick: { side: "left" | "right" | "center" };
languageChange: SidebarDesktopEvents["languageChange"];
themeChange: SidebarDesktopEvents["themeChange"];
};Minimal HTML example
<hb-layout-mobile i18nlang="en"></hb-layout-mobile>