Skip to content

Commit

Permalink
Add mobile nav button and enable search
Browse files Browse the repository at this point in the history
  • Loading branch information
etaoxing committed Feb 12, 2025
1 parent ed0e4b4 commit ae7ebe4
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 68 deletions.
57 changes: 30 additions & 27 deletions src/components/Header.astro
Original file line number Diff line number Diff line change
@@ -1,45 +1,38 @@
---
import config from 'virtual:starlight/user-config'
import type { Props } from '@astrojs/starlight/props'
import LanguageSelect from 'virtual:starlight/components/LanguageSelect'
import Search from 'virtual:starlight/components/Search'
import SiteTitle from 'virtual:starlight/components/SiteTitle'
import SocialIcons from 'virtual:starlight/components/SocialIcons'
import ThemeSelect from 'virtual:starlight/components/ThemeSelect'
import Nav from './Nav.astro'
/**
* Render the `Search` component if Pagefind is enabled or the default search component has been overridden.
*/
const shouldRenderSearch = false
/**
config.pagefind ||
config.components.Search !== '@astrojs/starlight/components/Search.astro'
*/
---

<div class="unselectable title-wrapper sl-flex">
<SiteTitle {...Astro.props} />
</div>
<div class="unselectable sl-flex">
<Nav {...Astro.props} />
</div>
<!--
<div class="sl-flex print:hidden">
{shouldRenderSearch && <Search {...Astro.props} />}
</div>
-->
<div class="sl-hidden md:sl-flex print:hidden right-group">
<div class="sl-flex social-icons">
<SocialIcons {...Astro.props} />
<div class="header sl-flex">
<div class="unselectable title-wrapper sl-flex">
<SiteTitle {...Astro.props} />
</div>
<div class="unselectable nav sl-flex">
<Nav {...Astro.props} />
</div>
<div class="unselectable sl-hidden md:sl-flex print:hidden right-group">
<div class="sl-flex social-icons">
<SocialIcons {...Astro.props} />
</div>
<ThemeSelect {...Astro.props} />
<!-- <LanguageSelect {...Astro.props} /> -->
</div>
<ThemeSelect {...Astro.props} />
<!-- <LanguageSelect {...Astro.props} /> -->
</div>

<style>
.header {
gap: var(--sl-nav-gap);
justify-content: space-between;
align-items: center;
height: 100%;
}

.title-wrapper {
/* Prevent long titles overflowing and covering the search and menu buttons on narrow viewports. */
overflow: clip;
Expand All @@ -49,6 +42,10 @@ const shouldRenderSearch = false
min-width: 0;
}

.nav {
justify-self: right;
}

.right-group,
.social-icons {
gap: 1rem;
Expand Down Expand Up @@ -98,4 +95,10 @@ const shouldRenderSearch = false
align-content: center;
}
}

