Skip to content

Sam guide component docs #1017

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion content/in-app-ui/guides/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ A guide represents a piece of UI that you want to be **powered by Knock within y
alt="Whatisaguide"
width={1356}
height={1452}
className="rounded-md mx-auto border border-gray-200"
className="mx-auto border border-gray-200"
style={{ borderRadius: "var(--tgph-rounded-5)" }}
/>

You configure your guide in the Knock dashboard, including its **content**, its **targeting** rules (who can see it), and its **activation** rules (where in your product they can see it.)
Expand Down
6 changes: 6 additions & 0 deletions content/in-app-ui/react/banner.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: "Banner"
description: How to ship an in-app notification banner using our pre-built guides component.
tags: ["banner", "guides", "alert"]
section: Building in-app UI
---
6 changes: 6 additions & 0 deletions content/in-app-ui/react/card.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: "Card"
description: How to ship an inline card using our pre-built guides component.
tags: ["card", "guides"]
section: Building in-app UI
---
9 changes: 9 additions & 0 deletions content/in-app-ui/react/feed.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ Our `@knocklabs/react` library comes pre-built with a real-time feed component t

[See a live demo of our pre-built in-app feed UI element ->](https://in-app-demo.knock.app/)

<Image
src="/images/in-app-ui/Docs_FeedImage.png"
alt="FeedComponent"
width={1356}
height={1000}
className="mx-auto border border-gray-200"
style={{ borderRadius: "var(--tgph-rounded-5)" }}
/>

## Getting started

To use this example, you'll need [an account on Knock](https://dashboard.knock.app), as well as an in-app feed channel with a workflow that produces in-app feed messages. You'll also need:
Expand Down
259 changes: 259 additions & 0 deletions content/in-app-ui/react/modal.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
---
title: "Modal"
description: How to ship an in-app notification modal using our pre-built guides component.
tags: ["modal", "guides"]
section: Building in-app UI
---

Our `@knocklabs/react` library comes with a pre-built modal component you can drop into your application.

The modal component enables you to display important notifications, announcements, or interactive content in a focused overlay that appears above your application's main content.

<Image
src="/images/in-app-ui/Docs_ModalImage.png"
alt="ModalComponent"
width={1356}
height={1000}
className="mx-auto border border-gray-200"
style={{ borderRadius: "var(--tgph-rounded-5)" }}
/>

<Callout
emoji="🚧"
bgColor="blue"
text={
<>
Guides are currently in beta. If you'd like early access, or this is
blocking your adoption of Knock, please{" "}
<a href="mailto:[email protected]?subject=Guides%20beta%20access">
get in touch
</a>
.
</>
}
/>

## Getting started

To use the modal component, you'll need:

- [An account on Knock](https://dashboard.knock.app)
- A guide channel set up in your Knock dashboard
- A guide created using the "Modal" [message type](/in-app-ui/message-types)

<Callout
emoji="⚠️"
text={
<>
<span className="font-bold">Note:</span> You must be on @knocklabs/react
version 0.7.0 or higher to use guides-related features.
</>
}
/>

### Installing dependencies

```bash title="Installing dependencies"
npm install @knocklabs/react
```

## Basic usage

<Steps titleSize="h3">
<Step title="Setup the KnockGuideProvider">

First, wrap your application with the `KnockProvider` and `KnockGuideProvider`. The `KnockGuideProvider` requires a `channelId`. You can find your guide channel ID on the integrations page in the dashboard under "Channels".

```tsx title="Setup the KnockGuideProvider within your product."
import { KnockProvider, KnockGuideProvider } from "@knocklabs/react";
import { useCurrentUser } from "@/lib/hooks";

const MyApplication = () => {
// Get your authenticated current user
const currentUser = useCurrentUser();

return (
<KnockProvider
apiKey={process.env.NEXT_PUBLIC_KNOCK_API_KEY}
userId={currentUser.id}
>
<KnockGuideProvider
channelId={process.env.NEXT_PUBLIC_KNOCK_GUIDE_CHANNEL_ID}
>
<Header />
<Sidebar />
{/* Rest of your app */}
Comment on lines +83 to +85
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<Header />
<Sidebar />
{/* Rest of your app */}
<MyLayout>
{/* Rest of your app */}
</MyLayout>

Just a thought that I had, whether it'd be good to reference the component we are using as an example below.

</KnockGuideProvider>
</KnockProvider>
);
};
```

</Step>
<Step title="Add the Modal component">

Import Knock's pre-built `Modal` component and place it under the `KnockGuideProvider` near the top of your application. The `<Modal/>` component is most effective when placed in the root layout of your application, this ensures that your modal is available to render on every page of your application.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Import Knock's pre-built `Modal` component and place it under the `KnockGuideProvider` near the top of your application. The `<Modal/>` component is most effective when placed in the root layout of your application, this ensures that your modal is available to render on every page of your application.
Import Knock's pre-built `Modal` component and place it inside the `KnockGuideProvider` near the top of your application's component tree. The `<Modal/>` component is most effective when placed in the root layout of your application, this ensures that your modal is available to render on every page of your application.


```tsx title="Add the modal near the top of your application."
import { Modal } from "@knocklabs/react";

const DashboardLayout = ({children}) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const DashboardLayout = ({children}) => {
const MyLayout = ({children}) => {

return (
<div>
<header>My App Header</header>
<main>
{children}
</main>
<Modal />
</div>
);
};
```

</Step>
<Step title="Mount the component">

The `Modal` component will mount automatically when a user becomes eligible for a guide created using the `modal` message type.

Remember, for a user to be eligible, they must match the targeting rules of the guide, and they must be in a page in your application that matches the activation rules of the guide.

You can learn more about guide targeting and activation rules in the [creating guides](/in-app-ui/guides/create-guides) page.

</Step>
</Steps>

## Working with modal variants

The pre-built modal message type supports three variants for different use cases:

- **Default.** A dismissible modal with no action buttons.
- **Single action.** A dismissible modal with a single action button.
- **Multi-action.** A dismissible modal with two action buttons.

## Handling user engagement

The modal component handles user engagement tracking automatically. Here's an overview of what user behavior maps to which engagement statuses tracked in Knock.

- **Seen.** The modal has been rendered to (seen by) the user.
- **Interacted.** The user has interacted with (clicked) the modal. Dismissing the modal does not count as an interaction.
- **Archived.** The modal has been archived (dismissed) by the user.

## Styling your modal

### CSS customization

You can style your modal using standard CSS. Here's a basic example:

```css title="Modal styles"
.modal-overlay {
Copy link
Contributor

Choose a reason for hiding this comment

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

The class names here are not quite right. Here is what we have in the latest SDK we can reference.

One other thing to touch on in this "Styling" section is that we use css variables (e.g. --knock-guide-accent) in our css definitions (linked above). This was intentional as we wanted to make it easy to "theme" the prebuilt components using your own color tokens if you are otherwise happy with how the components are styled. More specifically, the ones prefixed with --knock-guide- are meant to be overridden for the theming purposes.

So there are different layers of abstractions we provide that you can use to approach styling, from the simplest (but limited) to most involved (but flexible):

  • Override the --knock-guide- css vars to "theme" the components with your own colors
  • Override some or all of the css definitions to completely customize the styles
  • Use the individual sub components to compose your own component (and use inline style props, if needed)
    • This is technically available but i think at this point most people would reach for the BYOC option
  • "Bring your own component (BYOC)" and style freely, and leverage the useGuide hook to power it.

position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}

.modal-content {
background: white;
border-radius: 8px;
padding: 24px;
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
}

.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}

.modal-body {
margin-bottom: 24px;
}

.modal-footer {
display: flex;
justify-content: flex-end;
gap: 8px;
}

.close-button {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #666;
}

.primary-button {
background: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}

.secondary-button {
background: transparent;
color: #007bff;
border: 1px solid #007bff;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
```

## Build your own modal component

You can build your own modal component using the `useGuide` hook.

```tsx title="Building your own modal component"
import { useEffect } from "react";
import { useGuide } from "@knocklabs/react";

const ByoModal = () => {
const { step } = useGuide({ type: "modal" });

useEffect(() => {
if (step) step.markAsSeen();
}, [step]);

if (!step) return null;

return (
<div onClick={() => step.markAsInteracted()}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it'd be better to show an example with a button and step.markAsInteracted() as an onClick handler for the button rather than at the root container, because this markup structure can lead to firing markAsInteracted when a dismiss button is clicked inside, for example. You can prevent that with event.preventDefault() and/or event.stopPropagation() but that's more things to explain.

{step.content.primary_button && (
  <button onClick={() => step.markAsInteracted()}>...</button>
)}

<h3>{step.content.title}</h3>
<p>{step.content.body}</p>
</div>
);
};
```

<Callout
emoji="⚠️"
text={
<>
<span className="font-bold">Note:</span> If your custom modal component
needs any fields not included in our pre-built modal message type and its
variants, you'll need to archive the pre-built modal message type and
create your own.
</>
}
/>

## Related links

- [Creating guides](/in-app-ui/guides/create-guides)
- [Rendering guides](/in-app-ui/guides/render-guides)
- [Message types](/in-app-ui/message-types)
- [React SDK reference](/in-app-ui/react/sdk/reference)
3 changes: 3 additions & 0 deletions data/sidebars/inAppSidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ export const REACT_SIDEBAR: SidebarSection[] = [
{ slug: "/feed", title: "Feed" },
{ slug: "/toasts", title: "Toast" },
{ slug: "/inbox", title: "Inbox" },
{ slug: "/card", title: "Card" },
{ slug: "/banner", title: "Banner" },
{ slug: "/modal", title: "Modal" },
{ slug: "/preferences", title: "Preferences" },
{ slug: "/slack-kit", title: "SlackKit" },
{ slug: "/teams-kit", title: "TeamsKit" },
Expand Down
Binary file added public/images/in-app-ui/Docs_FeedImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/in-app-ui/Docs_ModalImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading