-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Editable site menu #196
Comments
I made a quick PoC for this feature in a clone of the No Dodos website, since it relied on the new linked record routing already in place there. My findings: Result in the browser: Works well to have a modular content field for I used a menu item that supported nested I used a single menu item for all 3 types of items, with a required I introduced the external link model so it would be just as easy to link to an external as an internal page. But that gives a bit of an odd behaviour the next time you want to select a record to link to as suddenly that external url is an option you can select: I discussed this with @jurgenbelien and would now instead opt for 3 separate menu item blocks:
This setup is open for extension and more suitable for a customisable setup that Head Start strives to be. And it allows for stricter requirements on each block:
Now for example an easy extension could be that each group item has an |
For the implementation above, these are some of the code highlights:
#import '@lib/routing/PageRoute.fragment.graphql'
fragment MenuItem on MenuItemRecord {
id
title
link {
__typename
... on HomePageRecord {
title
}
... on PageRecord {
title
...PageRoute
}
... on ExternalLinkRecord {
title: url
url
}
}
}
---
import MenuItem from '@blocks/MenuItem/MenuItem.astro';
const { items } = Astro.props;
---
<nav aria-label="Site menu">
<ul>
{items.map((item) => <MenuItem item={item} />)}
</ul>
</nav>
---
import type { MenuItemFragment, SiteLocale } from '@lib/types/datocms';
import { getLocale } from '@lib/i18n';
import { getHref } from '@lib/routing';
export type MenuItem = MenuItemFragment & {
items: MenuItem[];
};
interface Props {
item: MenuItem;
level?: number;
}
const {
item: { title, link, items },
level = 1,
} = Astro.props;
const locale = getLocale() as SiteLocale;
---
<li class={`level-${level}`}>
{
link ? (
link.__typename === 'ExternalLinkRecord' ? (
<a href={link.url} target='_blank'>
{title}
</a>
) : (
<a href={getHref({ locale, record: link })}>{title}</a>
)
) : (
title
)
}
{
items.length ? (
<ul>
{items.map((item) => (
<Astro.self item={item} level={level + 1} />
))}
</ul>
) : null
}
</li> usage in layout: #import '@blocks/MenuItem/MenuItem.fragment.graphql'
query DefaultLayout($locale: SiteLocale!) {
# ...
app(locale: $locale) {
# ...
menuItems {
...MenuItem
items {
...MenuItem
items {
...MenuItem
items {
...MenuItem
items {
...MenuItem
}
}
}
}
}
}
}
<AppMenu items={data.app.menuItems} /> |
Reference implementation of responsive menu (no nesting) in No Dodos website: |
Should we implement this in 2 stages (separate PRs)?:
Q: can ... link menu items have sub items or should only group items be able to have those? Maybe dependents on the desired UI and patterns? |
User stories
As a website visitor,
I want to have access to an app/site menu,
so that I get an overview of the site content/structure and can directly navigate to pages.
As a content editor,
I want to be able to edit/compose the app/site menu,
so that I can guide users to specific pages.
Requirements
<nav>
witharia-label
oraria-labelledby
).Example menu (taking Head Start itself as an example):
The text was updated successfully, but these errors were encountered: