Skip to content

Commit

Permalink
Add kapa.ai (#1107)
Browse files Browse the repository at this point in the history
* Add kapa.ai

* Implement option 2

* Add JS tooltips

* Move chat button to bottom-right corner

* Move chat below GDPR banner

* Fix AI hover

* Override button outline from text.scss

* Add scaling to Ask AI button wiggle

* Update CSP, title, and z-index

* More CSP headers

* Update CSP headers

* Update CSP headers

* Update CSP headers

* Update code CSS

* Update CSS

* Update CSS

* Update CSS: feedback buttons

* Update CSS: source buttons

* Update CSS: Source links body

* CSS test

* Update CSS: tooltip

* Update CSS: Popover

* Update CSS: Feedback button

* Update CSS: Checkboxes

* Update CSS: Feedback submit button

* Update CSS: Footer

* Update CSS: Button border

* Update CSS: Stop generation button

* Update next.config.js with all connect-src

* Trying a tighter CSP

---------

Co-authored-by: Thiago Teixeira <[email protected]>
  • Loading branch information
sfc-gh-dmatthews and sfc-gh-tteixeira authored Aug 2, 2024
1 parent ecb2cce commit 5ca15f0
Show file tree
Hide file tree
Showing 13 changed files with 327 additions and 3 deletions.
2 changes: 2 additions & 0 deletions components/layouts/globalTemplate.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from "react";
import Header from "../navigation/header";
import ChatSticky from "../navigation/chatSticky";

import styles from "./globalTemplate.module.css";

Expand All @@ -25,6 +26,7 @@ const Layout = ({ children }) => {
<div className={isSticky ? styles.stickyPageWrapper : undefined}>
{children}
</div>
<ChatSticky />
</main>
);
};
Expand Down
17 changes: 17 additions & 0 deletions components/navigation/chatSticky.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import classNames from "classnames";
import Kapa from "../utilities/kapa";
import styles from "./chatSticky.module.css";

const ChatSticky = () => {
return (
<div className={classNames(styles.Container)}>
<nav className={styles.Navigation} id="chat-sticky">
<section className={styles.NavigationContainer}>
<Kapa />
</section>
</nav>
</div>
);
};

export default ChatSticky;
11 changes: 11 additions & 0 deletions components/navigation/chatSticky.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.Container {
@apply fixed bottom-[30px] w-full z-10;
}

.Navigation {
@apply container px-2 xl:px-4 flex items-center justify-between relative transition-all mx-auto h-full left-auto;
}

.NavigationContainer {
@apply flex flex-auto justify-end;
}
2 changes: 1 addition & 1 deletion components/navigation/header.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.Container {
@apply relative w-screen z-30 border-b;
@apply relative w-full z-30 border-b;
@apply bg-white !important;
}

Expand Down
67 changes: 67 additions & 0 deletions components/utilities/kapa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import styles from "./kapa.module.css";

const Kapa = () => {
const showTooltip = () => {
let tips = document.getElementsByClassName(styles.Tooltip);
if (tips.length > 0) {
tips[0].style.display = "block";
}
};

const hideTooltip = () => {
let tips = document.getElementsByClassName(styles.Tooltip);
if (tips.length > 0) {
tips[0].style.display = "none";
}
};
let kapaWidget = (
<div className={styles.FooterContainer}>
<section className={styles.AskButtonContainer}>
<button
id="kapa-ai"
type="button"
className={styles.AskButton}
onMouseOver={showTooltip}
onMouseOut={hideTooltip}
>
<i className={styles.AskIcon}>forum</i> Ask AI
</button>
{/* <div className={styles.Tooltip}>
<p>Try our new docs assistant!</p>
</div> */}
<script
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id="e81c2b35-6c03-4576-a56c-3c825f866e06"
data-project-name="Streamlit"
data-project-color="#000000"
data-project-logo="https://docs.streamlit.io/logo.svg"
data-modal-title="Streamlit docs assistant (beta)"
data-modal-disclaimer="
This AI chatbot is powered by kapa.ai and public Streamlit information.
Answers may be inaccurate, inefficient, or biased. Any use or decisions
based on such answers should include reasonable practices including
human oversight to ensure they are safe, accurate, and suitable for
your intended purpose. Streamlit is not liable for any actions, losses,
or damages resulting from the use of the chatbot.
Do not enter any private, sensitive, personal, or regulated data.
By using this chatbot, you acknowledge and agree that input you provide
and answers you receive (collectively, “Content”) may be used by
Streamlit and kapa.ai to provide, maintain, develop, and improve
their respective offerings. For more information on how
kapa.ai may use your Content, see https://www.kapa.ai/content/terms-of-service."
data-button-hide="true"
data-modal-override-open-id="kapa-ai"
data-modal-lock-scroll="false"
data-modal-border-radius="6px"
data-modal-image-height="18px"
data-answer-feedback-button-active-border="1px solid #808495"
></script>
</section>
</div>
);

return kapaWidget;
};

