Skip to content

Commit 6ca8fce

Browse files
feat(ChatContainer): add floating header mode and prompt input padding vars
1 parent 3568a70 commit 6ca8fce

11 files changed

Lines changed: 66 additions & 21 deletions

File tree

docs/THEMING.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ In mobile mode the history is a `Sheet`; these tokens shape it, `env(safe-area-i
106106

107107
### Prompt Input
108108

109-
| Variable | Default | Description |
110-
| ----------------------------------------- | ------- | ------------------------------ |
111-
| `--g-aikit-prompt-input-panel-max-height` | `500px` | Max height of expandable panel |
109+
| Variable | Default | Description |
110+
| ----------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------ |
111+
| `--g-aikit-prompt-input-panel-max-height` | `500px` | Max height of expandable panel |
112+
| `--g-aikit-prompt-input-simple-padding` | `var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-3)` | Padding of the `simple` view |
113+
| `--g-aikit-prompt-input-full-padding` | `var(--g-spacing-2)` | Padding of the `full` view |
112114

113115
### Empty Container
114116

llms-full.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -951,9 +951,11 @@ In mobile mode the history is a `Sheet`; these tokens shape it, `env(safe-area-i
951951

952952
### Prompt Input
953953

954-
| Variable | Default | Description |
955-
| ----------------------------------------- | ------- | ------------------------------ |
956-
| `--g-aikit-prompt-input-panel-max-height` | `500px` | Max height of expandable panel |
954+
| Variable | Default | Description |
955+
| ----------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------ |
956+
| `--g-aikit-prompt-input-panel-max-height` | `500px` | Max height of expandable panel |
957+
| `--g-aikit-prompt-input-simple-padding` | `var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-3)` | Padding of the `simple` view |
958+
| `--g-aikit-prompt-input-full-padding` | `var(--g-spacing-2)` | Padding of the `full` view |
957959

958960
### Empty Container
959961

src/components/organisms/PromptInput/PromptInput.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ $block: '.#{variables.$ns}prompt-input';
1111
&_view_simple {
1212
display: flex;
1313
flex-direction: column;
14-
padding: var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-3);
14+
padding: var(--g-aikit-prompt-input-simple-padding);
1515
}
1616

