Skip to content

Commit

Permalink
chore: mobile sidebars
Browse files Browse the repository at this point in the history
  • Loading branch information
jer3m01 committed Oct 23, 2024
1 parent 216356e commit 728e87f
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 66 deletions.
46 changes: 38 additions & 8 deletions src/client/components/Article.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
position: sticky;
top: calc(var(--header-height) + 2rem - var(--header-offset));
max-height: calc(100dvh - var(--header-height) - 4rem + var(--header-offset));
width: 12rem;
right: 0;
transition: transform 0.3s ease-in-out;
overflow-y: auto;
Expand All @@ -23,14 +24,6 @@
.article {
margin: 2rem 1.25rem;
}

.aside {
position: fixed;
top: 0;
right: 0;
height: 100dvh;
transform: translateX(100%);
}
}

.info {
Expand Down Expand Up @@ -75,3 +68,40 @@
.next {
align-items: flex-end;
}

.sidenav {
position: fixed;
right: 0;
top: 0;
height: 100dvh;
z-index: 51;
width: 70dvw;
background: var(--background-color);
animation: contentHide 300ms ease-out forwards;
padding: 1rem;

&[data-expanded] {
animation: contentShow 300ms ease-out;
}
}

@keyframes contentShow {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes contentHide {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(100%);
}
}
33 changes: 26 additions & 7 deletions src/client/components/Article.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { solidBaseConfig } from "virtual:solidbase";
import { Dialog } from "@kobalte/core/dialog";
import { WindowEventListener } from "@solid-primitives/event-listener";
import { createShortcut } from "@solid-primitives/keyboard";
import { isAppleDevice } from "@solid-primitives/platform";
import { type ParentProps, Show, createSignal } from "solid-js";
import { useSolidBaseContext } from "../context";
import { mobileLayout } from "../globals";
import { useCurrentPageData } from "../page-data";
import { usePrevNext, useSidebar } from "../sidebar";
import { usePrevNext } from "../sidebar";
import styles from "./Article.module.css";
import layoutStyles from "./Layout.module.css";

export default function Article(props: ParentProps) {
const { TableOfContents, Link, LastUpdated, Footer } =
useSolidBaseContext().components;
const {
components: { TableOfContents, Link, LastUpdated, Footer },
tocOpen,
setTocOpen,
} = useSolidBaseContext();

const [contentRef, setContentRef] = createSignal<HTMLElement>();

Expand Down Expand Up @@ -110,9 +115,23 @@ export default function Article(props: ParentProps) {
</Show>
</div>

<aside class={styles.aside}>
<TableOfContents />
</aside>
<Show
when={mobileLayout()}
fallback={
<aside class={styles.aside}>
<TableOfContents />
</aside>
}
>
<Dialog open={tocOpen()} onOpenChange={setTocOpen}>
<Dialog.Portal>
<Dialog.Overlay class={layoutStyles["sidenav-overlay"]} />
<Dialog.Content class={styles.sidenav}>
<TableOfContents />
</Dialog.Content>
</Dialog.Portal>
</Dialog>
</Show>
</article>
</>
);
Expand Down
34 changes: 28 additions & 6 deletions src/client/components/Header.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
}

html {
--header-height: 5.5rem !important;
--header-height: 6.5rem !important;
}
}

@media screen and (min-width: 1100px) {
.mobile-menu {
display: none;
.mobile-bar {
display: none !important;
}
}

Expand All @@ -55,12 +55,26 @@
background: transparent;
border-radius: var(--border-radius);
color: var(--text-color);
padding: 0.25rem;
font-size: .8rem;
padding: 0.5rem;
cursor: var(--button-cursor);
display: flex;
align-items: center;
gap: .5rem;
margin: 0 -.5rem;
text-decoration: none;
transition-property: background-color, color;
transition-timing-function: var(--transition-timing);
transition-duration: .15s;

&:hover,
&:focus {
background: color-mix(in hsl, var(--text-color) 10%, transparent);
&:focus-visible {
color: var(--heading-color);
background: color-mix(in hsl, var(--link-underline-color) 20%, transparent);
}

&.active {
color: var(--active-link-color);
}

& svg {
Expand Down Expand Up @@ -105,3 +119,11 @@
}
}
}

.mobile-bar {
flex: none !important;
border-top: 1px solid
color-mix(in hsl, var(--decoration-color) 15%, transparent);
margin: 0 -4rem;
padding: .25rem 4rem;
}
22 changes: 12 additions & 10 deletions src/client/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ import { useSolidBaseContext } from "../context";
import { mobileLayout } from "../globals";
import { getLocaleLink } from "../locale";
import styles from "./Header.module.css";
import { MenuIcon } from "./icons";
import { MenuLeftIcon, MenuRightIcon } from "./icons";

const DocSearch = lazy(() => import("./DocSearch"));

const BUFFER_MULT = 3;

interface HeaderProps {
setSidebarOpen: Setter<boolean>;
}
interface HeaderProps {}

