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

AiChat for iTwinUI Docs #1414

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fcfc8b2
Added Algolia Docsearch
r100-stack Jun 16, 2023
7614a21
yarn lock
r100-stack Jun 25, 2023
bb5be19
Merge remote-tracking branch 'origin/main' into rohan/algolia-docsearch
r100-stack Jun 25, 2023
fe497ca
.gitignore
r100-stack Jul 12, 2023
9d30415
docsearch custom styling
r100-stack Jul 12, 2023
77428b1
Use yarn docsearch packages
r100-stack Jul 12, 2023
c427145
yarn.lock
r100-stack Jul 12, 2023
d4ad754
Prefixed Algolia env variables with PUBLIC_
r100-stack Jul 12, 2023
2517a8a
Merge branch 'dev' into rohan/algolia-docsearch
r100-stack Jul 13, 2023
bb3a7c3
Merge branch 'dev' into rohan/algolia-docsearch
r100-stack Jul 13, 2023
0b07023
Merge branch 'dev' into rohan/algolia-docsearch
r100-stack Jul 13, 2023
9156577
Merge branch 'dev' into rohan/algolia-docsearch
r100-stack Jul 13, 2023
814e2e9
Revert back some test images
r100-stack Jul 13, 2023
09ff2ad
Readded algolia yarn packages
r100-stack Jul 13, 2023
a16f453
Added .env to root .gitignore instead of apps/website/.gitignore
r100-stack Jul 13, 2023
5a6d195
yarn.lock
r100-stack Jul 13, 2023
3f5a944
Added a separate AlgoliaSearch component. Also tried cascade layers, …
r100-stack Jul 13, 2023
05eea2d
Removed testing code
r100-stack Jul 13, 2023
f91dc5b
Completed version of ai chat
r100-stack Jul 14, 2023
7071879
Added InputGroup for response_type
r100-stack Jul 14, 2023
b4cf977
Removed unnecessary console.log
r100-stack Jul 15, 2023
069b022
Add query-response pairs to query history
r100-stack Jul 15, 2023
ca9d212
Made code_and_text as the default response_type in AiChat
r100-stack Jul 15, 2023
b510332
Added a question mark that upon hovering explains the radio buttons
r100-stack Jul 15, 2023
cf16748
Removed unnecessary comments and styles
r100-stack Jul 15, 2023
7ce07c7
Improved radio button explanations
r100-stack Jul 15, 2023
ef143cd
More intuitive words in explanations
r100-stack Jul 15, 2023
c9f5c84
Use enter to submit and shift+enter for new line
r100-stack Jul 15, 2023
4c19b7b
More intuitive words in explanations
r100-stack Jul 15, 2023
c1c007a
Few more styles for radio buttons section
r100-stack Jul 15, 2023
98fe53b
More intuitive words in explanations
r100-stack Jul 16, 2023
c630014
More styles
r100-stack Jul 16, 2023
24832ec
Do not include defaultValue and description if they are empty
r100-stack Jul 17, 2023
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ build
yarn-debug.log*
yarn-error.log*

# env files
.env

# local env files
.env.local
.env.development.local
Expand Down
3 changes: 3 additions & 0 deletions apps/website/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# build output
dist/
.output/

# data
src/_data
4 changes: 4 additions & 0 deletions apps/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
"@astrojs/mdx": "^0.19.7",
"@astrojs/react": "^2.2.1",
"@astrojs/sitemap": "^1.3.3",
"@docsearch/css": "3",
"@docsearch/js": "3",
"@fontsource/noto-sans": "^4.5.11",
"@fontsource/noto-sans-mono": "^4.5.11",
"@itwin/itwinui-react": "3.0.0-dev.4",
"@jsdevtools/rehype-toc": "3.0.2",
"@tippyjs/react": "4.2.6",
"@types/react": "^18.0.0",
"astro": "^2.6.3",
"csv-parse": "^5.4.0",
"examples": "*",
"lz-string": "^1.4.4",
"nanoid": "^4.0.1",
Expand All @@ -31,6 +34,7 @@
"react-docgen": "^6.0.0-alpha.3",
"react-docgen-typescript": "^2.2.2",
"react-dom": "^18.0.0",
"react-markdown": "^8.0.7",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
"sass": "^1.55.0",
Expand Down
94 changes: 94 additions & 0 deletions apps/website/src/components/AiChat.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
.wrapper {
max-inline-size: min(700px, 90vi);
block-size: min(600px, 70vb);
margin-inline: auto;
padding: var(--space-6);
background-color: var(--color-background-1);
border-radius: var(--border-radius-1);
border: 1px solid var(--color-line-2);
box-shadow: 0 0 3px black;
grid-template-rows: auto 1fr auto;
color: var(--color-text);
}

