How to use this component
The AppFrame
is a pure layout component that can be used to build the top-level “frame” of an application. The frame’s child containers (“header”, “sidebar”, “main”, “footer”) are agnostic of the content, and don’t have intrinsic sizes (apart from the ones that are required to make it work as top-level application frame).
“Main” container
The AppFrame::Main
child component includes a default id
with the value hds-main
on the HTML <main>
element it renders. This serves as a target for the hasA11yRefocus
feature skip links which are built into the AppHeader
and the standalone SideNav
components.
Note: The upcoming AppSideNav
component, which is meant to only be used together with the AppHeader
and not as standalone navigation, does not include a skip link.
Basic use
The most basic invocation of an application “frame” looks like this:
<div class="doc-app-frame-mock-viewport">
<Hds::AppFrame as |Frame|>
<Frame.Header>
{{! your "header" content goes here, this is just a mock placeholder }}
<Doc::Placeholder @height="60px" @text="header" @background="#e5ffd2" />
</Frame.Header>
<Frame.Sidebar>
{{! your "sidebar" content goes here, this is just a mock placeholder }}
<Doc::Placeholder @width="120px" @height="100%" @text="sidebar" @background="#e4c5f3" />
</Frame.Sidebar>
<Frame.Main>
{{! your "main" content goes here, this is just a mock placeholder }}
<Doc::Placeholder @height="100%" @text="main" @background="#d2f4ff" />
</Frame.Main>
<Frame.Footer>
{{! your "footer" content goes here, this is just a mock placeholder }}
<Doc::Placeholder @height="60px" @text="footer" @background="#fff8d2" />
</Frame.Footer>
</Hds::AppFrame>
</div>
Optional containers
Depending on the UI implementation of the product where the component is used, it's possible to omit certain containers simply by not yielding them. For example, this would be the “frame” of an application that doesn't have a “header”:
<div class="doc-app-frame-mock-viewport">
<Hds::AppFrame as |Frame|>
<Frame.Sidebar>
<Doc::Placeholder @width="120px" @height="100%" @text="sidebar" @background="#e4c5f3" />
</Frame.Sidebar>
<Frame.Main>
<Doc::Placeholder @height="100%" @text="main" @background="#d2f4ff" />
</Frame.Main>
<Frame.Footer>
<Doc::Placeholder @height="60px" @text="footer" @background="#fff8d2" />
</Frame.Footer>
</Hds::AppFrame>
</div>
Programmatic control of the containers’ rendering
Using the exposed API of the component, it's possible to programmatically control the rendering of some of the containers. An example of programmatic control of the rendering of the sidebar could be this:
<div class="doc-app-frame-mock-viewport">
<Hds::AppFrame as |Frame|>
{{! conditional control of the rendering of the "sidebar" }}
{{#if this.yourSidebarBooleanFlag}}
<Frame.Sidebar>
<Doc::Placeholder @width="120px" @height="100%" @text="sidebar" @background="#e4c5f3" />
</Frame.Sidebar>
{{/if}}
<Frame.Main>
<Doc::Placeholder @height="100%" @text="main" @background="#d2f4ff" />
</Frame.Main>
<Frame.Footer>
<Doc::Placeholder @height="60px" @text="footer" @background="#fff8d2" />
</Frame.Footer>
</Hds::AppFrame>
</div>
If for some reason it's not possible to use conditional logic to control the yielding of the containers, we provide an alternative way using special has[Container]
arguments to programmatically control the rendering (see the component API specifications for details):
<div class="doc-app-frame-mock-viewport">
<Hds::AppFrame @hasSidebar={{false}} as |Frame|>
<Frame.Sidebar>
<Doc::Placeholder @width="120px" @height="100%" @text="sidebar" @background="#e4c5f3" />
</Frame.Sidebar>
<Frame.Main>
<Doc::Placeholder @height="100%" @text="main" @background="#d2f4ff" />
</Frame.Main>
<Frame.Footer>
<Doc::Placeholder @height="60px" @text="footer" @background="#fff8d2" />
</Frame.Footer>
</Hds::AppFrame>
</div>
Modals container
We also provide an extra container that can be used to display content that sits on top of all the other elements of the page (typically modal elements):
<div class="doc-app-frame-mock-viewport">
<Hds::AppFrame as |Frame|>
<Frame.Header>
<Doc::Placeholder @height="60px" @text="header" @background="#e5ffd2" />
</Frame.Header>
<Frame.Sidebar>
<Doc::Placeholder @width="120px" @height="100%" @text="sidebar" @background="#e4c5f3" />
</Frame.Sidebar>
<Frame.Main>
<Doc::Placeholder @height="100%" @text="main" @background="#d2f4ff" />
</Frame.Main>
<Frame.Footer>
<Doc::Placeholder @height="60px" @text="footer" @background="#fff8d2" />
</Frame.Footer>
<Frame.Modals>
{{! your "modal" content goes here, this is just a mock placeholder }}
<div class="doc-app-frame-fake-overlay" />
<div class="doc-app-frame-fake-modal">
<Doc::Placeholder @width="100%" @height="100%" @text="modal" @background="#ffffffb5" />
</div>
</Frame.Modals>
</Hds::AppFrame>
</div>
If the content is injected dynamically—eg. via JavaScript or via Ember "portals"—you can assign an ID to the HTML element so that it can be targeted in the DOM by the code:
<div class="doc-app-frame-mock-viewport">
<Hds::AppFrame as |Frame|>
<Frame.Sidebar>
...
</Frame.Sidebar>
<Frame.Main>
...
</Frame.Main>
{{! assign an ID to the element to target it in the DOM }}
<Frame.Modals id="app-frame-modals" data-test-modals-container />
</Hds::AppFrame>
</div>
Component API
AppFrame
<[AF].Header>
yielded component
AppFrame::Header
yielded as contextual component (see below).
<[AF].Sidebar>
yielded component
AppFrame::Sidebar
yielded as contextual component (see below).
<[AF].Main>
yielded component
AppFrame::Main
yielded as contextual component (see below).
<[AF].Footer>
yielded component
AppFrame::Footer
yielded as contextual component (see below).
<[AF].Modals>
yielded component
AppFrame::Modals
yielded as contextual component (see below).
hasHeader
boolean
- true (default)
header
container.
hasSidebar
boolean
- true (default)
sidebar
container.
hasFooter
boolean
- true (default)
footer
container.
hasModals
boolean
- true (default)
modals
container.
…attributes
...attributes
.
Contextual components
[AF].Header
The AppFrame::Header
component, yielded as contextual component.
To be used as container for the application's top navigation.
yield
<header>
HTML element.
…attributes
...attributes
.
[AF].Sidebar
The AppFrame::Sidebar
component, yielded as contextual component.
To be used as container for the application's sidebar navigation.
yield
<aside>
HTML element.
…attributes
...attributes
.
[AF].Main
The AppFrame::Main
component, yielded as contextual component.
To be used as container for the application's main page content.
yield
<main>
HTML element.
id
- "hds-main" (default)
…attributes
...attributes
.
[AF].Footer
The AppFrame::Footer
component, yielded as contextual component.
To be used as container for the application's footer.
yield
<footer>
HTML element.
…attributes
...attributes
.
[AF].Modals
The AppFrame::Modals
component, yielded as contextual component.
To be used as container for modal elements.
yield
<div>
HTML element.
…attributes
...attributes
.
4.10.0
Updated
AppFrame
- Modified sticky/fixed position to turn off when viewport height is under 480px in height
- Refactored styles to make
AppFrame
responsible for sticky/fixed layout ofSideNav
andAppHeader
AppFrame::Main
- Added
id
with default value of "hds-main" which theSideNav
andAppHeader
a11yRefocusSkipTo
arguments point to.