export default function Header(props: HeaderProps) {
const [ref, setRef] = createSignal<HTMLElement>();

const { ThemeSelector, LocaleSelector } = useSolidBaseContext().components;
const {
components: { ThemeSelector, LocaleSelector },
setSidebarOpen,
setTocOpen,
} = useSolidBaseContext();

const scroll = useWindowScrollPosition();
const [offset, setOffset] = createSignal(0);
Expand Down Expand Up @@ -128,18 +130,18 @@ export default function Header(props: HeaderProps) {
<button
type="button"
class={styles["mobile-menu"]}
onClick={() => props.setSidebarOpen((p) => !p)}
onClick={() => setSidebarOpen((p) => !p)}
aria-label="Open navigation"
>
<MenuIcon /> Menu
<MenuLeftIcon /> Menu
</button>
<button
type="button"
class={styles["mobile-menu"]}
onClick={() => props.setSidebarOpen((p) => !p)}
aria-label="Open table of contenst"
onClick={() => setTocOpen((p) => !p)}
aria-label="Open table of contents"
>
On this page
On this page <MenuRightIcon />
</button>
</div>
</header>
Expand Down
27 changes: 3 additions & 24 deletions src/client/components/Layout.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
top: 0;
height: 100dvh;
z-index: 51;
min-width: 80%;
width: 70dvw;
background: var(--background-color);
animation: contentHide 300ms ease-out forwards;

Expand Down Expand Up @@ -163,27 +163,6 @@
}
}

.sidenav-close-btn {
appearance: none;
outline: none;
border: none;
background: transparent;
border-radius: var(--border-radius);
color: var(--text-color);
padding: 0.5rem;
cursor: var(--button-cursor);

&:hover,
&:focus {
background: color-mix(in hsl, var(--text-color) 10%, transparent);
}

& svg {
width: 1.25rem;
height: 1.25rem;
}
}

@keyframes overlayShow {
from {
opacity: 0;
Expand Down Expand Up @@ -214,10 +193,10 @@
@keyframes contentHide {
from {
opacity: 1;
transform: translateX(-100%);
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(0);
transform: translateX(-100%);
}
}
9 changes: 3 additions & 6 deletions src/client/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ export default function Layout(props: ParentProps) {
const {
config,
components: { Header, Article },
sidebarOpen,
setSidebarOpen,
} = useSolidBaseContext();

const pageData = useCurrentPageData();

const [sidebarOpen, setSidebarOpen] = createSignal(false);

const sidebar = useSidebar();

createEffect(() =>
Expand Down Expand Up @@ -78,7 +78,7 @@ export default function Layout(props: ParentProps) {
</Show>

<div class={styles.layout}>
<Header setSidebarOpen={setSidebarOpen} />
<Header />

<Show
when={sidebar() && sidebar()!.items?.length > 0}
Expand Down Expand Up @@ -108,9 +108,6 @@ export default function Layout(props: ParentProps) {
<img src={config().logo} alt={config().title} />
</Show>
</a>
<Dialog.CloseButton class={styles["sidenav-close-btn"]}>
<CrossIcon />
</Dialog.CloseButton>
</div>
<Navigation sidebar={sidebar()!} />
</div>
Expand Down
19 changes: 15 additions & 4 deletions src/client/components/TableOfContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { type TableOfContentData, useCurrentPageData } from "../page-data";
import styles from "./TableOfContents.module.css";

export default function TableOfContents(props: {}) {
export default function TableOfContents(props: { scrollspy?: boolean }) {
const toc = () => useCurrentPageData()().toc;

const [currentSection, setCurrentSection] = createSignal<string | undefined>(
Expand All @@ -24,7 +24,7 @@ export default function TableOfContents(props: {}) {
>([]);

createEffect(() => {
if (!toc()) return [];
if (!toc() || !props.scrollspy) return [];
setHeadingPositions(
flattenData(toc()!).map((url) => {
const el = document.getElementById(url.slice(1));
Expand All @@ -51,6 +51,8 @@ export default function TableOfContents(props: {}) {
});

createEffect(() => {
if (!props.scrollspy) return;

const top = scroll.y;
let current = headingPositions()[0]?.url;

Expand All @@ -72,7 +74,11 @@ export default function TableOfContents(props: {}) {
<nav class={styles.toc}>
<span>On This Page</span>
<ol>
<TableOfContentsItem data={toc()!} current={currentSection()} />
<TableOfContentsItem
data={toc()!}
current={currentSection()}
scrollspy={!!props.scrollspy}
/>
</ol>
</nav>
</Show>
Expand All @@ -82,6 +88,7 @@ export default function TableOfContents(props: {}) {
function TableOfContentsItem(props: {
data: TableOfContentData;
current: string | undefined;
scrollspy: boolean;
}) {
const [ref, setRef] = createSignal<HTMLElement>();

Expand Down Expand Up @@ -120,7 +127,11 @@ function TableOfContentsItem(props: {
<ol>
<For each={props.data.children}>
{(nested) => (
<TableOfContentsItem data={nested} current={props.current} />
<TableOfContentsItem
data={nested}
current={props.current}
scrollspy={props.scrollspy}
/>
)}
</For>
</ol>
Expand Down
17 changes: 17 additions & 0 deletions src/client/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ export function MenuIcon(props: ComponentProps<"svg">) {
);
}

export function MenuLeftIcon(props: ComponentProps<"svg">) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
{...props}
>
<path d="M3 4H21V6H3V4ZM3 11H15V13H3V11ZM3 18H21V20H3V18Z" />
</svg>
);
}

export function MenuRightIcon(props: ComponentProps<"svg">) {
return <MenuLeftIcon style="transform: scaleX(-1)" {...props} />;
}

export function CrossIcon(props: ComponentProps<"svg">) {
return (
<svg
Expand Down
Loading

0 comments on commit 728e87f

Please sign in to comment.