export default Kapa;
66 changes: 66 additions & 0 deletions components/utilities/kapa.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
@keyframes wiggle {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(0deg);
}
60% {
transform: rotate(5deg) scale(1.25);
}
70% {
transform: rotate(-5deg) scale(1.25);
}
80% {
transform: rotate(5deg) scale(1.25);
}
90% {
transform: rotate(-5deg) scale(1.25);
}
100% {
transform: rotate(0deg);
}
}

.AskButtonContainer {
@apply flex justify-end;
}

.AskButton {
@apply flex items-center justify-center p-0 rounded-md h-8 px-4 cursor-pointer bg-gray-100 text-white hover:opacity-90 hover:shadow-sm;
animation: wiggle 2s 1;
}

.AskButton:hover {
transform: scale(1.025);
}

.AskButton:focus,
.AskButton:focus-visible {
@apply outline-0;
}

:global(.dark) .AskButton {
@apply text-gray-100 bg-gray-40 !important;
}

.AskIcon {
@apply text-lg m-0 pr-2 group-hover:opacity-70;
@apply text-white !important;
}

:global(.dark) .AskIcon {
@apply text-gray-100 !important;
}

.Tooltip {
@apply hidden absolute top-20 right-[4.5rem] h-8 px-2 pt-0.5 rounded-md bg-gray-20;
}

.Tooltip p {
@apply text-gray-70;
}

:global(.dark) .Tooltip {
@apply bg-gray-90;
}
124 changes: 124 additions & 0 deletions components/utilities/kapaModal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
.mantine-Modal-overlay {
background-color: rgba(166, 168, 184, 0.6) !important;
}

.mantine-Modal-header,
.mantine-Modal-header h3 {
@apply bg-white dark:bg-gray-90 text-gray-90 dark:text-gray-40 border-b-0 font-normal tracking-wide;
}

.mantine-Modal-header > .mantine-Group-root:first-child .mantine-Image-root {
@apply hidden;
}

.mantine-Modal-body,
.mantine-Modal-body a,
.mantine-Modal-body .mantine-List-root,
.mantine-Modal-body .mantine-List-item {
@apply bg-white dark:bg-gray-90;
@apply text-gray-90 dark:text-gray-40;
}

.mantine-Paper-root
> .mantine-Modal-body
> .mantine-Modal-body
> div:first-child
> div:first-child:has(.mantine-Text-root) {
@apply bg-gray-20 dark:bg-gray-80;
}

.mantine-Paper-root
> .mantine-Modal-body
> .mantine-Modal-body
> div:first-child
> div:first-child
.mantine-Text-root {
@apply text-gray-70 dark:text-gray-50;
}

.mantine-Group-root button {
@apply text-gray-70;
}

.mantine-Group-root button:hover {
@apply bg-gray-20 dark:bg-gray-80;
}

.mantine-Input-input {
@apply bg-white dark:bg-gray-90 border-gray-70 focus:border-orange-70 text-gray-90 dark:text-gray-40;
}

.mantine-Input-rightSection > .mantine-Group-root > .mantine-ActionIcon-root {
@apply bg-white dark:bg-gray-90 border-none text-orange-70 !important;
}

.mantine-Input-rightSection
> .mantine-Group-root
> .mantine-ActionIcon-root
svg {
@apply scale-150 hover:scale-[1.6];
}

.mantine-Code-root {
@apply bg-transparent border border-gray-40 dark:border-gray-80 rounded-md text-red-70 px-1 mx-1;
}

