Skip to content
Merged
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
16 changes: 5 additions & 11 deletions components/ask-salem.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.launcherGroup {
position: fixed;
bottom: 16px;
left: 16px;
right: 16px;
z-index: 60;
display: inline-flex;
align-items: stretch;
Expand All @@ -14,17 +14,11 @@
transition: border-color 0.15s ease;
}

/* On viewports where the docs sidebar shows, clear its footer row
(search shortcut + theme toggle) instead of covering it. Applied only on
/docs routes via .overSidebar — and dropped while the feedback panel is
open, since that panel sits at bottom: 88px in the same corner. */
/* The bottom-right corner has no fixed docs chrome (the sidebar footer is
bottom-left), so no lift is needed on /docs routes. */
@media (min-width: 768px) {
.launcherGroup {
left: 24px;
}

.launcherGroup.overSidebar {
bottom: 78px;
right: 24px;
}
}

Expand Down Expand Up @@ -61,7 +55,7 @@
.panel {
position: fixed;
bottom: 24px;
left: 24px;
right: 24px;
z-index: 61;
display: flex;
flex-direction: column;
Expand Down
11 changes: 2 additions & 9 deletions components/ask-salem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// markdown subset using React elements — never innerHTML.
//
// The launcher is shared with the OpenCoven Feedback widget: one pill,
// bottom-left, with an "Ask Salem" segment (this chat panel) and a
// bottom-right, with an "Ask Salem" segment (this chat panel) and a
// "Feedback" segment (the feedback panel from feedback.opencoven.ai,
// mounted with its own launcher disabled — see lib/feedback-widget). The
// two panels are mutually exclusive.
Expand All @@ -28,7 +28,6 @@ import {
type ReactNode,
} from 'react';
import { Icon } from '@iconify/react';
import { usePathname } from 'next/navigation';
import {
CLIENT_MARKER_HEADER,
CLIENT_MARKER_VALUE,
Expand Down Expand Up @@ -173,9 +172,6 @@ function parseRetryAfterSec(res: Response): number {
export function AskSalem() {
const [open, setOpen] = useState(false);
const [feedbackOpen, setFeedbackOpen] = useState(false);
const pathname = usePathname();
// Docs pages pin a sidebar footer bottom-left; lift the launcher above it.
const overSidebar = pathname?.startsWith('/docs') ?? false;
const [question, setQuestion] = useState('');
const [log, setLog] = useState<Turn[]>([]);
const [streaming, setStreaming] = useState(false);
Expand Down Expand Up @@ -359,12 +355,9 @@ export function AskSalem() {
const blocked = streaming || cooldownSec > 0;

if (!open) {
// The feedback panel sits at bottom: 88px in this corner, so while it is
// open the sidebar lift is dropped to keep the launcher clear of it.
const lifted = overSidebar && !feedbackOpen;
return (
<div
className={lifted ? `${s.launcherGroup} ${s.overSidebar}` : s.launcherGroup}
className={s.launcherGroup}
role="group"
aria-label="Documentation assistant and feedback"
>
Expand Down
2 changes: 1 addition & 1 deletion content/docs/reference/ask-salem.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ read_when:

Every page on this site includes **Ask Salem**, a floating assistant backed by [salem.opencoven.ai](https://salem.opencoven.ai) — a retrieval service that indexes this documentation and answers questions with linked sources. No account or token is required.

Salem shares its launcher with the site's [feedback widget](/docs/reference/feedback-widget): one pill, bottom-left, with an **Ask Salem** segment that opens the chat panel and a **Feedback** segment that opens the OpenCoven Feedback panel. The two panels are mutually exclusive, and the feedback SDK is loaded lazily the first time the Feedback segment is used.
Salem shares its launcher with the site's [feedback widget](/docs/reference/feedback-widget): one pill, bottom-right, with an **Ask Salem** segment that opens the chat panel and a **Feedback** segment that opens the OpenCoven Feedback panel. The two panels are mutually exclusive, and the feedback SDK is loaded lazily the first time the Feedback segment is used.

## Transport paths

Expand Down
2 changes: 1 addition & 1 deletion content/docs/reference/feedback-widget.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ OpenCovenFeedback('logout')

To restrict the widget so only your own users can submit feedback, use the SSO token shape and call `init` with `launcher: false`. Then mount the launcher yourself once identity resolves.

> `launcher: false` is also the hook for replacing the floating bubble with your own UI: call `open`/`close` from any element you control. This docs site does exactly that — its bottom-left launcher is shared with the [Ask Salem assistant](/docs/reference/ask-salem), and the Feedback segment drives the widget through `init({ launcher: false, placement: 'left' })` plus `open`.
> `launcher: false` is also the hook for replacing the floating bubble with your own UI: call `open`/`close` from any element you control. This docs site does exactly that — its bottom-right launcher is shared with the [Ask Salem assistant](/docs/reference/ask-salem), and the Feedback segment drives the widget through `init({ launcher: false, placement: 'right' })` plus `open`.

```ts
// 1. Load without showing the launcher
Expand Down
4 changes: 2 additions & 2 deletions lib/feedback-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function quackback(): QuackbackFn {

/**
* Injects the SDK script once and initializes the widget without its own
* launcher, panel anchored bottom-left next to the shared launcher. Resolves
* launcher, panel anchored bottom-right next to the shared launcher. Resolves
* when the script has loaded; rejects if it fails (offline, content
* blockers), letting callers fall back to FEEDBACK_PORTAL.
*/
Expand All @@ -48,7 +48,7 @@ export function ensureFeedbackWidget(): Promise<void> {
return Promise.reject(new Error('Feedback widget is client-side only'));
}
if (loadPromise) return loadPromise;
quackback()('init', { launcher: false, placement: 'left' });
quackback()('init', { launcher: false, placement: 'right' });
loadPromise = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.id = SCRIPT_ID;
Expand Down