fix: Keep terminal view out of the way of the keyboard on mobile views (#398)
This commit is contained in:
@@ -206,6 +206,13 @@ export const MainLayout: React.FC = () => {
|
|||||||
if (!active) {
|
if (!active) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const explicitTargetId = active.getAttribute('data-keyboard-avoid-target-id');
|
||||||
|
if (explicitTargetId) {
|
||||||
|
const explicitTarget = document.getElementById(explicitTargetId);
|
||||||
|
if (explicitTarget instanceof HTMLElement) {
|
||||||
|
return explicitTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
const markedTarget = active.closest('[data-keyboard-avoid]') as HTMLElement | null;
|
const markedTarget = active.closest('[data-keyboard-avoid]') as HTMLElement | null;
|
||||||
if (markedTarget) {
|
if (markedTarget) {
|
||||||
// data-keyboard-avoid="none" opts out of translateY avoidance entirely.
|
// data-keyboard-avoid="none" opts out of translateY avoidance entirely.
|
||||||
|
|||||||
@@ -65,11 +65,24 @@ interface TerminalViewportProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
enableTouchScroll?: boolean;
|
enableTouchScroll?: boolean;
|
||||||
autoFocus?: boolean;
|
autoFocus?: boolean;
|
||||||
|
keyboardAvoidTargetId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportProps>(
|
const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportProps>(
|
||||||
(
|
(
|
||||||
{ sessionKey, chunks, onInput, onResize, theme, fontFamily, fontSize, className, enableTouchScroll, autoFocus = true },
|
{
|
||||||
|
sessionKey,
|
||||||
|
chunks,
|
||||||
|
onInput,
|
||||||
|
onResize,
|
||||||
|
theme,
|
||||||
|
fontFamily,
|
||||||
|
fontSize,
|
||||||
|
className,
|
||||||
|
enableTouchScroll,
|
||||||
|
autoFocus = true,
|
||||||
|
keyboardAvoidTargetId,
|
||||||
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||||
@@ -1443,6 +1456,7 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
enterKeyHint="send"
|
enterKeyHint="send"
|
||||||
data-terminal-hidden-input="true"
|
data-terminal-hidden-input="true"
|
||||||
|
data-keyboard-avoid-target-id={keyboardAvoidTargetId}
|
||||||
aria-label="Terminal input"
|
aria-label="Terminal input"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{
|
style={{
|
||||||
@@ -1470,6 +1484,7 @@ const TerminalViewport = React.forwardRef<TerminalController, TerminalViewportPr
|
|||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
enterKeyHint="send"
|
enterKeyHint="send"
|
||||||
data-terminal-hidden-input="true"
|
data-terminal-hidden-input="true"
|
||||||
|
data-keyboard-avoid-target-id={keyboardAvoidTargetId}
|
||||||
aria-label="Terminal input"
|
aria-label="Terminal input"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ export const TerminalView: React.FC = () => {
|
|||||||
const [isFatalError, setIsFatalError] = React.useState(false);
|
const [isFatalError, setIsFatalError] = React.useState(false);
|
||||||
const [activeModifier, setActiveModifier] = React.useState<Modifier | null>(null);
|
const [activeModifier, setActiveModifier] = React.useState<Modifier | null>(null);
|
||||||
const [isRestarting, setIsRestarting] = React.useState(false);
|
const [isRestarting, setIsRestarting] = React.useState(false);
|
||||||
|
const keyboardAvoidTargetId = React.useId();
|
||||||
|
|
||||||
const streamCleanupRef = React.useRef<(() => void) | null>(null);
|
const streamCleanupRef = React.useRef<(() => void) | null>(null);
|
||||||
const activeTerminalIdRef = React.useRef<string | null>(null);
|
const activeTerminalIdRef = React.useRef<string | null>(null);
|
||||||
@@ -890,7 +891,7 @@ export const TerminalView: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-col overflow-hidden bg-[var(--surface-background)]">
|
<div className="flex h-full flex-col overflow-hidden bg-[var(--surface-background)]">
|
||||||
<div className="px-5 py-2 text-xs bg-[var(--surface-background)]">
|
<div className="sticky top-0 z-20 shrink-0 bg-[var(--surface-background)] px-5 py-2 text-xs">
|
||||||
{enableTabs && directoryTerminalState ? (
|
{enableTabs && directoryTerminalState ? (
|
||||||
<div className="mt-2 pl-1 pr-1 flex items-center gap-2">
|
<div className="mt-2 pl-1 pr-1 flex items-center gap-2">
|
||||||
<div className="min-w-0 flex-1 overflow-x-auto pb-1">
|
<div className="min-w-0 flex-1 overflow-x-auto pb-1">
|
||||||
@@ -962,6 +963,7 @@ export const TerminalView: React.FC = () => {
|
|||||||
<div
|
<div
|
||||||
className="relative flex-1 overflow-hidden"
|
className="relative flex-1 overflow-hidden"
|
||||||
style={{ backgroundColor: xtermTheme.background }}
|
style={{ backgroundColor: xtermTheme.background }}
|
||||||
|
id={keyboardAvoidTargetId}
|
||||||
data-keyboard-avoid="true"
|
data-keyboard-avoid="true"
|
||||||
>
|
>
|
||||||
<div className="h-full w-full box-border pl-7 pr-5 pt-3 pb-4">
|
<div className="h-full w-full box-border pl-7 pr-5 pt-3 pb-4">
|
||||||
@@ -981,6 +983,7 @@ export const TerminalView: React.FC = () => {
|
|||||||
fontSize={terminalFontSize}
|
fontSize={terminalFontSize}
|
||||||
enableTouchScroll={hasTouchInput}
|
enableTouchScroll={hasTouchInput}
|
||||||
autoFocus={isTerminalVisible}
|
autoFocus={isTerminalVisible}
|
||||||
|
keyboardAvoidTargetId={keyboardAvoidTargetId}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ScrollableOverlay outerClassName="h-full" className="h-full w-full" disableHorizontal>
|
<ScrollableOverlay outerClassName="h-full" className="h-full w-full" disableHorizontal>
|
||||||
@@ -998,6 +1001,7 @@ export const TerminalView: React.FC = () => {
|
|||||||
fontSize={terminalFontSize}
|
fontSize={terminalFontSize}
|
||||||
enableTouchScroll={hasTouchInput}
|
enableTouchScroll={hasTouchInput}
|
||||||
autoFocus={isTerminalVisible}
|
autoFocus={isTerminalVisible}
|
||||||
|
keyboardAvoidTargetId={keyboardAvoidTargetId}
|
||||||
/>
|
/>
|
||||||
</ScrollableOverlay>
|
</ScrollableOverlay>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user