.wrapper,
.header {
display: grid;
gap: var(--space-3);
}

.chat {
overflow: auto;
scrollbar-gutter: stable both-edges;
margin-block: var(--space-3);
}

.chat ul {
list-style-type: disc;
padding-inline-start: var(--space-4);
}

.input {
font: inherit;
padding: var(--space-2) var(--space-3);
background-color: transparent;
border-radius: var(--border-radius-1);
border: 1px solid var(--color-line-1);
resize: none;
}

.form .input-div {
display: grid;
grid-template-columns: 1fr auto;
gap: var(--space-2);
}

.form .radio-input-group-label {
display: flex;
align-items: center;
column-gap: var(--space-1);
cursor: auto;
}

.form .radio-input-group-label {
display: flex;
align-items: center;
}

.form .question-mark-div {
display: flex;
align-items: center;
}

.form .question-mark-div .question-mark-content {
display: none;
position: absolute;
z-index: 1;
background-color: var(--color-background-1);
color: var(--color-text);
padding: var(--space-2);
border-radius: var(--border-radius-1);
box-shadow: 0 0 3px black;
}

.form .question-mark-div:hover .question-mark-content {
display: block;
}

.send {
display: flex;
align-items: center;
cursor: pointer;
font-family: inherit;
font-size: var(--font-size-1);
color: var(--color-background-1);
padding: var(--space-2) var(--space-4);
border-radius: var(--border-radius-1);
background: var(--color-highlight-gradient);
}

.send[disabled] {
cursor: wait;
background: var(--color-background-2);
color: var(--color-mutedtext);
}
132 changes: 132 additions & 0 deletions apps/website/src/components/AiChat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import ReactMarkdown from 'react-markdown';
import styles from './AiChat.module.css';
import { InputGroup, Radio } from '@itwin/itwinui-react';
import { SvgHelpCircularHollow } from '@itwin/itwinui-icons-react';

type ResponseType = 'only_code' | 'only_text' | 'code_and_text';

export default function AiChat() {
const [responseAwaiting, setResponseAwaiting] = React.useState(false);

const [message, setMessage] = React.useState('');
const [responseType, setResponseType] = React.useState<ResponseType>('code_and_text');

const [answer, setAnswer] = React.useState('');

const fetchAnswer = async () => {
if (responseAwaiting) {
return;
}
setResponseAwaiting(true);

// Send a post request to /api/search with the body that contains the query and the response_type.
// The response will be the answer to the query.
const response = await fetch('/api/search.json', {
method: 'POST',
body: JSON.stringify({ query: message, response_type: responseType }),
headers: {
'Content-Type': 'application/json',
},
});

const responseJson = await response.json();
setAnswer(responseJson['textCompletion']);

setResponseAwaiting(false);
};

const onRadioChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setResponseType(e.target.value as ResponseType);
};

