Add a custom title and subtitle to the chatbot

This commit is contained in:
braginini
2026-03-13 18:43:08 +01:00
parent 11917c70c4
commit abfd65af4e
4 changed files with 25 additions and 15 deletions
+12 -12
View File
@@ -1,18 +1,18 @@
# netbird-explain
# @netbirdio/explain
AI-powered "Explain" assistant for React apps. Users click on UI elements and get contextual AI explanations via a chat panel.
The package has two entry points:
- `netbird-explain/client` — React components (provider, chat panel, floating button)
- `netbird-explain/server` — Node.js handler that proxies requests to Anthropic or OpenAI
- `@netbirdio/explain/client` — React components (provider, chat panel, floating button)
- `@netbirdio/explain/server` — Node.js handler that proxies requests to Anthropic or OpenAI
No CSS framework required — the package is fully self-contained with inline styles and CSS custom properties.
## Installation
```bash
npm install netbird-explain
npm install @netbirdio/explain
```
Peer dependencies: `react >=18`, `react-dom >=18`.
@@ -22,7 +22,7 @@ For local development as a workspace package, add it to your `package.json`:
```json
{
"dependencies": {
"netbird-explain": "file:./packages/netbird-explain"
"@netbirdio/explain": "file:./packages/@netbirdio/explain"
}
}
```
@@ -31,7 +31,7 @@ If you're using Next.js, add to `next.config.js`:
```js
module.exports = {
transpilePackages: ["netbird-explain"],
transpilePackages: ["@netbirdio/explain"],
};
```
@@ -44,7 +44,7 @@ module.exports = {
Wrap your app with `AIAssistantProvider`:
```tsx
import { AIAssistantProvider } from "netbird-explain/client";
import { AIAssistantProvider } from "@netbirdio/explain/client";
export default function App({ children }) {
return (
@@ -112,7 +112,7 @@ Use `data-nb-explain-ignore` to prevent an element from being selectable in expl
Use the `useAIAssistant` hook to provide context that gets included in every query:
```tsx
import { useAIAssistant } from "netbird-explain/client";
import { useAIAssistant } from "@netbirdio/explain/client";
function MyModal() {
const { setExplainContext, clearExplainContext } = useAIAssistant();
@@ -222,7 +222,7 @@ The server module provides a framework-agnostic handler that proxies chat reques
```ts
import express from "express";
import { createAssistant } from "netbird-explain/server";
import { createAssistant } from "@netbirdio/explain/server";
const assistant = createAssistant({
provider: "anthropic",
@@ -243,7 +243,7 @@ app.listen(3080);
```ts
import http from "http";
import { createAssistant } from "netbird-explain/server";
import { createAssistant } from "@netbirdio/explain/server";
const assistant = createAssistant({
provider: "openai",
@@ -341,7 +341,7 @@ Environment variables:
```tsx
// layout.tsx — wrap app with provider
import { AIAssistantProvider } from "netbird-explain/client";
import { AIAssistantProvider } from "@netbirdio/explain/client";
export default function Layout({ children }) {
return (
@@ -357,7 +357,7 @@ export default function Layout({ children }) {
```tsx
// MyModal.tsx — add explain support to a modal
import { useAIAssistant } from "netbird-explain/client";
import { useAIAssistant } from "@netbirdio/explain/client";
import { Sparkles } from "lucide-react";
function MyModal() {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "netbird-explain",
"name": "@netbirdio/explain",
"version": "0.1.0",
"description": "Full-stack AI assistant library with React frontend components and Node.js backend handler",
"license": "BSD-3-Clause",
+6
View File
@@ -40,6 +40,8 @@ type AIAssistantProviderProps = {
endpoint: string;
apiKey?: string;
children: React.ReactNode;
title?: string;
subtitle?: string;
};
/**
@@ -117,6 +119,8 @@ export default function AIAssistantProvider({
endpoint,
apiKey,
children,
title,
subtitle,
}: AIAssistantProviderProps) {
const [isChatOpen, setIsChatOpen] = useState(false);
const [initialQuery, setInitialQuery] = useState("");
@@ -282,6 +286,8 @@ export default function AIAssistantProvider({
initialQuery={initialQuery}
endpoint={endpoint}
apiKey={apiKey}
title={title}
subtitle={subtitle}
/>
</AIAssistantContext.Provider>
);
+6 -2
View File
@@ -18,6 +18,8 @@ type Props = {
initialQuery: string;
endpoint: string;
apiKey?: string;
title?: string;
subtitle?: string;
};
async function fetchAIResponse(
@@ -58,6 +60,8 @@ export default function AIChatBot({
initialQuery,
endpoint,
apiKey,
title = "AI Assistant",
subtitle = "Ask anything",
}: Props) {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState("");
@@ -183,8 +187,8 @@ export default function AIChatBot({
<Sparkles size={15} style={{ color: "var(--nb-explain-accent)" }} />
</div>
<div>
<h3 style={S.chatHeaderTitle}>AI Assistant</h3>
<span style={S.chatHeaderSubtitle}>Ask anything</span>
<h3 style={S.chatHeaderTitle}>{title}</h3>
<span style={S.chatHeaderSubtitle}>{subtitle}</span>
</div>
</div>
<button