Skip to content
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

Adding option to keep the api categories closed by default - #289

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/zudoku/src/config/validators/SidebarSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type SidebarItemCategory = Omit<
items: SidebarItem[];
link?: SidebarItemCategoryLinkDoc;
icon?: LucideIcon | string;
apiReference?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure about the naming of this toggle. I think we should better describe the behaviour that we are toggleing here, like openOnScroll?

Copy link
Contributor Author

@arian0zen arian0zen Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • the key apiReference is not actually user-facing, this one is just to identify if the collapsable categories are apiRef or not, if they are not apis and just documentation I figured we should not add the open on scroll ability.

  • the open-on-scroll actually defined by the key defaultCollapsed, that one is user-facing. ( I think here this should be defined as openOnScroll )

  • Although, I am very much open to this suggestion.. what do you say?

};

export type SidebarItem =
Expand Down
1 change: 1 addition & 0 deletions packages/zudoku/src/config/validators/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const ThemeSchema = z
const ApiConfigSchema = z.object({
server: z.string().optional(),
navigationId: z.string().optional(),
defaultCollapsed: z.boolean().optional(),
});

const ApiSchema = z.union([
Expand Down
28 changes: 25 additions & 3 deletions packages/zudoku/src/lib/components/navigation/SidebarCategory.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* eslint-disable no-console */
arian0zen marked this conversation as resolved.
Show resolved Hide resolved
import * as Collapsible from "@radix-ui/react-collapsible";
import { ChevronRightIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { NavLink, useMatch } from "react-router-dom";
import type { SidebarItemCategory } from "../../../config/validators/SidebarSchema.js";
import { cn } from "../../util/cn.js";
import { joinPath } from "../../util/joinPath.js";
import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
import { useTopNavigationItem } from "../context/ZudokuContext.js";
import { navigationListItem, SidebarItem } from "./SidebarItem.js";
import { useIsCategoryOpen } from "./utils.js";
Expand All @@ -27,6 +29,7 @@ export const SidebarCategory = ({
);
const [open, setOpen] = useState(isDefaultOpen);
const isActive = useMatch(joinPath(topNavItem?.id, category.link?.id));
const { activeAnchor } = useViewportAnchor();

useEffect(() => {
// this is triggered when an item from the sidebar is clicked
Expand All @@ -36,6 +39,25 @@ export const SidebarCategory = ({
}
}, [isCategoryOpen]);

const categoryLabel = useMemo(
() => category.label.toLowerCase(),
[category.label],
);

// this is useful when sidebar is collapsed and then user scrolls to an anchor link in the content then the sidebar should open to show the active category
useEffect(() => {
if (!activeAnchor) return;
if (hasInteracted) return;

// if this category is not part of the api reference then return as we don't want to close-open on scroll for other documentation
if (!category.apiReference) return;

const currentActiveCategory = activeAnchor.split("-")[0];
const shouldBeOpen = currentActiveCategory === categoryLabel;

setOpen(shouldBeOpen);
}, [activeAnchor, category.apiReference, categoryLabel, hasInteracted]);

const ToggleButton = isCollapsible && (
<button
type="button"
Expand Down Expand Up @@ -116,8 +138,8 @@ export const SidebarCategory = ({
</Collapsible.Trigger>
<Collapsible.Content
className={cn(
// CollapsibleContent class is used to animate and it should only be applied when the user has triggered the toggle
hasInteracted && "CollapsibleContent",
// CollapsibleContent class is used to animate and it should only be applied when the user has triggered the toggle or the category is collapsed (if it was collapsed by default then while scrolling to an anchor link in the content it should animate as well)
(hasInteracted || category.collapsed) && "CollapsibleContent",
)}
>
<ul className="mt-1 border-l ms-0.5">
Expand Down
3 changes: 2 additions & 1 deletion packages/zudoku/src/lib/plugins/openapi/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export const openApiPlugin = (
type: "category",
label: tag.name || "Other endpoints",
collapsible: true,
collapsed: false,
collapsed: config.defaultCollapsed ?? false,
items: tag.operations.map((operation) => ({
type: "link",
label: operation.summary ?? operation.path,
Expand All @@ -173,6 +173,7 @@ export const openApiPlugin = (
color: MethodColorMap[operation.method.toLowerCase()],
},
})),
apiReference: true,
}));

categories.unshift({
Expand Down
1 change: 1 addition & 0 deletions packages/zudoku/src/lib/plugins/openapi/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ type OasSource =
export type OasPluginConfig = {
server?: string;
navigationId?: string;
defaultCollapsed?: boolean;
skipPreload?: boolean;
} & OasSource;
2 changes: 2 additions & 0 deletions packages/zudoku/src/vite/dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ export class DevServer {
const graphql = createGraphQLServer({
graphqlEndpoint: "/__z/graphql",
});

const proxiedEntryClientPath = path.join(
vite.config.base,
"/__z/entry.client.tsx",
);

app.use(graphql.graphqlEndpoint, graphql);
app.use(proxiedEntryClientPath, async (_req, res) => {
const transformed = await vite.transformRequest(getAppClientEntryPath());
Expand Down