Skip to content

Commit ad61047

Browse files
authored
fix: new accordion behavior (#2197)
1 parent 5f4d23f commit ad61047

File tree

3 files changed

+25
-146
lines changed

3 files changed

+25
-146
lines changed

packages/fern-docs/mdx/src/toc.ts

+2-87
Original file line numberDiff line numberDiff line change
@@ -59,91 +59,6 @@ export function makeToc(
5959
return;
6060
}
6161

62-
if (isMdxJsxElementHast(node) && node.name === "Accordion") {
63-
const baseId =
64-
node.attributes
65-
.filter(isMdxJsxAttribute)
66-
.find((attr) => attr.name === "id")?.value ||
67-
slug(
68-
node.attributes
69-
.filter(isMdxJsxAttribute)
70-
.find((attr) => attr.name === "title")?.value as string
71-
) ||
72-
"";
73-
74-
if (baseId && typeof baseId === "string") {
75-
const updateChildIds = (
76-
items: (Hast.Element | Hast.MdxJsxElement)[],
77-
parentId: string
78-
) => {
79-
items.forEach((item) => {
80-
if (item.type === "element") {
81-
if (item.properties?.id) {
82-
const oldId = item.properties.id as string;
83-
item.properties.id = oldId.startsWith(parentId)
84-
? oldId
85-
: `${parentId}.${oldId}`;
86-
}
87-
if (item.children) {
88-
updateChildIds(
89-
item.children.filter(
90-
(child): child is Hast.Element | Hast.MdxJsxElement =>
91-
child.type === "element" ||
92-
child.type === "mdxJsxFlowElement"
93-
),
94-
(item.properties?.id as string) || parentId
95-
);
96-
}
97-
} else if (item.type === "mdxJsxFlowElement") {
98-
if (item.name === "Accordion") {
99-
const newId = slug(
100-
item.attributes
101-
.filter(isMdxJsxAttribute)
102-
.find((attr) => attr.name === "title")?.value as string
103-
);
104-
105-
item.attributes.push({
106-
type: "mdxJsxAttribute",
107-
name: "id",
108-
value: `${parentId}.${newId}`,
109-
});
110-
111-
return;
112-
}
113-
114-
const itemIdAttr = item.attributes
115-
.filter(isMdxJsxAttribute)
116-
.find((attr) => attr.name === "id");
117-
if (itemIdAttr && typeof itemIdAttr.value === "string") {
118-
const oldId = itemIdAttr.value;
119-
itemIdAttr.value = oldId.startsWith(parentId)
120-
? oldId
121-
: `${parentId}.${oldId}`;
122-
}
123-
if (item.children) {
124-
updateChildIds(
125-
item.children.filter(
126-
(child): child is Hast.Element | Hast.MdxJsxElement =>
127-
child.type === "element" ||
128-
child.type === "mdxJsxFlowElement"
129-
),
130-
(itemIdAttr?.value as string) || parentId
131-
);
132-
}
133-
}
134-
});
135-
};
136-
137-
updateChildIds(
138-
node.children.filter(
139-
(child): child is Hast.Element | Hast.MdxJsxElement =>
140-
child.type === "element" || child.type === "mdxJsxFlowElement"
141-
),
142-
baseId
143-
);
144-
}
145-
}
146-
14762
// if the node is a <Steps toc={false}>, skip traversing its children
14863
if (isMdxJsxElementHast(node) && node.name === "StepGroup") {
14964
const isTocEnabled =
@@ -245,7 +160,7 @@ export function makeToc(
245160
}
246161
headings.push({
247162
depth: 6,
248-
id: item.id ?? slug(item.title),
163+
id: slug(item.title),
249164
title: item.title,
250165
featureFlags: findFlag(parents),
251166
});
@@ -275,7 +190,7 @@ export function makeToc(
275190
}
276191
headings.push({
277192
depth: 6,
278-
id: item.id ?? slug(item.title),
193+
id: slug(item.title),
279194
title: item.title,
280195
featureFlags: findFlag(parents),
281196
});

packages/fern-docs/ui/src/mdx/components/accordion/AccordionGroup.tsx

+7-13
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface AccordionItemProps {
1313
title: string;
1414
id: string;
1515
toc?: boolean;
16+
nestedHeaders?: string[];
1617
children: ReactNode;
1718
}
1819

@@ -34,19 +35,12 @@ export const AccordionGroup = forwardRef<HTMLDivElement, AccordionGroupProps>(
3435
return anchor;
3536
}
3637

37-
// Check parent paths
38-
if (anchor.includes(".")) {
39-
const segments = anchor.split(".");
40-
return segments.reduce<string | undefined>(
41-
(parentPath, segment, index) => {
42-
if (index === 0) return segment;
43-
const path = `${parentPath}.${segment}`;
44-
return items.some((tab) => tab.id === parentPath)
45-
? parentPath
46-
: path;
47-
},
48-
undefined
49-
);
38+
const parentAccordion = items.find((tab) =>
39+
tab.nestedHeaders?.includes(anchor)
40+
);
41+
42+
if (parentAccordion) {
43+
return parentAccordion.id;
5044
}
5145

5246
return undefined;

packages/fern-docs/ui/src/mdx/plugins/rehypeFernComponents.ts

+16-46
Original file line numberDiff line numberDiff line change
@@ -298,87 +298,57 @@ function transformAccordion(
298298
): VisitorResult {
299299
const title = getTitle(node) ?? `Untitled ${index + 1}`;
300300
applyGeneratedId(node, title);
301-
const idAttr = node.attributes
302-
.filter(isMdxJsxAttribute)
303-
.find((attr) => attr.name === "id");
304301

305-
// Find parent accordion's ID if it exists
306-
let parentId: string | undefined;
307-
if (isMdxJsxElementHast(parent) && parent.name === "Accordion") {
308-
parentId = parent.attributes
309-
.filter(isMdxJsxAttribute)
310-
.find((attr) => attr.name === "id")?.value as string | undefined;
311-
}
312-
313-
// If we have both a parent ID and current ID, combine them
314-
if (parentId && idAttr && typeof idAttr.value === "string") {
315-
idAttr.value = `${parentId}.${idAttr.value}`;
316-
}
302+
const nestedHeaders: string[] = [];
317303

318-
// Rest of the updateChildIds logic for nested elements
319-
if (idAttr && typeof idAttr.value === "string") {
320-
const baseId = idAttr.value;
321-
const updateChildIds = (
322-
items: (Hast.Element | Hast.MdxJsxElement)[],
323-
parentId: string
324-
) => {
304+
if (node.children.length > 0) {
305+
const collectHeaders = (items: (Hast.Element | Hast.MdxJsxElement)[]) => {
325306
items.forEach((item) => {
326307
if (item.type === "element") {
327308
if (item.properties?.id) {
328-
const oldId = item.properties.id as string;
329-
item.properties.id = oldId.startsWith(parentId)
330-
? oldId
331-
: `${parentId}.${oldId}`;
309+
nestedHeaders.push(item.properties.id as string);
332310
}
311+
333312
if (item.children) {
334-
updateChildIds(
313+
collectHeaders(
335314
item.children.filter(
336315
(child): child is Hast.Element | Hast.MdxJsxElement =>
337316
child.type === "element" || child.type === "mdxJsxFlowElement"
338-
),
339-
(item.properties?.id as string) || parentId
317+
)
340318
);
341319
}
342320
} else if (item.type === "mdxJsxFlowElement") {
343-
if (item.name === "Accordion") {
344-
return;
345-
}
346-
347-
const itemIdAttr = item.attributes
321+
const itemId = item.attributes
348322
.filter(isMdxJsxAttribute)
349323
.find((attr) => attr.name === "id");
350-
if (itemIdAttr && typeof itemIdAttr.value === "string") {
351-
const oldId = itemIdAttr.value;
352-
itemIdAttr.value = oldId.startsWith(parentId)
353-
? oldId
354-
: `${parentId}.${oldId}`;
324+
if (itemId?.value && typeof itemId.value === "string") {
325+
nestedHeaders.push(itemId.value);
355326
}
327+
356328
if (item.children) {
357-
updateChildIds(
329+
collectHeaders(
358330
item.children.filter(
359331
(child): child is Hast.Element | Hast.MdxJsxElement =>
360332
child.type === "element" || child.type === "mdxJsxFlowElement"
361-
),
362-
(itemIdAttr?.value as string) || parentId
333+
)
363334
);
364335
}
365336
}
366337
});
367338
};
368339

369-
updateChildIds(
340+
collectHeaders(
370341
node.children.filter(
371342
(child): child is Hast.Element | Hast.MdxJsxElement =>
372343
child.type === "element" || child.type === "mdxJsxFlowElement"
373-
),
374-
baseId
344+
)
375345
);
376346
}
377347

378348
visit(node, visitor);
379349

380350
const { props } = hastMdxJsxElementHastToProps(node);
381-
const items = [props];
351+
const items = [{ ...props, nestedHeaders }];
382352

383353
const child = {
384354
type: "mdxJsxFlowElement" as const,

0 commit comments

Comments
 (0)