Skip to content

Commit 2dff4f6

Browse files
authored
feat: support adding custom links on the nav header (#1836)
* feat: support adding custom links on the nav header * include condition to use apiClient.buildEndpoint * adjust size of buttons
1 parent e08f7cb commit 2dff4f6

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

backend/chainlit/config.py

+15
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@
143143
# Be careful: If this is a relative path, it should not start with a slash.
144144
# custom_build = "./public/build"
145145
146+
# Specify optional one or more custom links in the header.
147+
# [[UI.header_links]]
148+
# name = "Issues"
149+
# icon_url = "https://avatars.githubusercontent.com/u/128686189?s=200&v=4"
150+
# url = "https://github.com/Chainlit/chainlit/issues"
151+
146152
[meta]
147153
generated_by = "{__version__}"
148154
"""
@@ -214,6 +220,13 @@ class FeaturesSettings(DataClassJsonMixin):
214220
edit_message: bool = True
215221

216222

223+
@dataclass
224+
class HeaderLink(DataClassJsonMixin):
225+
name: str
226+
icon_url: str
227+
url: str
228+
229+
217230
@dataclass()
218231
class UISettings(DataClassJsonMixin):
219232
name: str
@@ -230,6 +243,8 @@ class UISettings(DataClassJsonMixin):
230243
custom_meta_image_url: Optional[str] = None
231244
# Optional custom build directory for the frontend
232245
custom_build: Optional[str] = None
246+
# Optional header links
247+
header_links: Optional[List[HeaderLink]] = None
233248

234249

235250
@dataclass()
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useContext } from 'react';
2+
3+
import { ChainlitContext } from '@chainlit/react-client';
4+
5+
import { Button } from '@/components/ui/button';
6+
import {
7+
Tooltip,
8+
TooltipContent,
9+
TooltipProvider,
10+
TooltipTrigger
11+
} from '@/components/ui/tooltip';
12+
13+
export interface ButtonLinkProps {
14+
name?: string;
15+
iconUrl?: string;
16+
url: string;
17+
}
18+
19+
export default function ButtonLink({ name, iconUrl, url }: ButtonLinkProps) {
20+
const apiClient = useContext(ChainlitContext);
21+
return (
22+
<TooltipProvider>
23+
<Tooltip>
24+
<TooltipTrigger asChild>
25+
<Button
26+
variant="ghost"
27+
size="icon"
28+
className="text-muted-foreground hover:text-muted-foreground"
29+
>
30+
<a href={url} target="_blank">
31+
<img
32+
src={
33+
iconUrl?.startsWith('/public')
34+
? apiClient.buildEndpoint(iconUrl)
35+
: iconUrl
36+
}
37+
className={'h-6 w-6'}
38+
alt={name}
39+
/>
40+
</a>
41+
</Button>
42+
</TooltipTrigger>
43+
<TooltipContent>{name}</TooltipContent>
44+
</Tooltip>
45+
</TooltipProvider>
46+
);
47+
}

frontend/src/components/header/index.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom';
44
import { useAudio, useAuth, useConfig } from '@chainlit/react-client';
55

66
import AudioPresence from '@/components/AudioPresence';
7+
import ButtonLink from '@/components/ButtonLink';
78
import { useSidebar } from '@/components/ui/sidebar';
89

910
import ApiKeys from './ApiKeys';
@@ -25,6 +26,8 @@ const Header = memo(() => {
2526

2627
const historyEnabled = data?.requireLogin && config?.dataPersistence;
2728

29+
const links = config?.ui?.header_links || [];
30+
2831
return (
2932
<div
3033
className="p-3 flex h-[60px] items-center justify-between gap-2 relative"
@@ -59,6 +62,9 @@ const Header = memo(() => {
5962
<div className="flex items-center gap-1">
6063
<ReadmeButton />
6164
<ApiKeys />
65+
{links && (
66+
links.map(link => <ButtonLink name={link.name} iconUrl={link.icon_url} url={link.url}/>)
67+
)}
6268
<ThemeToggle />
6369
<UserNav />
6470
</div>

libs/react-client/src/types/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export interface IChainlitConfig {
3939
custom_js?: string;
4040
custom_font?: string;
4141
custom_meta_image_url?: string;
42+
header_links?: { name: string; icon_url: string, url: string }[];
4243
};
4344
features: {
4445
spontaneous_file_upload?: {

0 commit comments

Comments
 (0)