Skip to content

Commit ba9bfca

Browse files
dslovinskyclaude
andcommitted
fix: mark section hidden when all children are hidden
Prevents empty section headers from appearing when consumers filter hidden items. Also fixes misleading comment ("no visible children" → "no children"). Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 04ac844 commit ba9bfca

2 files changed

Lines changed: 84 additions & 3 deletions

File tree

src/content-indexer/visitors/__tests__/visit-section.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,84 @@ describe("visitSection", () => {
223223
expect(Object.keys(result.indexEntries).length).toBeGreaterThan(0);
224224
});
225225

226+
test("should mark section hidden when all children are hidden", () => {
227+
const context = new ProcessingContext("docs");
228+
const cache = new ContentCache();
229+
230+
const result = visitSection(
231+
{
232+
item: {
233+
section: "Looks Visible",
234+
contents: [
235+
{
236+
page: "Hidden A",
237+
path: "fern/guides/a.mdx",
238+
hidden: true,
239+
},
240+
{
241+
page: "Hidden B",
242+
path: "fern/guides/b.mdx",
243+
hidden: true,
244+
},
245+
],
246+
},
247+
parentPath: PathBuilder.init("guides"),
248+
tab: "guides",
249+
stripPathPrefix: undefined,
250+
contentCache: cache,
251+
context,
252+
navigationAncestors: [],
253+
},
254+
visitNavigationItem,
255+
);
256+
257+
// Section itself should be marked hidden since all children are hidden
258+
expect(result.navItem).toBeDefined();
259+
expect(result.navItem).toHaveProperty("hidden", true);
260+
// Children should still be present
261+
if (
262+
result.navItem &&
263+
!Array.isArray(result.navItem) &&
264+
"children" in result.navItem
265+
) {
266+
expect(result.navItem.children).toHaveLength(2);
267+
}
268+
});
269+
270+
test("should not mark section hidden when some children are visible", () => {
271+
const context = new ProcessingContext("docs");
272+
const cache = new ContentCache();
273+
274+
const result = visitSection(
275+
{
276+
item: {
277+
section: "Mixed Section",
278+
contents: [
279+
{
280+
page: "Hidden Page",
281+
path: "fern/guides/hidden.mdx",
282+
hidden: true,
283+
},
284+
{
285+
page: "Visible Page",
286+
path: "fern/guides/visible.mdx",
287+
},
288+
],
289+
},
290+
parentPath: PathBuilder.init("guides"),
291+
tab: "guides",
292+
stripPathPrefix: undefined,
293+
contentCache: cache,
294+
context,
295+
navigationAncestors: [],
296+
},
297+
visitNavigationItem,
298+
);
299+
300+
expect(result.navItem).toBeDefined();
301+
expect(result.navItem).not.toHaveProperty("hidden");
302+
});
303+
226304
test("should recursively process nested sections", () => {
227305
const context = new ProcessingContext("docs");
228306
const cache = new ContentCache();

src/content-indexer/visitors/visit-section.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,17 @@ export const visitSection = (
138138
.flat()
139139
.filter((child): child is NavItem => child !== undefined);
140140

141-
// Skip section from nav if it has no visible children
141+
// Skip section from nav if it has no children
142142
if (children.length === 0) {
143143
return { indexEntries, navItem: undefined };
144144
}
145145

146-
// Update section nav item with children (mark hidden if applicable)
146+
// Update section nav item with children.
147+
// Mark hidden if explicitly hidden OR if every child is hidden
148+
// (prevents empty section headers when consumers filter hidden items).
147149
sectionNavItem.children = children;
148-
if (sectionItem.hidden) {
150+
const allChildrenHidden = children.every((child) => child.hidden === true);
151+
if (sectionItem.hidden || allChildrenHidden) {
149152
sectionNavItem.hidden = true;
150153
}
151154

0 commit comments

Comments
 (0)