mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-04 11:45:38 +08:00
fix(mobile): prevent bottom padding removal on input focus
This commit is contained in:
@@ -106,7 +106,7 @@ export default function AppContent() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={`flex-1 flex flex-col min-w-0 ${isMobile && !isInputFocused ? 'pb-mobile-nav' : ''}`}>
|
<div className={`flex-1 flex flex-col min-w-0 ${isMobile ? 'pb-mobile-nav' : ''}`}>
|
||||||
<MainContent
|
<MainContent
|
||||||
selectedProject={selectedProject}
|
selectedProject={selectedProject}
|
||||||
selectedSession={selectedSession}
|
selectedSession={selectedSession}
|
||||||
|
|||||||
@@ -903,8 +903,11 @@ export function useChatComposerState({
|
|||||||
[sendMessage, setClaudeStatus, setPendingPermissionRequests],
|
[sendMessage, setClaudeStatus, setPendingPermissionRequests],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [isInputFocused, setIsInputFocused] = useState(false);
|
||||||
|
|
||||||
const handleInputFocusChange = useCallback(
|
const handleInputFocusChange = useCallback(
|
||||||
(focused: boolean) => {
|
(focused: boolean) => {
|
||||||
|
setIsInputFocused(focused);
|
||||||
onInputFocusChange?.(focused);
|
onInputFocusChange?.(focused);
|
||||||
},
|
},
|
||||||
[onInputFocusChange],
|
[onInputFocusChange],
|
||||||
@@ -953,5 +956,6 @@ export function useChatComposerState({
|
|||||||
handlePermissionDecision,
|
handlePermissionDecision,
|
||||||
handleGrantToolPermission,
|
handleGrantToolPermission,
|
||||||
handleInputFocusChange,
|
handleInputFocusChange,
|
||||||
|
isInputFocused,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<details className={`relative group/details ${className}`} open={open}>
|
<details className={`relative group/details ${className}`} open={open}>
|
||||||
<summary className="flex items-center gap-1.5 text-xs cursor-pointer py-0.5 select-none">
|
<summary className="flex items-center gap-1.5 text-xs cursor-pointer py-0.5 select-none group-open/details:sticky group-open/details:top-0 group-open/details:z-10 group-open/details:bg-background group-open/details:-mx-1 group-open/details:px-1">
|
||||||
<svg
|
<svg
|
||||||
className="w-3 h-3 text-gray-400 dark:text-gray-500 transition-transform duration-150 group-open/details:rotate-90 flex-shrink-0"
|
className="w-3 h-3 text-gray-400 dark:text-gray-500 transition-transform duration-150 group-open/details:rotate-90 flex-shrink-0"
|
||||||
fill="none"
|
fill="none"
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ function ChatInterface({
|
|||||||
handlePermissionDecision,
|
handlePermissionDecision,
|
||||||
handleGrantToolPermission,
|
handleGrantToolPermission,
|
||||||
handleInputFocusChange,
|
handleInputFocusChange,
|
||||||
|
isInputFocused,
|
||||||
} = useChatComposerState({
|
} = useChatComposerState({
|
||||||
selectedProject,
|
selectedProject,
|
||||||
selectedSession,
|
selectedSession,
|
||||||
@@ -373,6 +374,7 @@ function ChatInterface({
|
|||||||
onTextareaScrollSync={syncInputOverlayScroll}
|
onTextareaScrollSync={syncInputOverlayScroll}
|
||||||
onTextareaInput={handleTextareaInput}
|
onTextareaInput={handleTextareaInput}
|
||||||
onInputFocusChange={handleInputFocusChange}
|
onInputFocusChange={handleInputFocusChange}
|
||||||
|
isInputFocused={isInputFocused}
|
||||||
placeholder={t('input.placeholder', {
|
placeholder={t('input.placeholder', {
|
||||||
provider:
|
provider:
|
||||||
provider === 'cursor'
|
provider === 'cursor'
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ interface ChatComposerProps {
|
|||||||
onTextareaScrollSync: (target: HTMLTextAreaElement) => void;
|
onTextareaScrollSync: (target: HTMLTextAreaElement) => void;
|
||||||
onTextareaInput: (event: FormEvent<HTMLTextAreaElement>) => void;
|
onTextareaInput: (event: FormEvent<HTMLTextAreaElement>) => void;
|
||||||
onInputFocusChange?: (focused: boolean) => void;
|
onInputFocusChange?: (focused: boolean) => void;
|
||||||
|
isInputFocused?: boolean;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
isTextareaExpanded: boolean;
|
isTextareaExpanded: boolean;
|
||||||
sendByCtrlEnter?: boolean;
|
sendByCtrlEnter?: boolean;
|
||||||
@@ -143,6 +144,7 @@ export default function ChatComposer({
|
|||||||
onTextareaScrollSync,
|
onTextareaScrollSync,
|
||||||
onTextareaInput,
|
onTextareaInput,
|
||||||
onInputFocusChange,
|
onInputFocusChange,
|
||||||
|
isInputFocused,
|
||||||
placeholder,
|
placeholder,
|
||||||
isTextareaExpanded,
|
isTextareaExpanded,
|
||||||
sendByCtrlEnter,
|
sendByCtrlEnter,
|
||||||
@@ -162,8 +164,13 @@ export default function ChatComposer({
|
|||||||
(r) => r.toolName === 'AskUserQuestion'
|
(r) => r.toolName === 'AskUserQuestion'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// On mobile, when input is focused, float the input box at the bottom
|
||||||
|
const mobileFloatingClass = isInputFocused
|
||||||
|
? 'max-sm:fixed max-sm:bottom-0 max-sm:left-0 max-sm:right-0 max-sm:z-50 max-sm:bg-background max-sm:shadow-[0_-4px_20px_rgba(0,0,0,0.15)]'
|
||||||
|
: '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-2 sm:p-4 md:p-4 flex-shrink-0 pb-2 sm:pb-4 md:pb-6">
|
<div className={`p-2 sm:p-4 md:p-4 flex-shrink-0 pb-2 sm:pb-4 md:pb-6 ${mobileFloatingClass}`}>
|
||||||
{!hasQuestionPanel && (
|
{!hasQuestionPanel && (
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<ClaudeStatus
|
<ClaudeStatus
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ export default function MainContentTitle({
|
|||||||
</div>
|
</div>
|
||||||
) : showChatNewSession ? (
|
) : showChatNewSession ? (
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<h2 className="text-sm font-semibold text-foreground leading-tight">{t('mainContent.newSession')}</h2>
|
<h2 className="text-base font-semibold text-foreground leading-tight">{t('mainContent.newSession')}</h2>
|
||||||
<div className="text-[11px] text-muted-foreground truncate leading-tight">{selectedProject.displayName}</div>
|
<div className="text-xs text-muted-foreground truncate leading-tight">{selectedProject.displayName}</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
|
|||||||
Reference in New Issue
Block a user