Skip to content

Commit 099d69a

Browse files
markdumayclaude
andcommitted
feat: add menu bookshop content block for hierarchical navigation
Introduces a new Bookshop content block for rendering hierarchical menu structures with customizable styling and layout options. Supports both grid and masonry layouts with icon support and responsive column configuration. Features: - Grid and masonry layout modes for flexible presentation - Hierarchical menu rendering with parent-child relationships - Icon support with optional rounded styling - Responsive column configuration (1-6 columns) - Automatic integration with Hugo menu system - Section title support with configurable alignment Components: - menu.hugo.html: Main bookshop component template - menu.html: Reusable partial for menu rendering - menu-item.html: Individual menu item with children support - menu.bookshop.yml: Schema definition for CMS integration - menu.scss: Component-specific styles with masonry and grid layouts The component leverages the refactored navbar-item partial for consistent rendering of menu entries and supports all Hugo menu configuration options including weights, icons, and custom parameters. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 476a38f commit 099d69a

File tree

10 files changed

+529
-1
lines changed

10 files changed

+529
-1
lines changed

component-library/bookshop.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
@import "modules/bookshop/components/featured/featured";
99
@import "modules/bookshop/components/hero/hero";
1010
@import "modules/bookshop/components/list/list";
11+
@import "modules/bookshop/components/menu/menu";
1112
@import "modules/bookshop/components/panels/panels";
1213
@import "modules/bookshop/components/releases/releases";
1314
@import "modules/bookshop/components/separator/separator";
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Metadata about this component, to be used in the CMS
2+
spec:
3+
structures:
4+
- content_blocks
5+
label: Menu
6+
description: Index of menu items
7+
icon: menu
8+
tags: []
9+
10+
# Defines the structure of this component, as well as the default values
11+
blueprint:
12+
heading:
13+
preheading:
14+
heading:
15+
content:
16+
align:
17+
width:
18+
cols:
19+
menu:
20+
menu-style:
21+
icon-rounded: false
22+
icon-style:
23+
background:
24+
backdrop:
25+
color:
26+
subtle:
27+
class:
28+
width:
29+
justify:
30+
fluid:
31+
theme:
32+
cover:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{{/*
2+
Copyright © 2025 The Hinode Team / Mark Dumay. All rights reserved.
3+
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
4+
Visit gethinode.com/license for more details.
5+
*/}}
6+
7+
{{ $error := false }}
8+
9+
{{/* Initialize arguments */}}
10+
{{ $args := partial "utilities/InitArgs.html" (dict "bookshop" "menu" "args" .)}}
11+
{{ if or $args.err $args.warnmsg }}
12+
{{ partial (cond $args.err "utilities/LogErr.html" "utilities/LogWarn.html") (dict
13+
"partial" "component-library/components/menu/menu.hugo.html"
14+
"warnid" "warn-invalid-arguments"
15+
"msg" "Invalid arguments"
16+
"details" ($args.errmsg | append $args.warnmsg)
17+
"file" page.File
18+
)}}
19+
{{ $error = $args.err }}
20+
{{ end }}
21+
22+
{{/* Initialize global arguments */}}
23+
{{- $padding := partial "utilities/GetPadding.html" -}}
24+
25+
{{/* Main code */}}
26+
{{ if not $error }}
27+
{{- partial "assets/section-title.html" (dict
28+
"heading" $args.heading
29+
"justify" $args.justify
30+
"class" (printf "pb-%d" $padding.y))
31+
-}}
32+
33+
{{- partial "assets/menu.html" (dict
34+
"page" page
35+
"menu" $args.menu
36+
"menu-style" $args.menuStyle
37+
"cols" $args.cols
38+
"icon-rounded" $args.iconRounded
39+
"icon-style" $args.iconStyle
40+
) -}}
41+
{{ end }}
42+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
section.menu {
2+
.m-col div, .col div {
3+
border-radius: #{$theme-border-radius} if($enable-important-utilities, !important, null);
4+
}
5+
6+
.menu-item {
7+
--bs-menu-border: var(--bs-border-color);
8+
--bs-menu-color-hover: var(--bs-light);
9+
--bs-menu-background-hover: var(--bs-primary);
10+
--bs-menu-item-color-hover: var(--bs-gray-300);
11+
12+
position: relative;
13+
border: solid var(--bs-menu-border);
14+
15+
&:hover,
16+
&:focus {
17+
background-color: var(--bs-menu-background-hover) if($enable-important-utilities, !important, null);
18+
color: var(--bs-menu-color-hover) if($enable-important-utilities, !important, null);
19+
transition-property: background-color, border-color;
20+
transition-duration: .3s;
21+
transition-timing-function: ease-in-out;
22+
23+
.fa-inverse {
24+
color: var(--bs-menu-background-hover);
25+
}
26+
}
27+
}
28+
29+
.menu-link {
30+
// make menu-link clickable on top of the stretched-link.
31+
z-index: 2 if($enable-important-utilities, !important, null);
32+
position: relative;
33+
34+
&:hover,
35+
&:focus {
36+
color: var(--bs-menu-item-color-hover) if($enable-important-utilities, !important, null);
37+
}
38+
}
39+
40+
.menu-link-header {
41+
font-weight: $font-weight-bold if($enable-important-utilities, !important, null);
42+
font-size: $h5-font-size if($enable-important-utilities, !important, null);
43+
}
44+
}

