update AI button w/ text (#947)

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->

Enhances AI chat button, and adds it to search as well. 

<img width="106" height="63" alt="image"
src="https://github.com/user-attachments/assets/e76ef5cb-9e27-40c8-bf0f-04940b214f44"
/>

<img width="710" height="291" alt="image"
src="https://github.com/user-attachments/assets/7c1ba130-8e15-4929-b8c7-475bb32fefaf"
/>

<!-- RECURSEML_SUMMARY:START -->
## High-level PR Summary
This PR enhances the AI chat button across the documentation site by
adding text labels alongside the sparkles icon, making it more
discoverable. The button now displays "AI Chat" text and has been
updated consistently across the home layout and shared header.
Additionally, an "Ask AI" fallback button has been added to the search
dialog footer to help users who can't find what they're looking for
through regular search.

⏱️ Estimated Review Time: 15-30 minutes

<details>
<summary>💡 Review Order Suggestion</summary>

| Order | File Path |
|-------|-----------|
| 1 | `docs/src/components/layouts/home-layout.tsx` |
| 2 | `docs/src/components/layouts/shared-header.tsx` |
| 3 | `docs/src/components/layout/custom-search-dialog.tsx` |
</details>



[![Need help? Join our
Discord](https://img.shields.io/badge/Need%20help%3F%20Join%20our%20Discord-5865F2?style=plastic&logo=discord&logoColor=white)](https://discord.gg/n3SsVDAW6U)


[![Analyze latest
changes](ba7372824c/?repo_owner=stack-auth&repo_name=stack-auth&pr_number=947)
<!-- RECURSEML_SUMMARY:END -->
<!-- ELLIPSIS_HIDDEN -->


----

> [!IMPORTANT]
> Enhances AI chat button with text labels and adds an "Ask AI" fallback
button to the search dialog, improving discoverability and user
experience.
> 
>   - **AI Chat Button Enhancements**:
> - Added text label "AI Chat" to the button in `home-layout.tsx` and
`shared-header.tsx`.
> - Introduced compact icon-only variant for tighter spaces in
`home-layout.tsx`.
> - Updated styling for better visibility and state-awareness when chat
is open.
>   - **Search Dialog**:
> - Added "Ask AI" fallback button in the footer of
`custom-search-dialog.tsx` to open AI chat if search results are
insufficient.
>   - **Styling Adjustments**:
> - Adjusted header spacing and layout for better alignment in
`shared-header.tsx`.
> - Refined footer structure in `custom-search-dialog.tsx` to
accommodate AI fallback.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup>
for 6e13d5a894. You can
[customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this
summary. It will automatically update as commits are pushed.</sup>

----


<!-- ELLIPSIS_HIDDEN -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added an “Ask AI” option in the search dialog footer that opens AI
chat as a fallback.
* Introduced a compact icon-only variant of the AI Chat toggle for
tighter spaces.

* **Style**
* Updated AI Chat controls with an inline label, smaller icon, and
state-aware styling when chat is open.
* Adjusted header spacing and layout for better alignment and
readability.
* Refined search dialog footer structure to accommodate the AI fallback
row.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
This commit is contained in:
Madison 2025-10-14 15:03:56 -05:00 committed by GitHub
parent b76fcb1282
commit 6b08d8bfcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 70 additions and 21 deletions

View File

@ -1,9 +1,10 @@
'use client';
import { AlignLeft, ChevronDown, ExternalLink, FileText, Hash, Search, X } from 'lucide-react';
import { AlignLeft, ChevronDown, ExternalLink, FileText, Hash, Search, Sparkles, X } from 'lucide-react';
import Link from 'next/link';
import { useCallback, useEffect, useRef, useState } from 'react';
import { cn } from '../../lib/cn';
import { useSidebar } from '../layouts/sidebar-context';
// Platform colors matching your theme
const PLATFORM_COLORS = {
@ -137,10 +138,28 @@ export function CustomSearchDialog({ open, onOpenChange }: CustomSearchDialogPro
const dropdownRef = useRef<HTMLDivElement>(null);
const searchTimeoutRef = useRef<NodeJS.Timeout>();
const sidebarContext = useSidebar();
// Available platforms for the dropdown
const availablePlatforms = ['all', 'next', 'react', 'js', 'python', 'api'];
// Handle AI chat opening
const handleOpenAIChat = () => {
onOpenChange(false); // Close search dialog first
if (!sidebarContext) {
return;
}
const { toggleChat } = sidebarContext;
// Small delay to ensure search dialog closes smoothly
setTimeout(() => {
if (!sidebarContext.isChatOpen) {
toggleChat();
}
}, 100);
};
// Close dropdown when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
@ -436,16 +455,30 @@ export function CustomSearchDialog({ open, onOpenChange }: CustomSearchDialogPro
</div>
{/* Footer */}
<div className="border-t border-fd-border px-3 py-2 text-xs text-fd-muted-foreground flex justify-between items-center">
<span>Use to navigate, Enter to select, Esc to close</span>
<span>
{filteredResults.length} result group{filteredResults.length !== 1 ? 's' : ''}
{selectedPlatformFilter !== 'all' && filteredResults.length > 0 && (
<span className="ml-2 text-fd-primary">
{PLATFORM_NAMES[selectedPlatformFilter as keyof typeof PLATFORM_NAMES]} only
</span>
)}
</span>
<div className="border-t border-fd-border px-3 py-2 text-xs text-fd-muted-foreground">
<div className="flex justify-between items-center mb-2">
<span>Use to navigate, Enter to select, Esc to close</span>
<span>
{filteredResults.length} result group{filteredResults.length !== 1 ? 's' : ''}
{selectedPlatformFilter !== 'all' && filteredResults.length > 0 && (
<span className="ml-2 text-fd-primary">
{PLATFORM_NAMES[selectedPlatformFilter as keyof typeof PLATFORM_NAMES]} only
</span>
)}
</span>
</div>
{/* AI Chat Fallback */}
<div className="flex justify-center items-center gap-2">
<span className="text-fd-muted-foreground">Can&apos;t find what you&apos;re looking for?</span>
<button
onClick={handleOpenAIChat}
className="flex items-center gap-1 px-2 py-1 text-xs rounded-md transition-all duration-300 ease-out relative overflow-hidden text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg"
>
<Sparkles className="h-3 w-3 relative z-10" />
<span className="font-medium relative z-10">Ask AI</span>
</button>
</div>
</div>
</div>
</div>

View File

@ -45,20 +45,33 @@ function StackAuthLogo() {
}
// AI Chat Toggle Button for Home Layout
function HomeAIChatToggleButton() {
function HomeAIChatToggleButton({ compact = false }: { compact?: boolean }) {
const sidebarContext = useSidebar();
const { isChatOpen, toggleChat } = sidebarContext || {
isChatOpen: false,
toggleChat: () => {},
};
if (compact) {
return (
<button
onClick={toggleChat}
className="flex items-center justify-center transition-all duration-500 ease-out w-8 h-8 rounded-lg text-sm font-medium relative overflow-hidden text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg"
title={isChatOpen ? 'Close AI chat' : 'Open AI chat'}
>
<Sparkles className="h-4 w-4 relative z-10" />
</button>
);
}
return (
<button
onClick={toggleChat}
className="flex items-center justify-center transition-all duration-500 ease-out w-8 h-8 rounded-lg text-sm font-medium relative overflow-hidden text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg"
className="flex items-center gap-2 transition-all duration-500 ease-out px-2 py-1 rounded-lg text-xs font-medium relative overflow-hidden text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg"
title={isChatOpen ? 'Close AI chat' : 'Open AI chat'}
>
<Sparkles className="h-4 w-4 relative z-10" />
<Sparkles className="h-3 w-3 relative z-10" />
<span className="font-medium relative z-10">AI Chat</span>
</button>
);
}
@ -248,7 +261,7 @@ function HomeNavbar() {
<ThemeToggle compact />
{/* Compact AI Chat Toggle */}
<HomeAIChatToggleButton />
<HomeAIChatToggleButton compact />
{/* Compact User Button */}
<UserButton />

View File

@ -81,18 +81,21 @@ function AIChatToggleButton() {
return null;
}
const { toggleChat } = sidebarContext;
const { toggleChat, isChatOpen } = sidebarContext;
return (
<button
className={cn(
'flex items-center justify-center rounded-md w-8 h-8 text-xs transition-all duration-500 ease-out relative overflow-hidden',
'text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg'
'flex items-center gap-2 rounded-md px-2 py-1 text-xs transition-all duration-500 ease-out relative overflow-hidden',
isChatOpen
? 'text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg'
: 'text-white chat-gradient-active hover:scale-105 hover:brightness-110 hover:shadow-lg'
)}
onClick={toggleChat}
title="AI Chat"
>
<Sparkles className="h-4 w-4 relative z-10" />
<Sparkles className="h-3 w-3 relative z-10" />
<span className="font-medium relative z-10">AI Chat</span>
</button>
);
}
@ -312,7 +315,7 @@ export function SharedHeader({
</div>
{/* Right side - Mobile Menu and Search */}
<div className="flex items-center gap-4 relative z-10">
<div className="flex items-center gap-3 relative z-10">
{/* Search Bar - Responsive sizing */}
{showSearch && (
<>
@ -344,7 +347,7 @@ export function SharedHeader({
</div>
{/* User Button */}
<div className="hidden md:block">
<div className="hidden md:block ml-2">
<UserButton />
</div>