Skip to content

Commit

Permalink
feat(docx): Integrate triton to next gen docs (#2373)
Browse files Browse the repository at this point in the history
* initial integration

* docs: Create top nav (#2364)

* create header component

* accurate header width calculation

* ToggleThemeButton into Header

* align ToggleThemeButton to the right of the header

* make sure nav menu aligns with header

* border on the header

* Header takes up the whole width

* make sure only BaseView.Main scrolls with header on top

* move top nav to be inside BaseView.Main

* refactor Triton SideDrawer into its own component and created TritonContext

* header styling

* dont use box as main due to lack of boxShadow

* make header responsive in minimal mode

* fix eslint

* overflow auto on main routed div

* ask triton button styling

* only rounded top corners of main content

* fixed main content not growing

* fix BaseView border radius

* some layout/styling tweaks

* add header to collection pages and make scrollbar inside the content

* isolate blending to only content card wrapper

* align nav with header

* Renamed Header to TopNav

* use Box instead of div

---------

Co-authored-by: Chris Murray <[email protected]>

* docs: Add Triton to SideDrawer (#2380)

* Triton SideDrawer knows if ApiKey is valid or not via InputPassword

* add validation message for wrong api key

* stream hooked up, seeing questions and answers flowing in sidedrawer

* fix layout of sidedrawer and update styling of questions

* styling is where I want it

* links are working

* make it so the response appears to be typing, scroll container as responses come in and update InputText button to say Asking when loading

* install react-markdown as a dependency

* package-lock updates

* use component and design lists in TritonLinks

* remove comments

* manage loading state in the provider and fix broken api key

* refactor provider

* refactor TritonSideDrawer

* refactor TritonConversation

* refactor TritonConversation css

* update marginBottom of question

* add the copy code button to code blocks

* use correct url in useTritonApi

* actually make copy  code button work

* rename fetchWithApiKey to invokeTritonApi

* move TritonLinks to utils

* move scrollToBottom function

* adjust validation of api logic and move validateApiKey to useTritonApi

* move scrollToBottom to useTritonApi.ts

* move sendSearch andhandleStreamResponse to useTritonApi

* test out streaming response

* remove handleStreamResponse

* remove unnecessary console.error and other cleanups

---------

Co-authored-by: Scott Thompson <[email protected]>
Co-authored-by: Chris Murray <[email protected]>
Co-authored-by: Taylor Noj <[email protected]>
  • Loading branch information
4 people authored Feb 24, 2025
1 parent d0a5595 commit 5053e7b
Show file tree
Hide file tree
Showing 20 changed files with 809 additions and 339 deletions.
266 changes: 70 additions & 196 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-element-to-jsx-string": "^15.0.0",
"react-markdown": "^9.0.1",
"react-native-svg-web": "^1.0.9",
"react-router": "5.3.4",
"react-router-dom": "5.3.4"
Expand Down
93 changes: 54 additions & 39 deletions packages/site/src/components/PageBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CategoryCardSection } from "./CategoryCardSection";
import { PageWrapper } from "../layout/PageWrapper";
import { ContentCardProps } from "../types/components";
import usePageTitle from "../hooks/usePageTitle";
import { TopNav } from "../layout/TopNav";

interface PageBlockProps {
readonly structure: {
Expand Down Expand Up @@ -63,48 +64,62 @@ export const PageBlock = ({ structure }: PageBlockProps) => {

return (
<PageWrapper>
<HeaderBlock {...structure.header} />
<BodyBlock>
{structure.showSegmentedControl && (
<div
style={{
width: "240px",
margin: "auto",
paddingBottom: "var(--space-largest)",
}}
>
<SegmentedControl
selectedValue={cardView}
onSelectValue={setCardView}
>
<SegmentedControl.Option value={"category"}>
Categorical
</SegmentedControl.Option>
<SegmentedControl.Option value={"a-z"}>
Alphabetical
</SegmentedControl.Option>
</SegmentedControl>
</div>
)}
<TopNav />
<main
style={{
boxShadow: "var(--shadow-base)",
borderRadius: "var(--radius-base) var(--radius-base) 0 0",
overflow: "hidden",
position: "relative",
flexGrow: 1,
backgroundColor: "var(--color-surface)",
}}
>
<div style={{ overflowY: "scroll", height: "100%" }}>
<HeaderBlock {...structure.header} />
<BodyBlock>
{structure.showSegmentedControl && (
<div
style={{
width: "240px",
margin: "auto",
paddingBottom: "var(--space-largest)",
}}
>
<SegmentedControl
selectedValue={cardView}
onSelectValue={setCardView}
>
<SegmentedControl.Option value={"category"}>
Categorical
</SegmentedControl.Option>
<SegmentedControl.Option value={"a-z"}>
Alphabetical
</SegmentedControl.Option>
</SegmentedControl>
</div>
)}

{structure.useCategories && cardView === "category" ? (
<>
{sectionedComponents().map(({ section, items }) => (
<CategoryCardSection key={section} category={section}>
{items.map((content, index) => (
{structure.useCategories && cardView === "category" ? (
<>
{sectionedComponents().map(({ section, items }) => (
<CategoryCardSection key={section} category={section}>
{items.map((content, index) => (
<ContentCard {...content} key={index} />
))}
</CategoryCardSection>
))}
</>
) : (
<ContentCardWrapper>
{structure.body.content.map((content, index) => (
<ContentCard {...content} key={index} />
))}
</CategoryCardSection>
))}
</>
) : (
<ContentCardWrapper>
{structure.body.content.map((content, index) => (
<ContentCard {...content} key={index} />
))}
</ContentCardWrapper>
)}
</BodyBlock>
</ContentCardWrapper>
)}
</BodyBlock>
</div>
</main>
</PageWrapper>
);
};
23 changes: 5 additions & 18 deletions packages/site/src/components/ToggleThemeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,10 @@ export const ToggleThemeButton = () => {
};

return (
<div
style={{
position: "fixed",
bottom: "var(--space-base)",
right: "var(--space-base)",
boxShadow: "var(--shadow-base)",
borderRadius: "var(--radius-base)",
zIndex: 1,
}}
data-elevation="elevated"
>
<Button
type="secondary"
variation="subtle"
label={isDark ? "☀️" : "🌒"}
onClick={handleClick}
/>
</div>
<Button
variation="subtle"
label={isDark ? "☀️" : "🌒"}
onClick={handleClick}
/>
);
};
21 changes: 21 additions & 0 deletions packages/site/src/components/TritonConversation.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.codeWrapper {
position: relative;
max-width: 100%;
padding: var(--space-small);
border: var(--border-base) solid var(--color-border);
border-radius: var(--radius-base);
background: var(--color-surface--background);
overflow-x: hidden;
}

.codeWrapper,
.codeWrapper code {
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-all;
}

.codeWrapper:focus {
outline: none;
box-shadow: var(--shadow-focus);
}
95 changes: 95 additions & 0 deletions packages/site/src/components/TritonConversation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Box, Content, Heading, Icon, Link, Text } from "@jobber/components";
import ReactMarkdown from "react-markdown";
import { ReactElement } from "react";
import styles from "./TritonConversation.module.css";
import { CopyCodeButton } from "./CodeCopyButton";
import { componentMap, getComponentPath } from "../utils/TritonLinks";
import { useTritonChat } from "../providers/TritonProvider";

const WelcomeMessage = () => (
<Content>
<Heading level={2}>Welcome!</Heading>
<div style={{ marginBottom: 80 }}>
<Text>
I am an early-stage AI that can help you build with Atlantis components.
You can ask me questions, I will generate custom component code and you
can test it all out in the live preview.
</Text>
</div>
</Content>
);

interface MessageProps {
readonly question: string;
readonly response: string;
}

const Message = ({ question, response }: MessageProps) => (
<div>
<div style={{ width: "100%", display: "flex" }}>
<Box
background="surface--background"
padding="small"
radius="base"
margin={{ bottom: "base" }}
>
<Text>{question}</Text>
</Box>
</div>
<div style={{ display: "flex", gap: 6, marginBottom: "large" }}>
<Icon name="sparkles" size="small" color="interactiveSubtle" />
<div style={{ flex: 1, marginBottom: 40 }}>
<Content spacing="base">
<ReactMarkdown
components={{
a: ({ children }) => {
const text = String(children);
const key = Object.keys(componentMap).find(mapKey =>
text.toLowerCase().includes(mapKey.toLowerCase()),
);

return (
<Link url={getComponentPath(key || "")} external={false}>
{children}
</Link>
);
},
p: ({ children }) => <Text>{children}</Text>,
pre: ({ children, ...props }) => {
const codeContent =
(children as ReactElement)?.props?.children || "";

return (
<div style={{ position: "relative" }}>
<pre className={styles.codeWrapper} tabIndex={0} {...props}>
{children}
</pre>
<CopyCodeButton code={codeContent} />
</div>
);
},
}}
>
{response}
</ReactMarkdown>
</Content>
</div>
</div>
</div>
);

export function TritonConversation() {
const { responses, questions } = useTritonChat();

if (responses.length === 0) {
return <WelcomeMessage />;
}

return (
<div style={{ paddingRight: "var(--space-base)" }}>
{responses.map((response, index) => (
<Message key={index} question={questions[index]} response={response} />
))}
</div>
);
}
Loading

0 comments on commit 5053e7b

Please sign in to comment.