Repository: Chainlit/chainlit (language: python)

Issue:
Chat Profile Descriptions Cannot be Interacted With
**Describe the bug**
When you hover over a chat profile, Chainlit will display a description written by the developer in the `markdown_description` parameter of `cl.ChatProfile`. If users move their mouse over to the actual description popover, to either scroll (for long descriptions) or to click on links inside of the description (for documentation, model card, etc.) the description goes away. This prevents the inclusion of links or long descriptions as users can't interact with or scroll inside of the description popover.

**To Reproduce**
1. Follow the **Simple example** in the [Chainlit docs](https://docs.chainlit.io/api-reference/chat-profiles#usage).
2. Put a long description or clickable link in `markdown_description` parameter.
3. Try to scroll or click the link in the chat profile description.

**Example code**
```python
import chainlit as cl


@cl.set_chat_profiles
async def chat_profile():
    return [
        cl.ChatProfile(
            name="GPT-3.5",
            markdown_description="Click [this](https://openai.com/chatgpt/) for more info on ChatGPT!",
            icon="https://picsum.photos/200",
        ),
        cl.ChatProfile(
            name="GPT-4",
            markdown_description="Click [this](https://openai.com/chatgpt/) for more info on ChatGPT!",
            icon="https://picsum.photos/250",
        ),
    ]

@cl.on_chat_start
async def on_chat_start():
    chat_profile = cl.user_session.get("chat_profile")
    await cl.Message(
        content=f"starting chat using the {chat_profile} chat profile"
    ).send()

```

**Expected behavior**
It would be great to give users the ability to click links in the description to get more info about the specific model they are interacting with, such as provider documentation or usage explanation, etc.

**Desktop (please complete the following information):**

- OS: Windows 10
- Browser: Edge
- Version: 127.0.2651.86 (Official build) (64-bit)

**Additional Context**
I'm guessing the issue has to do with these lines in the [chatProfiles.tsx](https://github.com/Chainlit/chainlit/blob/9d6821558bdd57e1e88180f1b440699605974174/frontend/src/components/molecules/chatProfiles.tsx#L126-L149) file not accounting for the mouse hovering over the description popover, but I'm not very familiar with frontend development so I could be very wrong.

Chat Profile Descriptions Cannot be Interacted With
**Describe the bug**
When you hover over a chat profile, Chainlit will display a description written by the developer in the `markdown_description` parameter of `cl.ChatProfile`. If users move their mouse over to the actual description popover, to either scroll (for long descriptions) or to click on links inside of the description (for documentation, model card, etc.) the description goes away. This prevents the inclusion of links or long descriptions as users can't interact with or scroll inside of the description popover.

**To Reproduce**
1. Follow the **Simple example** in the [Chainlit docs](https://docs.chainlit.io/api-reference/chat-profiles#usage).
2. Put a long description or clickable link in `markdown_description` parameter.
3. Try to scroll or click the link in the chat profile description.

**Example code**
```python
import chainlit as cl


@cl.set_chat_profiles
async def chat_profile():
    return [
        cl.ChatProfile(
            name="GPT-3.5",
            markdown_description="Click [this](https://openai.com/chatgpt/) for more info on ChatGPT!",
            icon="https://picsum.photos/200",
        ),
        cl.ChatProfile(
            name="GPT-4",
            markdown_description="Click [this](https://openai.com/chatgpt/) for more info on ChatGPT!",
            icon="https://picsum.photos/250",
        ),
    ]

@cl.on_chat_start
async def on_chat_start():
    chat_profile = cl.user_session.get("chat_profile")
    await cl.Message(
        content=f"starting chat using the {chat_profile} chat profile"
    ).send()

```

**Expected behavior**
It would be great to give users the ability to click links in the description to get more info about the specific model they are interacting with, such as provider documentation or usage explanation, etc.

**Desktop (please complete the following information):**

- OS: Windows 10
- Browser: Edge
- Version: 127.0.2651.86 (Official build) (64-bit)

**Additional Context**
I'm guessing the issue has to do with these lines in the [chatProfiles.tsx](https://github.com/Chainlit/chainlit/blob/9d6821558bdd57e1e88180f1b440699605974174/frontend/src/components/molecules/chatProfiles.tsx#L126-L149) file not accounting for the mouse hovering over the description popover, but I'm not very familiar with frontend development so I could be very wrong.



Discussion / hints:

Fix patch:
diff --git a/frontend/src/components/molecules/chatProfiles.tsx b/frontend/src/components/molecules/chatProfiles.tsx
index 06f4f30029..08f2df111c 100644
--- a/frontend/src/components/molecules/chatProfiles.tsx
+++ b/frontend/src/components/molecules/chatProfiles.tsx
@@ -27,6 +27,7 @@ export default function ChatProfiles() {
   const { clear } = useChatInteract();
   const [newChatProfile, setNewChatProfile] = useState<string | null>(null);
   const [openDialog, setOpenDialog] = useState(false);
+  const [popoverOpen, setPopoverOpen] = useState(false);
   const navigate = useNavigate();
 
   const handleClose = () => {
@@ -58,8 +59,6 @@ export default function ChatProfiles() {
   const allowHtml = config?.features?.unsafe_allow_html;
   const latex = config?.features?.latex;
 
-  const popoverOpen = Boolean(anchorEl);
-
   const items = config.chatProfiles.map((item) => {
     const icon = item.icon?.includes('/public')
       ? apiClient.buildEndpoint(item.icon)
@@ -94,7 +93,8 @@ export default function ChatProfiles() {
               theme.palette.mode === 'light'
                 ? '0px 2px 4px 0px #0000000D'
                 : '0px 10px 10px 0px #0000000D',
-            ml: 2
+            ml: 2,
+            pointerEvents: 'auto' // Allow mouse interaction with the chat profile description
           }
         }}
         sx={{
@@ -110,6 +110,11 @@ export default function ChatProfiles() {
           horizontal: 'left'
         }}
         disableRestoreFocus
+        onMouseEnter={() => setPopoverOpen(true)}
+        onMouseLeave={() => {
+          setPopoverOpen(false);
+          setAnchorEl(null);
+        }}
       >
         <Box
           p={2}
@@ -134,10 +139,17 @@ export default function ChatProfiles() {
           if (!item) return;
           setChatProfileDescription(item.markdown_description);
           setAnchorEl(event.currentTarget);
+          setPopoverOpen(true);
         }}
-        onItemMouseLeave={() => setAnchorEl(null)}
+        onItemMouseLeave={() => setPopoverOpen(false)}
         onChange={(e) => {
           const newValue = e.target.value;
+
+          // Close the chat profile description when any selection is made
+          setPopoverOpen(false);
+          setAnchorEl(null);
+
+          // Handle user selection
           setNewChatProfile(newValue);
           if (firstInteraction) {
             setOpenDialog(true);
@@ -145,7 +157,10 @@ export default function ChatProfiles() {
             handleConfirm(newValue);
           }
         }}
-        onClose={() => setAnchorEl(null)}
+        onClose={() => {
+          setPopoverOpen(false);
+          setAnchorEl(null);
+        }}
       />
       <NewChatDialog
         open={openDialog}


Test patch:
diff --git a/cypress/e2e/chat_profiles/main.py b/cypress/e2e/chat_profiles/main.py
index 04446a42c0..bc38e29c86 100644
--- a/cypress/e2e/chat_profiles/main.py
+++ b/cypress/e2e/chat_profiles/main.py
@@ -30,7 +30,7 @@ async def chat_profile(current_user: cl.User):
         ),
         cl.ChatProfile(
             name="GPT-4",
-            markdown_description="The underlying LLM model is **GPT-4**, a *1.5T parameter model* trained on 3.5TB of text data.",
+            markdown_description="The underlying LLM model is **GPT-4**, a *1.5T parameter model* trained on 3.5TB of text data. [Learn more](https://example.com/gpt4)",
             icon="https://picsum.photos/250",
             starters=starters,
         ),
diff --git a/cypress/e2e/chat_profiles/spec.cy.ts b/cypress/e2e/chat_profiles/spec.cy.ts
index f80cb5f0da..0558691fe9 100644
--- a/cypress/e2e/chat_profiles/spec.cy.ts
+++ b/cypress/e2e/chat_profiles/spec.cy.ts
@@ -67,4 +67,60 @@ describe('Chat profiles', () => {
 
     cy.get('#starter-ask-for-help').should('exist');
   });
+
+  it('should keep chat profile description visible when hovering over a link', () => {
+    cy.visit('/');
+    cy.get("input[name='email']").type('admin');
+    cy.get("input[name='password']").type('admin');
+    cy.get("button[type='submit']").click();
+    cy.get('#chat-input').should('exist');
+
+    cy.get('#chat-profile-selector').parent().click();
+
+    // Force hover over GPT-4 profile to show description
+    cy.get('[data-test="select-item:GPT-4"]').trigger('mouseover', { force: true });
+
+    // Wait for the popover to appear and check its content
+    cy.get('#chat-profile-description').within(() => {
+      cy.contains('Learn more').should('be.visible');
+    });
+
+    // Check if the link is present in the description and has correct attributes
+    const linkSelector = '#chat-profile-description a:contains("Learn more")';
+    cy.get(linkSelector)
+      .should('have.attr', 'href', 'https://example.com/gpt4')
+      .and('have.attr', 'target', '_blank');
+
+    // Move mouse to the link
+    cy.get(linkSelector).trigger('mouseover', { force: true });
+
+    // Verify that the description is still visible after
+    cy.get('#chat-profile-description').within(() => {
+      cy.contains('Learn more').should('be.visible');
+    });
+
+    // Verify that the link is still present and clickable
+    cy.get(linkSelector)
+      .should('exist')
+      .and('be.visible')
+      .and('not.have.css', 'pointer-events', 'none')
+      .and('not.have.attr', 'disabled');
+
+    // Ensure the chat profile selector is still open
+    cy.get('[data-test="select-item:GPT-4"]').should('be.visible');
+
+    // Select GPT-4 profile
+    cy.get('[data-test="select-item:GPT-4"]').click();
+
+    // Verify the profile has been changed
+    submitMessage('hello');
+    cy.get('.step')
+      .should('have.length', 2)
+      .last()
+      .should(
+        'contain',
+        'starting chat with admin using the GPT-4 chat profile'
+      );
+
+  });
 });