data/structures/menu-item.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
comment: Renders a menu item.
2+
arguments:
3+
page:
4+
menu-entry:
5+
menu-style:
6+
type: select
7+
optional: true
8+
default: masonry
9+
comment: Style of the menu layout.
10+
options:
11+
values:
12+
- grid
13+
- masonry
14+
cols:
15+
default: 3
16+
icon-rounded:
17+
icon-style:
18+
padding:
19+
class:

data/structures/menu.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
comment: Display a menu section.
2+
arguments:
3+
page:
4+
menu:
5+
type: string
6+
optional: true
7+
default: main
8+
comment: Name of the site menu.
9+
menu-style:
10+
type: select
11+
optional: true
12+
default: masonry
13+
comment: Style of the menu layout.
14+
options:
15+
values:
16+
- grid
17+
- masonry
18+
cols:
19+
default: 3
20+
icon-rounded:
21+
icon-style:
22+
padding:

exampleSite/config/_default/menus/menus.en.toml

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,170 @@
7070
pageRef = "/projects/another-project/"
7171
parent = "Projects"
7272
weight = 2
73-
# toml-docs-end sample-navigation
73+
# toml-docs-end sample-navigation
74+
75+
# toml-docs-start sample-menu
76+
[[services]]
77+
name = "Menu 1"
78+
pageRef = "#!"
79+
weight = 10
80+
[[services.params]]
81+
icon = "fas 1"
82+
83+
[[services]]
84+
name = "Item 1.1"
85+
parent = "Menu 1"
86+
pageRef = "#!"
87+
weight = 10
88+
89+
[[services]]
90+
name = "Item 1.2"
91+
parent = "Menu 1"
92+
pageRef = "#!"
93+
weight = 20
94+
95+
[[services]]
96+
name = "Item 1.3"
97+
parent = "Menu 1"
98+
pageRef = "#!"
99+
weight = 30
100+
101+
# See source file for continued sample data
102+
# toml-docs-end sample-menu
103+
104+
[[services]]
105+
name = "Item 1.4"
106+
parent = "Menu 1"
107+
pageRef = "#!"
108+
weight = 40
109+
110+
[[services]]
111+
name = "Item 1.5"
112+
parent = "Menu 1"
113+
pageRef = "#!"
114+
weight = 50
115+
116+
[[services]]
117+
name = "Menu 2"
118+
pageRef = "#!"
119+
weight = 20
120+
[[services.params]]
121+
icon = "fas 2"
122+
123+
[[services]]
124+
name = "Item 2.1"
125+
parent = "Menu 2"
126+
pageRef = "#!"
127+
weight = 10
128+
129+
[[services]]
130+
name = "Item 2.2"
131+
parent = "Menu 2"
132+
pageRef = "#!"
133+
weight = 20
134+
135+
[[services]]
136+
name = "Menu 3"
137+
pageRef = "#!"
138+
weight = 30
139+
[[services.params]]
140+
icon = "fas 3"
141+
142+
[[services]]
143+
name = "Item 3.1"
144+
parent = "Menu 3"
145+
pageRef = "#!"
146+
weight = 10
147+
148+
[[services]]
149+
name = "Item 3.2"
150+
parent = "Menu 3"
151+
pageRef = "#!"
152+
weight = 20
153+
154+
[[services]]
155+
name = "Item 3.3"
156+
parent = "Menu 3"
157+
pageRef = "#!"
158+
weight = 30
159+
160+
[[services]]
161+
name = "Item 3.4"
162+
parent = "Menu 3"
163+
pageRef = "#!"
164+
weight = 40
165+
166+
[[services]]
167+
name = "Menu 4"
168+
pageRef = "#!"
169+
weight = 40
170+
[[services.params]]
171+
icon = "fas 4"
172+
173+
[[services]]
174+
name = "Item 4.1"
175+
parent = "Menu 4"
176+
pageRef = "#!"
177+
weight = 10
178+
179+
[[services]]
180+
name = "Item 4.2"
181+
parent = "Menu 4"
182+
pageRef = "#!"
183+
weight = 20
184+
185+
[[services]]
186+
name = "Item 4.3"
187+
parent = "Menu 4"
188+
pageRef = "#!"
189+
weight = 30
190+
191+
[[services]]
192+
name = "Item 4.4"
193+
parent = "Menu 4"
194+
pageRef = "#!"
195+
weight = 40
196+
197+
[[services]]
198+
name = "Menu 5"
199+
pageRef = "#!"
200+
weight = 50
201+
[[services.params]]
202+
icon = "fas 5"
203+
204+
[[services]]
205+
name = "Item 5.1"
206+
parent = "Menu 5"
207+
pageRef = "#!"
208+
weight = 10
209+
210+
[[services]]
211+
name = "Item 5.2"
212+
parent = "Menu 5"
213+
pageRef = "#!"
214+
weight = 20
215+
216+
[[services]]
217+
name = "Menu 6"
218+
pageRef = "#!"
219+
weight = 60
220+
[[services.params]]
221+
icon = "fas 6"
222+
223+
[[services]]
224+
name = "Item 6.1"
225+
parent = "Menu 6"
226+
pageRef = "#!"
227+
weight = 10
228+
229+
[[services]]
230+
name = "Item 6.2"
231+
parent = "Menu 6"
232+
pageRef = "#!"
233+
weight = 20
234+
235+
[[services]]
236+
name = "Item 6.3"
237+
parent = "Menu 6"
238+
pageRef = "#!"
239+
weight = 30

0 commit comments

Comments
 (0)