Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
82 changes: 82 additions & 0 deletions src/components/AskAi/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { useLocation } from "@docusaurus/router";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import IconClaude from "@site/static/icons/claude.svg";
import IconMarkdown from "@site/static/icons/markdown.svg";
import IconOpenAI from "@site/static/icons/openai.svg";
import styles from "./styles.module.scss";

const AskAiLink = ({ icon, text, link, description }) => {
return (
<li>
<a
href={link}
className="dropdown__link"
target="_blank"
rel="noopener noreferrer"
>
<span className={styles.link}>
{icon}
<span>{text}</span>
</span>
<span className={styles.linkDescription}>{description}</span>
</a>
</li>
);
};

export const AskAi = () => {
const { pathname } = useLocation();

const isCategory = pathname.includes("/category/");

if (isCategory) {
return <></>;
}

const {
siteConfig: { url }
} = useDocusaurusContext();

const markdownLink = `${pathname}.md`;

const prompt = encodeURIComponent(`Read from this URL: ${url}${pathname}`);
const claudeLink = `https://claude.ai/new?q=${prompt}`;
const chatGPTLink = `https://chatgpt.com/?prompt=${prompt}`;

return (
<div className="dropdown dropdown--hoverable">
<a
href="#"
aria-haspopup="true"
aria-expanded="false"
role="button"
className={`navbar__link breadcrumbs__link ${styles.btn}`}
>
Ask AI
</a>

<ul className="dropdown__menu">
<AskAiLink
icon={<IconMarkdown />}
link={markdownLink}
text="View as Markdown"
description="Open this page in Markdown"
/>

<AskAiLink
icon={<IconClaude />}
link={claudeLink}
text="Open in Claude"
description="Ask questions about this page"
/>

<AskAiLink
icon={<IconOpenAI />}
link={chatGPTLink}
text="Open in ChatGPT"
description="Ask questions about this page"
/>
</ul>
</div>
);
};
27 changes: 27 additions & 0 deletions src/components/AskAi/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.btn {
margin: 0.45rem 0;
border: 1px solid var(--ifm-toc-border-color);

&:hover,
&:active {
border: 1px solid var(--ifm-navbar-link-hover-color);
}

@media screen and (min-width: 997px) {
margin: 0;
}
}

.link {
display: flex;
align-items: center;
gap: 0.45rem;
font-size: calc(1rem * var(--ifm-breadcrumb-size-multiplier));
}

.linkDescription {
display: block;
font-size: calc(1rem * var(--ifm-breadcrumb-size-multiplier));
color: var(--ifm-color-emphasis-600);
line-height: 1.6;
}
101 changes: 101 additions & 0 deletions src/theme/DocBreadcrumbs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import Link from "@docusaurus/Link";
import { useSidebarBreadcrumbs } from "@docusaurus/plugin-content-docs/client";
import { ThemeClassNames } from "@docusaurus/theme-common";
import { useHomePageRoute } from "@docusaurus/theme-common/internal";
import { translate } from "@docusaurus/Translate";
import HomeBreadcrumbItem from "@theme/DocBreadcrumbs/Items/Home";
import DocBreadcrumbsStructuredData from "@theme/DocBreadcrumbs/StructuredData";
import clsx from "clsx";
import { type ReactNode } from "react";

import { AskAi } from "@site/src/components/AskAi";
import styles from "./styles.module.css";

// TODO move to design system folder
function BreadcrumbsItemLink({
children,
href,
isLast
}: {
children: ReactNode;
href: string | undefined;
isLast: boolean;
}): ReactNode {
const className = "breadcrumbs__link";
if (isLast) {
return <span className={className}>{children}</span>;
}
return href ? (
<Link className={className} href={href}>
<span>{children}</span>
</Link>
) : (
<span className={className}>{children}</span>
);
}

// TODO move to design system folder
function BreadcrumbsItem({
children,
active
}: {
children: ReactNode;
active?: boolean;
}): ReactNode {
return (
<li
className={clsx("breadcrumbs__item", {
"breadcrumbs__item--active": active
})}
>
{children}
</li>
);
}

export default function DocBreadcrumbs(): ReactNode {
const breadcrumbs = useSidebarBreadcrumbs();
const homePageRoute = useHomePageRoute();

if (!breadcrumbs) {
return null;
}

return (
<>
<DocBreadcrumbsStructuredData breadcrumbs={breadcrumbs} />
<nav
className={clsx(
ThemeClassNames.docs.docBreadcrumbs,
styles.breadcrumbsContainer,
styles.customBreadcrumbs
)}
aria-label={translate({
id: "theme.docs.breadcrumbs.navAriaLabel",
message: "Breadcrumbs",
description: "The ARIA label for the breadcrumbs"
})}
>
<ul className="breadcrumbs">
{homePageRoute && <HomeBreadcrumbItem />}
{breadcrumbs.map((item, idx) => {
const isLast = idx === breadcrumbs.length - 1;
const href =
item.type === "category" && item.linkUnlisted
? undefined
: item.href;
return (
<BreadcrumbsItem key={idx} active={isLast}>
<BreadcrumbsItemLink href={href} isLast={isLast}>
{item.label}
</BreadcrumbsItemLink>
</BreadcrumbsItem>
);
})}
</ul>

<AskAi />
</nav>
</>
);
}
11 changes: 11 additions & 0 deletions src/theme/DocBreadcrumbs/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.breadcrumbsContainer {
--ifm-breadcrumb-size-multiplier: 0.8;
margin-bottom: 0.8rem;
}

.customBreadcrumbs {
@media screen and (min-width: 997px) {
display: flex;
justify-content: space-between;
}
}
5 changes: 5 additions & 0 deletions static/icons/claude.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions static/icons/markdown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions static/icons/openai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.