Skip to content

Commit

Permalink
Merge pull request #18 from surjithctly/sticky-header
Browse files Browse the repository at this point in the history
feat: add sticky header utility
  • Loading branch information
surjithctly authored Oct 14, 2023
2 parents 9760684 + 5acf7e3 commit 7ca50be
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 2 deletions.
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Astro-Navbar is a fully responsive and accessible headless navigation bar for Astro, supporting nested dropdowns and mobile-responsive toggles.

### Live Demos

- [**Stackblitz**](https://stackblitz.com/edit/github-jpfnv9?file=src/pages/index.astro)
- [**Astroship Template**](https://astroship.web3templates.com/)

Expand All @@ -23,6 +24,7 @@ Ensure you have the `.hidden` class in your CSS. If not, add the following:
display: none;
}
```

Then integrate the navigation bar:

```astro
Expand Down Expand Up @@ -73,6 +75,7 @@ import { Astronav, MenuItems, MenuIcon, Dropdown, DropdownItems, DropdownSubmenu
</Astronav>
</div>
```

## Customization

### Styling
Expand Down Expand Up @@ -127,7 +130,7 @@ import { Astronav, MenuIcon, OpenIcon, CloseIcon } from "astro-navbar";

## Using with Tailwind CSS

Astro-Navbar pairs well with Tailwind CSS.
Astro-Navbar pairs well with Tailwind CSS.

<details>
<summary>Minimal Usage Example with Tailwind CSS</summary>
Expand Down Expand Up @@ -185,6 +188,35 @@ import { Astronav, MenuItems, MenuIcon, Dropdown, DropdownItems } from "astro-n

</details>

## Utilities

Some related utilities are provided for convenience.

### Sticky Header

To make the header sticky, you can use the `<StickyHeader />` component. This will help you to add custom classes to the header when scrolled such as `sticky`. Since this is a headless component, no sticky classes has been added by default. You can add your own classes. This utility adds a tiny JS snippet to detect scroll position in a performant way.

Here's an example:

```js
// Wrap the header with sticky header (renders as <header>...</header>)

<StickyHeader
// default class. applied all the time. No changes
class="sticky top-0 border-b z-20 transition-all"
// scroll threshold to enable active class
scrollY={50}
// initial classes which will be removed when scrollY reached
defaultClass="py-5 border-transparent"
// active classes to add when scrollY reached.
// "is-active" class will be added by default
activeClass="py-2 bg-white/80 border-gray-200 backdrop-blur-lg">
// ...
<Astronav>...</Astronav>
// ...
</StickyHeader>
```

## Options

Here are the supported options / props for this plugin.
Expand Down
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as MenuItems } from "./src/components/MenuItems.astro";
export { default as Dropdown } from "./src/components/Dropdown.astro";
export { default as DropdownSubmenu } from "./src/components/DropdownSubmenu.astro";
export { default as DropdownItems } from "./src/components/DropdownItems.astro";
export { default as StickyHeader } from "./src/components/StickyHeader.astro";
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "astro-navbar",
"version": "2.2.1",
"version": "2.3.0",
"description": "Responsive Mobile Navigation with Dropdown in Astro",
"type": "module",
"exports": "./index.ts",
Expand Down
58 changes: 58 additions & 0 deletions src/components/StickyHeader.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
interface Props {
scrollY?: number;
activeClass?: string;
defaultClass?: string;
class?: string;
}
const {
scrollY = 100,
defaultClass = "",
activeClass = "",
class: className = "",
} = Astro.props;
---

<header class:list={["astronav-sticky-header", className, defaultClass]}>
<slot />
</header>

<script define:vars={{ scrollY, defaultClass, activeClass }}>
let scrollPos = 0;
let ticking = false;

function OnScroll(scrollPos) {
const headers = document.querySelectorAll(".astronav-sticky-header");
const classArray = activeClass.split(" ");
const replaceArray = defaultClass.split(" ");

headers.forEach((header) => {
if (scrollPos > scrollY) {
header.classList.remove(...replaceArray);
header.classList.add("is-active", ...classArray);
header.setAttribute("active", "");
}
//reduce the scrollY to avoid flickering when scrolling up
if (scrollPos < Math.max(scrollY - 20, 0)) {
header.classList.remove("is-active", ...classArray);
header.classList.add(...replaceArray);
header.removeAttribute("active");
}
});
}

// Scroll event throttling as per MDN
// https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event

document.addEventListener("scroll", (event) => {
scrollPos = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(() => {
OnScroll(scrollPos);
ticking = false;
});

ticking = true;
}
});
</script>

0 comments on commit 7ca50be

Please sign in to comment.