1717
&_view_full {
1818
display: flex;
19-
padding: var(--g-spacing-2);
19+
padding: var(--g-aikit-prompt-input-full-padding);
2020
flex-direction: column;
2121
align-items: flex-start;
2222
gap: var(--g-spacing-2);

src/components/organisms/PromptInput/README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,18 @@ All state management is handled internally by the `usePromptInput` hook.
245245

246246
The component uses CSS variables for theming:
247247

248-
| Variable | Description | Default Value |
249-
| ----------------------------------------- | ----------------------------------------- | ------------- |
250-
| `--g-color-line-generic` | Border color around the component | - |
251-
| `--g-color-base-float` | Background color of the component | - |
252-
| `--g-color-base-simple-hover-solid` | Background color for panels | - |
253-
| `--g-border-radius-xl` | Border radius for component & panels | - |
254-
| `--g-spacing-1` | Small spacing (8px) | - |
255-
| `--g-spacing-2` | Medium spacing (12px) | - |
256-
| `--g-spacing-3` | Large spacing (16px) | - |
257-
| `--g-aikit-prompt-input-panel-max-height` | Max height for open panel (for animation) | `500px` |
248+
| Variable | Description | Default Value |
249+
| ----------------------------------------- | ----------------------------------------- | ------------------ |
250+
| `--g-color-line-generic` | Border color around the component | - |
251+
| `--g-color-base-float` | Background color of the component | - |
252+
| `--g-color-base-simple-hover-solid` | Background color for panels | - |
253+
| `--g-border-radius-xl` | Border radius for component & panels | - |
254+
| `--g-spacing-1` | Small spacing (8px) | - |
255+
| `--g-spacing-2` | Medium spacing (12px) | - |
256+
| `--g-spacing-3` | Large spacing (16px) | - |
257+
| `--g-aikit-prompt-input-panel-max-height` | Max height for open panel (for animation) | `500px` |
258+
| `--g-aikit-prompt-input-simple-padding` | Padding of the `simple` view | `4px 4px 4px 12px` |
259+
| `--g-aikit-prompt-input-full-padding` | Padding of the `full` view | `8px` |
258260

259261
```css
260262
/* Example: Custom theme */

src/components/pages/ChatContainer/ChatContainer.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@
7777
padding: var(--g-aikit-chat-container-mobile-header-padding);
7878
}
7979

80+
&_floating-header {
81+
position: relative;
82+
}
83+
84+
// The content keeps the full height and scrolls under the header; how far it is offset
85+
// depends on the layout, so it is left to the consumer.
86+
&_floating-header &__header {
87+
position: absolute;
88+
z-index: 2;
89+
inset: 0 0 auto;
90+
}
91+
8092
&__content {
8193
min-height: 0; // Important for proper overflow behavior in child elements
8294
display: flex;

src/components/pages/ChatContainer/ChatContainer.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ export function ChatContainer(props: ChatContainerProps) {
211211
hideTitleOnEmptyChat = false,
212212
isMobile: isMobileProp,
213213
adjustToKeyboard = true,
214+
floatingHeader = false,
214215
className,
215216
headerClassName,
216217
contentClassName,
@@ -644,7 +645,14 @@ export function ChatContainer(props: ChatContainerProps) {
644645
<MobileProvider mobile={isMobile}>
645646
<div
646647
ref={rootRef}
647-
className={b({mobile: isMobile, 'keyboard-open': isKeyboardOpen}, className)}
648+
className={b(
649+
{
650+
mobile: isMobile,
651+
'keyboard-open': isKeyboardOpen,
652+
'floating-header': floatingHeader,
653+
},
654+
className,
655+
)}
648656
style={maxHeight === undefined ? undefined : {maxHeight}}
649657
data-qa={resolveChatContainerRootQa(qaMap)}
650658
>

src/components/pages/ChatContainer/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ Use the `texts` prop with type `ChatContainerTexts` for a **flat** API over user
433433
| `hideTitleOnEmptyChat` | `boolean` | - | `false` | Hide header title and preview when chat is empty |
434434
| `isMobile` | `boolean` | - | - | Mobile mode for the chat and all inner components; falls back to `useMobile()` from `@gravity-ui/uikit` `MobileProvider` |
435435
| `adjustToKeyboard` | `boolean` | - | `true` | In mobile mode, shrink the container to the visible viewport while the on-screen keyboard is open |
436+
| `floatingHeader` | `boolean` | - | `false` | Render the header above the content instead of stacking it, so the content scrolls underneath |
436437
| `className` | `string` | - | - | Additional CSS class |
437438
| `headerClassName` | `string` | - | - | Additional CSS class for header section |
438439
| `contentClassName` | `string` | - | - | Additional CSS class for content section |

src/components/pages/ChatContainer/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ export interface ChatContainerProps {
225225
* @default true
226226
*/
227227
adjustToKeyboard?: boolean;
228+
/**
229+
* Renders the header above the content instead of stacking it on top: the message list and
230+
* the welcome screen scroll underneath. Pair it with a transparent
231+
* `--g-aikit-chat-container-header-background` and offset the content by
232+
* `--g-aikit-chat-container-header-height` yourself, since the offset depends on the layout.
233+
*/
234+
floatingHeader?: boolean;
228235

229236
// States
230237
/** Chat status: submitted, streaming, ready, error */

src/components/templates/History/ChatItem.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React, {useEffect, useRef, useState} from 'react';
33
import {TrashBin} from '@gravity-ui/icons';
44
import {Icon, InputControlSize, Text, Tooltip, useMobile} from '@gravity-ui/uikit';
55

6-
import {getControlIconSize, useMobileControlSize} from '../../../hooks/useMobileControlSize';
6+
import {getControlIconSize, resolveMobileControlSize} from '../../../hooks/useMobileControlSize';
77
import {ChatType} from '../../../types';
88
import {block} from '../../../utils/cn';
99
import {ActionButton} from '../../atoms/ActionButton';
@@ -36,7 +36,12 @@ export function ChatItem({chat, showActions, isActive, onDeleteClick, size}: Cha
3636
const labelRef = useRef<HTMLDivElement>(null);
3737
const chatLabel = chat.lastMessage || chat.name;
3838
const isMobile = useMobile();
39-
const deleteButtonSize = useMobileControlSize(size, 's', 'xl');
39+
const deleteButtonSize = resolveMobileControlSize({
40+
size,
41+
desktopDefault: 's',
42+
mobileDefault: 'xl',
43+
isMobile,
44+
});
4045
const deleteIconSize = getControlIconSize(deleteButtonSize);
4146

4247
useEffect(() => {

src/themes/common.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666

6767
/* === Prompt Input === */
6868
--g-aikit-prompt-input-panel-max-height: 500px;
69+
--g-aikit-prompt-input-simple-padding: var(--g-spacing-1) var(--g-spacing-1) var(--g-spacing-1)
70+
var(--g-spacing-3);
71+
--g-aikit-prompt-input-full-padding: var(--g-spacing-2);
6972

7073
/* === Empty Container === */
7174
--g-aikit-empty-container-background: var(--g-color-base-background);

0 commit comments

Comments
 (0)