@media (min-width: 72rem) {
.nav {
justify-self: left;
}
}
</style>
164 changes: 150 additions & 14 deletions src/components/Nav.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
---
import type { Props } from '@astrojs/starlight/props'
import { Icon } from '@astrojs/starlight/components'
import config from 'virtual:starlight/user-config'
import Search from 'virtual:starlight/components/Search'
const path = new URL(Astro.request.url).pathname
const navItems = [
Expand All @@ -8,24 +14,71 @@ const navItems = [
{ href: '/talks', label: 'Talks' },
{ href: '/teaching', label: 'Teaching' },
]
/**
* Render the `Search` component if Pagefind is enabled or the default search component has been overridden.
*/
const shouldRenderSearch =
config.pagefind ||
config.components.Search !== '@astrojs/starlight/components/Search.astro'
// mobile menu design from https://github.com/h-enk/henkverlinde.com/blob/main/src/components/Navbar.astro
---

<nav class="sl-flex">
{
navItems.map((item) => (
<a class={path.startsWith(item.href) ? 'active' : ''} href={item.href}>
{item.label}
</a>
))
}
<div class="nav-items sl-flex">
{
navItems.map((item) => (
<a class={path.startsWith(item.href) ? 'active' : ''} href={item.href}>
{item.label}
</a>
))
}
</div>
<button
class="mobile-nav-toggle"
aria-label={Astro.locals.t('menuButton.accessibleLabel')}
>
<Icon
name="bars"
class="menu-closed"
size="1.25rem"
color="var(--sl-color-text-accent)"
/>
<Icon
name="close"
class="menu-open"
size="1.25rem"
color="var(--sl-color-text-accent)"
/>
</button>
{shouldRenderSearch && <span>/</span>}
<div class="sl-flex print:hidden">
{shouldRenderSearch && <Search {...Astro.props} />}
</div>
</nav>

<script is:inline>
const navToggle = document.querySelector('.mobile-nav-toggle')
navToggle?.addEventListener('click', () => {
navToggle.classList.toggle('active')
document.querySelector('nav').classList.toggle('active')
})
</script>

<style>
/* Desktop styles */
nav {
justify-content: space-between;
gap: var(--sl-nav-gap);
align-items: inherit;
flex-flow: row wrap;
align-items: center;
}

.nav-items {
gap: var(--sl-nav-gap);
margin: 0;
padding: 0;
align-items: center;
}

a:first-of-type {
Expand All @@ -38,20 +91,103 @@ const navItems = [
white-space: nowrap;
margin: 0 0.1rem;
border-bottom: 1.5px solid var(--sl-color-bg-nav);
transition: opacity 0.2s ease-out;
transition:
opacity 0.2s ease-out,
color 0.2s ease-out,
border-color 0.2s ease-out;
color: var(--sl-color-text-accent);
font-weight: bold;
}

a:hover {
nav a:hover,
nav a:focus-visible,
nav a.active {
opacity: 0.66;
border-color: var(--sl-color-text-accent);
}

a:hover,
.active {
border-color: var(--sl-color-text-accent);
/* Mobile menu toggle button */
.mobile-nav-toggle {
display: none;
height: 2.5rem;
aspect-ratio: 1 / 1;
border: 1.5px solid var(--sl-color-text-accent);
border-radius: 0.5rem;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 2;
background: var(--sl-color-bg-nav);
}

.menu-open {
display: none;
}

.mobile-nav-toggle.active .menu-open {
display: flex;
}

.mobile-nav-toggle.active .menu-closed {
display: none;
}

/* Mobile styles */
@media (max-width: 56em) {
nav {
transition: all 0.2s ease;
}

.mobile-nav-toggle {
display: flex;
}

.nav-items {
flex-direction: column;
gap: 0;
position: absolute;
width: 100%;
top: calc(1rem + 40px);
right: 0;
padding: 1rem;
z-index: 1;
opacity: 0;
pointer-events: none;
transition: all 0.2s ease;
user-select: none;
height: calc(100vh - 1rem - 40px);
align-items: start;
}

nav.active {
background-color: var(--sl-color-bg-nav);
}

/* When the nav is toggled open, show the nav links */
nav.active .nav-items {
opacity: 1;
pointer-events: all;
background-color: var(--sl-color-bg-nav);
}

.nav-items a {
display: block;
padding: 0.75rem 0;
padding-left: 1rem;
width: 100%;
margin: 0;
font-size: 1.125em;
}

.nav-items a {
border-bottom: 1px solid var(--sl-color-hairline-shade);
}
.nav-items a:first-child {
border-top: 1px solid var(--sl-color-hairline-shade);
}

nav.active a {
top: 0;
}
}
</style>
1 change: 1 addition & 0 deletions src/content/docs/index.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Homepage
description: Bot Intelligence Group, in the Robotics Institute at Carnegie Mellon University.
pagefind: false
template: splash
hero:
title: Bot Intelligence Group
Expand Down
32 changes: 5 additions & 27 deletions src/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,18 @@ https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
}
}

.main-frame {
padding-top: var(
--sl-mobile-toc-height
); /* remove nav height padding since not fixed */
}

.header {
display: flex;
position: relative;
height: 100%;
flex-flow: row wrap;
justify-content: space-between;
align-items: center;
gap: clamp(1rem, 4vw, 2rem);
}

.site-title {
transition: opacity 0.2s;
}
.site-title:hover {
opacity: 0.66;
}

/* hide title (since only 1-level deep */
.pagefind-ui__result-nested > .pagefind-ui__result-title {
font-size: 0 !important;
}

/* Hero.astro */
.hero {
padding-block: unset;
Expand All @@ -60,17 +49,6 @@ https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
}

@media (min-width: 50rem) {
.header {
height: var(--sl-nav-height);
position: fixed;
display: flex;
flex-direction: row;
}

.main-frame {
padding-top: calc(var(--sl-nav-height) + var(--sl-mobile-toc-height));
}

.hero {
grid-template-columns: 9fr 4fr;
}
Expand Down

0 comments on commit ae7ebe4

Please sign in to comment.