diff --git a/content/in-app-ui/guides/overview.mdx b/content/in-app-ui/guides/overview.mdx index d44593a89..ab7813089 100644 --- a/content/in-app-ui/guides/overview.mdx +++ b/content/in-app-ui/guides/overview.mdx @@ -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.) diff --git a/content/in-app-ui/react/banner.mdx b/content/in-app-ui/react/banner.mdx new file mode 100644 index 000000000..048b2a7c3 --- /dev/null +++ b/content/in-app-ui/react/banner.mdx @@ -0,0 +1,392 @@ +--- +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 +--- + +Our `@knocklabs/react` library comes with a pre-built banner component you can drop into your application. + +The banner component enables you to display important notifications, alerts, or announcements in a prominent position at the top of your application's content area, ensuring users see critical information without interrupting their workflow. + +BannerComponent + + + Guides are currently in beta. If you'd like early access, or this is + blocking your adoption of Knock, please{" "} + + get in touch + + . + + } +/> + +## Getting started + +To use the banner 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 "Banner" [message type](/in-app-ui/message-types) + + + Note: You must be on @knocklabs/react + version 0.7.0 or higher to use Knock guides. + + } +/> + +### Installing dependencies + +```bash title="Installing dependencies" +npm install @knocklabs/react +``` + +## Basic usage + + + + + 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 ( + + + + {/* Rest of your app */} + + + + ); + }; + ``` + + + + + Import Knock's pre-built `Banner` component and place it inside the `KnockGuideProvider` at the top of your page or layout. The `` component is most effective when positioned prominently at the top of the content area where users will naturally notice it. + + ```tsx title="Add the banner at the top of your page or layout." + import { Banner } from "@knocklabs/react"; + + const MyLayout = ({children}) => { + return ( +
+
My App Header
+ +
+ {children} +
+
+ ); + }; + ``` + +
+ + + The `Banner` component will mount automatically when a user becomes eligible for a guide created using the `banner` 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. + + +
+ +## Working with banner variants + +The pre-built banner message type supports three variants for different use cases: + +- **Default.** A banner with just text content. +- **Single action.** A banner with a single action button. +- **Multi action.** A banner with multiple action buttons. + +BannerVariants + +## Handling user engagement + +The banner component handles user engagement tracking automatically. Here's an overview of what user behavior maps to which engagement statuses tracked in Knock. + +- **Seen.** The banner has been rendered to (seen by) the user. +- **Interacted.** The user has interacted with (clicked) the banner or its action buttons. Dismissing the banner does not count as an interaction. +- **Archived.** The banner has been archived (dismissed) by the user. + +## Styling your banner + +Knock provides multiple levels of customization for the banner component, from simple theming to complete custom implementations. Choose the approach that best fits your needs. + +### CSS variable theming + +The easiest way to customize the banner's appearance is by overriding CSS variables. Knock provides CSS variables prefixed with `--knock-guide-` that are specifically designed for theming all of Knock's pre-built guide components. + +```css title="Theme your banner with CSS variables" +:root { + --knock-guide-accent: #your-brand-color; + --knock-guide-background: #your-background-color; + --knock-guide-text: #your-text-color; + --knock-guide-border: #your-border-color; + --knock-guide-border-radius: 8px; + --knock-guide-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} +``` + +This approach enables you to quickly match your brand colors and basic styling without diving into complex CSS overrides. The `--knock-guide-accent` variable is particularly useful for theming buttons and interactive elements. + +### CSS class overrides + +For more granular control, you can override the specific CSS classes used by the banner component. All Knock guide components use classes that start with prefixes specific to the component type. + + + Note: You may need to add{" "} + !important to your CSS overrides to ensure they take + precedence over the component's default styles. + + } +/> + +```css title="Override banner CSS classes" +/* Banner container */ +.knock-guide-banner { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 16px 24px; + border-radius: 8px; + margin-bottom: 16px; + display: flex; + align-items: center; + justify-content: space-between; +} + +/* Banner message content */ +.knock-guide-banner__message { + flex: 1; + min-width: 0; +} + +.knock-guide-banner__title { + font-size: 16px; + font-weight: 600; + line-height: 1.4; + margin-bottom: 4px; + color: var(--knock-guide-title-color); +} + +.knock-guide-banner__body { + font-size: 14px; + line-height: 1.5; + color: var(--knock-guide-body-color); +} + +.knock-guide-banner__body p:first-child { + margin-top: 0; +} + +.knock-guide-banner__body p:last-child { + margin-bottom: 0; +} + +/* Banner actions */ +.knock-guide-banner__actions { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.knock-guide-banner__action { + padding: 8px 16px; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + text-decoration: none; + cursor: pointer; + border: 1px solid transparent; + background: var(--knock-guide-accent); + color: white; +} + +.knock-guide-banner__action--secondary { + background: transparent; + color: var(--knock-guide-accent); + border: 1px solid var(--knock-guide-accent); +} + +/* Close button */ +.knock-guide-banner__close { + background: transparent; + border: none; + cursor: pointer; + padding: 8px; + color: var(--knock-guide-text-muted); +} +``` + +### Individual subcomponents + +For maximum flexibility while still leveraging Knock's functionality, you can use the individual subcomponents to compose your own banner. This approach gives you full control over the layout and styling while maintaining the guide behavior: + +```tsx title="Compose your own banner with subcomponents" +import { + useGuide, + BannerContainer, + BannerContent, + BannerText, + BannerActions, + BannerButton, + BannerCloseButton, +} from "@knocklabs/react"; +import { useEffect } from "react"; + +const CustomBanner = () => { + const { step } = useGuide({ type: "banner" }); + + useEffect(() => { + if (step) step.markAsSeen(); + }, [step]); + + if (!step) return null; + + return ( + + + + {step.content.title} +

{step.content.body}

+
+ + + {step.content.actions?.map((action, index) => ( + { + step.markAsInteracted(); + // Handle action + }} + style={{ + background: "rgba(255, 255, 255, 0.2)", + color: "white", + padding: "6px 12px", + borderRadius: "4px", + border: "none", + }} + > + {action.label} + + ))} + + step.markAsArchived()} + style={{ + background: "transparent", + color: "rgba(255, 255, 255, 0.8)", + border: "none", + padding: "4px", + }} + > + × + + +
+
+ ); +}; +``` + +This approach is ideal when you want to customize a piece of the pre-built component or change its structure. + +## Building your own component + +For complete control over both functionality and appearance, you can build your own banner component using the `useGuide` hook. This approach gives you the most flexibility but requires implementing all the banner behavior yourself: + +```tsx title="Building your own banner component" +import { useEffect } from "react"; +import { useGuide } from "@knocklabs/react"; + +const CustomBanner = () => { + const { step } = useGuide({ type: "banner" }); + + useEffect(() => { + if (step) step.markAsSeen(); + }, [step]); + + if (!step) return null; + + return ( +
+

{step.content.title}

+

{step.content.body}

+ {step.content.primary_button && ( + + )} +
+ ); +}; +``` + + + Note: If your custom banner component + needs any fields not included in our pre-built banner message type and its + variants, you'll need to archive the pre-built banner 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) diff --git a/content/in-app-ui/react/card.mdx b/content/in-app-ui/react/card.mdx new file mode 100644 index 000000000..e884f2cc2 --- /dev/null +++ b/content/in-app-ui/react/card.mdx @@ -0,0 +1,421 @@ +--- +title: "Card" +description: How to ship an inline card using our pre-built guides component. +tags: ["card", "guides"] +section: Building in-app UI +--- + +Our `@knocklabs/react` library comes with a pre-built card component you can drop into your application. + +The card component enables you to display contextual information, tips, or interactive content inline within your application's content flow, providing users with relevant guidance without disrupting their current task. + +CardComponent + + + Guides are currently in beta. If you'd like early access, or this is + blocking your adoption of Knock, please{" "} + + get in touch + + . + + } +/> + +## Getting started + +To use the card 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 "Card" [message type](/in-app-ui/message-types) + + + Note: You must be on @knocklabs/react + version 0.7.0 or higher to use Knock guides. + + } +/> + +### Installing dependencies + +```bash title="Installing dependencies" +npm install @knocklabs/react +``` + +## Basic usage + + + + + 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 ( + + + + {/* Rest of your app */} + + + + ); + }; + ``` + + + + + Import Knock's pre-built `Card` component and place it inside the `KnockGuideProvider` wherever you want contextual guidance to appear. The `` component is most effective when positioned inline within your content where it can provide relevant information at the right moment. + + ```tsx title="Add the card within your page content." + import { Card } from "@knocklabs/react"; + + const Sidebar = () => { + return ( + + ); + }; + + const MyPage = () => { + return ( +
+

Welcome to Dashboard

+
+ +
+ {/* Your page content */} +
+
+
+ ); + }; + ``` + +
+ + + The `Card` component will mount automatically when a user becomes eligible for a guide created using the `card` 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. + + +
+ +## Working with card variants + +The pre-built card message type supports three variants for different use cases: + +- **Default.** A simple card with content and optional dismiss functionality. +- **Interactive.** A card with action buttons for user interaction. +- **Compact.** A smaller card variant for less prominent guidance. + +CardVariants + +## Handling user engagement + +The card component handles user engagement tracking automatically. Here's an overview of what user behavior maps to which engagement statuses tracked in Knock. + +- **Seen.** The card has been rendered to (seen by) the user. +- **Interacted.** The user has interacted with (clicked) the card or its action buttons. Dismissing the card does not count as an interaction. +- **Archived.** The card has been archived (dismissed) by the user. + +## Styling your card + +Knock provides multiple levels of customization for the card component, from simple theming to complete custom implementations. Choose the approach that best fits your needs: + +### CSS variable theming + +The easiest way to customize the card's appearance is by overriding CSS variables. Knock provides CSS variables prefixed with `--knock-guide-` that are specifically designed for theming all of Knock's pre-built guide components. + +```css title="Theme your card with CSS variables" +:root { + --knock-guide-accent: #your-brand-color; + --knock-guide-background: #your-background-color; + --knock-guide-text: #your-text-color; + --knock-guide-border: #your-border-color; + --knock-guide-border-radius: 8px; + --knock-guide-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); +} +``` + +This approach enables you to quickly match your brand colors and basic styling without diving into complex CSS overrides. The `--knock-guide-accent` variable is particularly useful for theming buttons and interactive elements. + +### CSS class overrides + +For more granular control, you can override the specific CSS classes used by the card component. All Knock guide components use classes that start with prefixes specific to the component type. + + + Note: You may need to add{" "} + !important to your CSS overrides to ensure they take + precedence over the component's default styles. + + } +/> + +```css title="Override card CSS classes" +/* Card container */ +.knock-guide-card { + background: white; + border: 1px solid var(--knock-guide-border); + border-radius: 12px; + padding: 20px; + margin: 16px 0; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; +} + +/* Card header */ +.knock-guide-card__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + margin-bottom: 12px; +} + +.knock-guide-card__headline { + font-size: 18px; + font-weight: 600; + line-height: 1.4; + color: var(--knock-guide-title-color); + margin: 0; +} + +/* Card message content */ +.knock-guide-card__message { + flex: 1; + display: flex; + flex-direction: column; + align-items: flex-start; +} + +.knock-guide-card__title { + font-size: 16px; + font-weight: 600; + line-height: 1.4; + color: var(--knock-guide-title-color); + margin-bottom: 8px; +} + +.knock-guide-card__body { + font-size: 14px; + line-height: 1.5; + color: var(--knock-guide-body-color); + margin-bottom: 16px; +} + +/* Card image */ +.knock-guide-card__img { + display: block; + max-width: 100%; + height: auto; + margin-bottom: 16px; + border-radius: 8px; +} + +/* Card actions */ +.knock-guide-card__actions { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 12px; + margin-top: auto; +} + +.knock-guide-card__action { + padding: 8px 16px; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + text-decoration: none; + cursor: pointer; + border: 1px solid transparent; + background: var(--knock-guide-accent); + color: white; +} + +.knock-guide-card__action--secondary { + background: transparent; + color: var(--knock-guide-accent); + border: 1px solid var(--knock-guide-accent); +} + +/* Close button */ +.knock-guide-card__close { + background: transparent; + border: none; + cursor: pointer; + padding: 8px; + color: var(--knock-guide-text-muted); +} +``` + +### Individual subcomponents + +For maximum flexibility while still leveraging Knock's functionality, you can use the individual subcomponents to compose your own card. This approach gives you full control over the layout and styling while maintaining the guide behavior: + +```tsx title="Compose your own card with subcomponents" +import { + useGuide, + CardContainer, + CardHeader, + CardTitle, + CardBody, + CardFooter, + CardButton, + CardCloseButton, +} from "@knocklabs/react"; +import { useEffect } from "react"; + +const CustomCard = () => { + const { step } = useGuide({ type: "card" }); + + useEffect(() => { + if (step) step.markAsSeen(); + }, [step]); + + if (!step) return null; + + return ( + + + + {step.content.title} + + step.markAsArchived()} + style={{ color: "rgba(255, 255, 255, 0.8)" }} + /> + + + +

{step.content.body}

+
+ + + {step.content.actions?.map((action, index) => ( + { + step.markAsInteracted(); + // Handle action + }} + style={{ + background: "rgba(255, 255, 255, 0.2)", + color: "white", + border: "1px solid rgba(255, 255, 255, 0.3)", + borderRadius: "8px", + padding: "10px 20px", + }} + > + {action.label} + + ))} + +
+ ); +}; +``` + +This approach is ideal when you want to customize a piece of the pre-built component or change its structure. + +## Building your own component + +For complete control over both functionality and appearance, you can build your own card component using the `useGuide` hook. This approach gives you the most flexibility but requires implementing all the card behavior yourself: + +```tsx title="Building your own card component" +import { useEffect } from "react"; +import { useGuide } from "@knocklabs/react"; + +const CustomCard = () => { + const { step } = useGuide({ type: "card" }); + + useEffect(() => { + if (step) step.markAsSeen(); + }, [step]); + + if (!step) return null; + + return ( +
+

{step.content.title}

+

{step.content.body}

+ {step.content.primary_button && ( + + )} +
+ ); +}; +``` + + + Note: If your custom card component + needs any fields not included in our pre-built card message type and its + variants, you'll need to archive the pre-built card 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) diff --git a/content/in-app-ui/react/feed.mdx b/content/in-app-ui/react/feed.mdx index 8d52c9fd8..e0c6cfd6d 100644 --- a/content/in-app-ui/react/feed.mdx +++ b/content/in-app-ui/react/feed.mdx @@ -1,5 +1,5 @@ --- -title: "Building notification feeds with React" +title: "Feed" description: How to ship an in-app notification feed using our pre-built feed component. tags: ["inbox", "feeds", "toasts", "action_url"] section: Building in-app UI @@ -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/) +FeedComponent + ## 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: diff --git a/content/in-app-ui/react/inbox.mdx b/content/in-app-ui/react/inbox.mdx index 63f3f0d07..e07755e67 100644 --- a/content/in-app-ui/react/inbox.mdx +++ b/content/in-app-ui/react/inbox.mdx @@ -1,6 +1,6 @@ --- -title: "Building notification inboxes with React" -description: How to build notification inboxes powered by Knock and React. +title: "Inbox" +description: How to build a notification inbox powered by Knock and React. section: Building in-app UI --- diff --git a/content/in-app-ui/react/modal.mdx b/content/in-app-ui/react/modal.mdx new file mode 100644 index 000000000..30469efad --- /dev/null +++ b/content/in-app-ui/react/modal.mdx @@ -0,0 +1,378 @@ +--- +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. + +ModalComponent + + + Guides are currently in beta. If you'd like early access, or this is + blocking your adoption of Knock, please{" "} + + get in touch + + . + + } +/> + +## 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) + + + Note: You must be on @knocklabs/react + version 0.7.0 or higher to use Knock guides. + + } +/> + +### Installing dependencies + +```bash title="Installing dependencies" +npm install @knocklabs/react +``` + +## Basic usage + + + + + 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 ( + + + + {/* Rest of your app */} + + + + ); + }; + ``` + + + + + Import Knock's pre-built `Modal` component and place it inside the `KnockGuideProvider` near the top of your application's component tree. The `` component is most effective when placed in the root layout of your application as it ensures 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 MyLayout = ({children}) => { + return ( +
+
My App Header
+
+ {children} +
+ +
+ ); + }; + ``` + +
+ + + 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. + + +
+ +## 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. + +ModalVariants + +## 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 + +Knock provides multiple levels of customization for the modal component, from simple theming to complete custom implementations. Choose the approach that best fits your needs: + +### CSS variable theming + +The easiest way to customize the modal's appearance is by overriding CSS variables. Knock provides CSS variables prefixed with `--knock-guide-` that are specifically designed for theming all of Knock's pre-built guide components. + +```css title="Theme your modal with CSS variables" +:root { + --knock-guide-accent: #your-brand-color; + --knock-guide-background: #your-background-color; + --knock-guide-text: #your-text-color; + --knock-guide-border: #your-border-color; + --knock-guide-border-radius: 8px; + --knock-guide-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} +``` + +This approach enables you to quickly match your brand colors and basic styling without diving into complex CSS overrides. The `--knock-guide-accent` variable is particularly useful for theming buttons and interactive elements. + +### CSS class overrides + +For more granular control, you can override the specific CSS classes used by the modal component. All Knock guide components use classes that start with prefixes specific to the component type. + + + Note: You may need to add{" "} + !important to your CSS overrides to ensure they take + precedence over the component's default styles. + + } +/> + +```css title="Override modal CSS classes" +/* Modal overlay */ +.knock-guide-modal__overlay { + background: rgba(0, 0, 0, 0.8); + backdrop-filter: blur(4px); +} + +/* Modal container */ +.knock-guide-modal { + border-radius: 12px; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); + max-width: 600px; +} + +/* Modal content areas */ +.knock-guide-modal__header { + border-bottom: 1px solid var(--knock-guide-border); + padding-bottom: 16px; +} + +.knock-guide-modal__title { + font-size: 20px; + font-weight: 600; + color: var(--knock-guide-title-color); +} + +.knock-guide-modal__body { + padding: 24px 0; + line-height: 1.6; + color: var(--knock-guide-body-color); +} + +.knock-guide-modal__actions { + display: flex; + gap: 12px; + justify-content: flex-end; +} + +/* Action buttons */ +.knock-guide-modal__action { + background: var(--knock-guide-accent); + color: white; + border: none; + border-radius: 6px; + padding: 12px 24px; + font-weight: 600; + cursor: pointer; +} + +.knock-guide-modal__action--secondary { + background: transparent; + color: var(--knock-guide-accent); + border: 2px solid var(--knock-guide-accent); +} + +/* Close button */ +.knock-guide-modal__close { + background: transparent; + border: none; + cursor: pointer; + padding: 8px; + color: var(--knock-guide-text-muted); +} + +/* Image styling */ +.knock-guide-modal__img { + width: 100%; + height: auto; + border-radius: 8px; +} +``` + +### Individual subcomponents + +For maximum flexibility while still leveraging Knock's functionality, you can use the individual subcomponents to compose your own modal. This approach gives you full control over the layout and styling while maintaining the guide behavior: + +```tsx title="Compose your own modal with subcomponents" +import { + useGuide, + ModalOverlay, + ModalContainer, + ModalHeader, + ModalBody, + ModalFooter, + ModalCloseButton, +} from "@knocklabs/react"; +import { useEffect } from "react"; + +const CustomModal = () => { + const { step } = useGuide({ type: "modal" }); + + useEffect(() => { + if (step) step.markAsSeen(); + }, [step]); + + if (!step) return null; + + return ( + step.markAsArchived()}> + e.stopPropagation()} + style={{ + background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", + color: "white", + borderRadius: "16px", + }} + > + +

{step.content.title}

+ step.markAsArchived()} /> +
+ + +

{step.content.body}

+
+ + + {step.content.actions?.map((action, index) => ( + + ))} + +
+
+ ); +}; +``` + +This approach is ideal when you want to customize a piece of the pre-built component or change its structure. + +## Building your own component + +For complete control over both functionality and appearance, you can build your own modal component using the `useGuide` hook. This approach gives you the most flexibility but requires implementing all the modal behavior yourself: + +```tsx title="Building your own modal component" +import { useEffect } from "react"; +import { useGuide } from "@knocklabs/react"; + +const CustomModal = () => { + const { step } = useGuide({ type: "modal" }); + + useEffect(() => { + if (step) step.markAsSeen(); + }, [step]); + + if (!step) return null; + + return ( +
+

{step.content.title}

+

{step.content.body}

+ {step.content.primary_button && ( + + )} +
+ ); +}; +``` + + + Note: 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) diff --git a/content/in-app-ui/react/preferences.mdx b/content/in-app-ui/react/preferences.mdx index 9ee8a7eab..5e4fed3c5 100644 --- a/content/in-app-ui/react/preferences.mdx +++ b/content/in-app-ui/react/preferences.mdx @@ -1,5 +1,5 @@ --- -title: "Building preference UIs in React" +title: "Preferences" description: How to build a complete notification preference center, powered by Knock and React. section: Building in-app UI --- diff --git a/content/in-app-ui/react/toasts.mdx b/content/in-app-ui/react/toasts.mdx index de0485983..64059b099 100644 --- a/content/in-app-ui/react/toasts.mdx +++ b/content/in-app-ui/react/toasts.mdx @@ -1,6 +1,6 @@ --- -title: "Building notification toasts with React" -description: How to build notification toasts powered by Knock and React. +title: "Toast" +description: How to build in-app toasts powered by Knock and React. section: Building in-app UI --- diff --git a/data/sidebars/inAppSidebar.ts b/data/sidebars/inAppSidebar.ts index 3d744d7d3..0ff292441 100644 --- a/data/sidebars/inAppSidebar.ts +++ b/data/sidebars/inAppSidebar.ts @@ -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" }, diff --git a/public/images/in-app-ui/Docs_BannerHero.png b/public/images/in-app-ui/Docs_BannerHero.png new file mode 100644 index 000000000..011dd4f6c Binary files /dev/null and b/public/images/in-app-ui/Docs_BannerHero.png differ diff --git a/public/images/in-app-ui/Docs_BannerVariants.png b/public/images/in-app-ui/Docs_BannerVariants.png new file mode 100644 index 000000000..f63898535 Binary files /dev/null and b/public/images/in-app-ui/Docs_BannerVariants.png differ diff --git a/public/images/in-app-ui/Docs_CardHero.png b/public/images/in-app-ui/Docs_CardHero.png new file mode 100644 index 000000000..d9911ea5b Binary files /dev/null and b/public/images/in-app-ui/Docs_CardHero.png differ diff --git a/public/images/in-app-ui/Docs_CardVariants.png b/public/images/in-app-ui/Docs_CardVariants.png new file mode 100644 index 000000000..87176202e Binary files /dev/null and b/public/images/in-app-ui/Docs_CardVariants.png differ diff --git a/public/images/in-app-ui/Docs_FeedImage.png b/public/images/in-app-ui/Docs_FeedImage.png new file mode 100644 index 000000000..ed59646b0 Binary files /dev/null and b/public/images/in-app-ui/Docs_FeedImage.png differ diff --git a/public/images/in-app-ui/Docs_ModalHero.png b/public/images/in-app-ui/Docs_ModalHero.png new file mode 100644 index 000000000..8c660f572 Binary files /dev/null and b/public/images/in-app-ui/Docs_ModalHero.png differ diff --git a/public/images/in-app-ui/Docs_ModalVariants.png b/public/images/in-app-ui/Docs_ModalVariants.png new file mode 100644 index 000000000..af602df49 Binary files /dev/null and b/public/images/in-app-ui/Docs_ModalVariants.png differ