return (
<div className={styles.wrapper}>
<div className={styles.header}>
<h1>AI chat</h1>
<p>Ask me anything about iTwinUI</p>
<p>AI results may not always be accurate. Please reconfirm whenever applicable</p>
</div>

<ReactMarkdown className={styles.chat}>{answer}</ReactMarkdown>

<form
className={styles.form}
onSubmit={(e) => {
e.preventDefault();

fetchAnswer();
}}
>
<InputGroup
// label={<a href='#'>What type of answers should I return?</a>}
className={styles['radio-input-group']}
label={
<div className={styles['radio-input-group-label']}>
<p>Response Mode</p>
{/* Question mark that upon hovered shows more information */}
<div className={styles['question-mark-div']}>
<SvgHelpCircularHollow className={styles['question-mark-svg']} />
<div className={styles['question-mark-content']}>
<p>Try modifying this if you feel the results are not satisfactory.</p>
<br />
<ul>
<li>
<b>Balanced</b> - Balanced text and code answers will be returned.
</li>
<li>
<b>Better Text</b> - Better text answers will be returned. May produce
incorrect code.
</li>
<li>
<b>Better Code</b> - Better code answers will be returned. May produce
incorrect text explanations.
</li>
</ul>
</div>
</div>
</div>
}
// label={'What type of answers should I return?'}
displayStyle='inline'
>
{[
{ value: 'code_and_text', label: 'Balanced' },
{ value: 'only_text', label: 'Better Text' },
{ value: 'only_code', label: 'Better Code' },
].map(({ value, label }) => (
<Radio
key={value}
name='choice'
defaultChecked={value === 'code_and_text'}
value={value}
label={label}
onChange={onRadioChange}
/>
))}
</InputGroup>
<div className={styles['input-div']}>
<textarea
className={styles.input}
placeholder='Send a message...'
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
fetchAnswer();
}
}}
/>
<button className={styles.send} type='submit' disabled={responseAwaiting}>
Send
</button>
</div>
</form>
</div>
);
}
74 changes: 74 additions & 0 deletions apps/website/src/components/AiChatButton.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
import AiChat from './AiChat.jsx';
---

<ai-chat-button>
<button type='button'>AI chat</button>

<dialog>
<AiChat client:load />
</dialog>
</ai-chat-button>

<script>
customElements.define(
'ai-chat-button',
class extends HTMLElement {
connectedCallback() {
const button = this.querySelector('button');
const dialog = this.querySelector('dialog');

button.addEventListener('click', () => {
dialog.showModal();
});

dialog.addEventListener('click', (e) => {
if (e.currentTarget === e.target) dialog.close();
});
}
}
);
</script>

<style>
ai-chat-button {
justify-self: end;
}

button {
font: inherit;
padding: var(--space-2) var(--space-3);
text-decoration: none;
opacity: 0.9;

display: flex;
align-items: center;
cursor: pointer;
font-family: inherit;
font-size: var(--font-size-1);
color: var(--color-background-1);
border-radius: var(--border-radius-1);
background: var(--color-highlight-gradient);

&:hover {
opacity: 1;
}
}

dialog[open] {
inset: 0;
margin: 0;
padding: 0;
width: unset;
height: unset;
display: grid;
place-items: center;
background: none;
border: none;
}

dialog::backdrop {
background-color: hsl(0 0% 0% / 0.1);
backdrop-filter: blur(5px);
}
</style>
30 changes: 30 additions & 0 deletions apps/website/src/components/AlgoliaSearch.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
---

<algolia-searchbox></algolia-searchbox>

<script>
import docsearch from '@docsearch/js';

docsearch({
appId: import.meta.env.PUBLIC_ALGOLIA_APP_ID,
apiKey: import.meta.env.PUBLIC_ALGOLIA_API_KEY,
indexName: import.meta.env.PUBLIC_ALGOLIA_INDEX_NAME,
container: 'algolia-searchbox',
// debug: false, // Set debug to true if you want to inspect the modal
});
</script>

<style lang='scss'>
@import '@docsearch/css' layer(algolia);

:root {
// Algolia DocSearch: https://docsearch.algolia.com/docs/styling/
--docsearch-primary-color: var(--color-highlight-4);
--docsearch-searchbox-background: var(--color-background-1);
--docsearch-searchbox-focus-background: var(--color-background-1);
--docsearch-hit-background: var(--color-background-2);
--docsearch-modal-background: var(--color-background-2);
--docsearch-footer-background: var(--color-background-2);
}
</style>
Loading