.mantine-Grid-root .mantine-Grid-col a {
@apply border-gray-20 dark:border-gray-80 bg-transparent;
}

.mantine-Grid-root .mantine-Grid-col a:hover {
@apply bg-gray-20 dark:bg-gray-80;
}

.mantine-Grid-root .mantine-Grid-col div {
@apply text-gray-90 dark:text-gray-40;
}

.mantine-Grid-root .mantine-Grid-col div.mantine-Tooltip-tooltip {
@apply bg-gray-80 dark:bg-gray-20 text-gray-50 dark:text-gray-70;
}

.mantine-Popover-dropdown,
.mantine-Popover-arrow {
@apply bg-white dark:bg-gray-90 text-gray-90 dark:text-gray-40;
}

.mantine-Popover-dropdown .mantine-Button-root {
@apply text-white;
}

.mantine-Popover-dropdown h5 {
@apply text-gray-90 dark:text-gray-40;
}

.mantine-Checkbox-input {
@apply bg-gray-20 dark:bg-gray-80 border-gray-70;
}

.mantine-Checkbox-label {
@apply text-gray-90 dark:text-gray-40;
}

.mantine-Paper-root
> .mantine-Modal-body
> .mantine-Modal-body
> div:last-child {
@apply text-gray-70;
}

.mantine-Paper-root
> .mantine-Modal-body
> .mantine-Modal-body
> div:last-child
a {
@apply text-gray-70;
}

.mantine-Button-icon:has(.tabler-icon-player-stop) {
@apply hidden;
}

.mantine-Button-root:has(.tabler-icon-player-stop) {
@apply py-0 px-4;
}
15 changes: 13 additions & 2 deletions components/utilities/themeToggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ const ThemeToggle = () => {
localStorage.setItem("theme", theme);
};

const showTooltip = () => {
document.getElementsByClassName(styles.Tooltip)[0].style.display = "block";
};

const hideTooltip = () => {
document.getElementsByClassName(styles.Tooltip)[0].style.display = "none";
};

useEffect(() => {
if (getUserPreference() === "dark") {
changeTailwindTheme("dark");
Expand All @@ -35,19 +43,22 @@ const ThemeToggle = () => {
return (
<React.Fragment>
<button
aria-label={`Change to ${inactiveTheme} mode`}
title={`Change to ${inactiveTheme} mode`}
type="button"
onClick={
activeTheme === "light"
? () => changeTailwindTheme("dark")
: () => changeTailwindTheme("light")
}
onMouseOver={showTooltip}
onMouseOut={hideTooltip}
className={styles.Container}
>
<i className={classNames(styles.DarkIcon, styles.Icon)}>dark_mode</i>
<i className={classNames(styles.LightIcon, styles.Icon)}>light_mode</i>
</button>
<div className={styles.Tooltip}>
<p>Change to {inactiveTheme} mode</p>
</div>
</React.Fragment>
);
};
Expand Down
12 changes: 12 additions & 0 deletions components/utilities/themeToggle.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,15 @@
:global(.dark) .LightIcon {
@apply opacity-0;
}

.Tooltip {
@apply hidden absolute top-20 right-4 h-8 px-2 pt-0.5 rounded-md bg-gray-20;
}

.Tooltip p {
@apply text-gray-70;
}

:global(.dark) .Tooltip {
@apply bg-gray-90;
}
4 changes: 4 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ connect-src \
https://px.ads.linkedin.com/ \
https://*.algolia.net/ \
https://*.algolianet.com/ \
https://kapa-widget-proxy-la7dkmplpq-uc.a.run.app/ \
; \
default-src 'none' ; \
font-src 'self' ; \
Expand Down Expand Up @@ -53,6 +54,9 @@ script-src \
https://connect.facebook.net/ \
https://*.algolia.net/ \
https://*.algolianet.com/ \
https://widget.kapa.ai/kapa-widget.bundle.js \
https://www.google.com/recaptcha/api.js \
https://www.gstatic.com/recaptcha/releases/ \
; \
style-src \
'self' \
Expand Down
Loading

0 comments on commit 5ca15f0

Please sign in to comment.