Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/lib/components/TerminalInput.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script lang="ts">
import { hasOnScreenKeyboard } from '$lib/device';

interface Props {
value: string;
onSubmit: () => void;
Expand Down Expand Up @@ -30,6 +32,7 @@
}

function handleBlur(e: FocusEvent) {
if (hasOnScreenKeyboard()) return;
const target = e.target as HTMLInputElement;
target?.focus({ preventScroll: true });
}
Expand Down Expand Up @@ -67,7 +70,7 @@
onkeydown={handleKeyDown}
onblur={handleBlur}
type="text"
class="w-full border-none bg-transparent font-mono text-gray-900 outline-none dark:text-gray-100"
class="w-full border-none bg-transparent font-mono text-base text-gray-900 outline-none md:text-sm dark:text-gray-100"
style="caret-color: transparent;"
spellcheck="false"
autocomplete="off"
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/TerminalOutput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{#each history as entry, i (i)}
{#if entry.type === 'greeting'}
<pre
class="m-0 font-mono leading-tight whitespace-pre text-blue-600 dark:text-blue-400">{entry.content}</pre>
class="m-0 max-w-full overflow-x-auto font-mono leading-tight whitespace-pre text-blue-600 dark:text-blue-400">{entry.content}</pre>
{#if entry.links && entry.links.length > 0}
<div class="mt-3 mb-5 flex flex-wrap gap-3 font-mono">
{#each entry.links as link, k (k)}
Expand Down
13 changes: 13 additions & 0 deletions src/lib/device.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Returns true on devices likely to show an on-screen keyboard:
* coarse primary pointer (touch) combined with a narrow viewport.
* This intentionally excludes large touch-enabled desktops/tablets that
* don't pop up a software keyboard on focus.
*/
export function hasOnScreenKeyboard(): boolean {
return (
typeof window !== 'undefined' &&
window.matchMedia('(pointer: coarse)').matches &&
window.matchMedia('(max-width: 1024px)').matches
);
}
17 changes: 12 additions & 5 deletions src/routes/Terminal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import TerminalOutput from '$lib/components/TerminalOutput.svelte';
import TerminalInput from '$lib/components/TerminalInput.svelte';
import { executeCommand, config } from '$lib/commands-utils';
import { hasOnScreenKeyboard } from '$lib/device';
import type { HistoryEntry, Link } from '$lib/types/terminal';

interface Props {
Expand Down Expand Up @@ -32,8 +33,10 @@
// Apply theme to document
updateTheme();

// Focus input
inputElement?.focus();
// Focus input (skip on devices with on-screen keyboards to avoid keyboard popup)
if (!hasOnScreenKeyboard()) {
inputElement?.focus();
}
});

function updateTheme() {
Expand Down Expand Up @@ -115,7 +118,9 @@
} else if (link.type === 'url') {
window.open(link.target, '_blank', 'noopener,noreferrer');
}
setTimeout(() => inputElement?.focus({ preventScroll: true }), 0);
if (!hasOnScreenKeyboard()) {
setTimeout(() => inputElement?.focus({ preventScroll: true }), 0);
}
}

function handleInput(value: string) {
Expand All @@ -127,12 +132,14 @@
}

function focusInput() {
inputElement?.focus({ preventScroll: true });
if (!hasOnScreenKeyboard()) {
inputElement?.focus({ preventScroll: true });
}
}
</script>

<div
class="flex h-screen w-screen flex-col bg-white font-mono text-sm transition-colors dark:bg-gray-900"
class="flex h-screen w-screen flex-col overflow-x-hidden bg-white font-mono text-sm transition-colors dark:bg-gray-900"
>
<TerminalHeader {darkMode} onToggleTheme={toggleTheme} />

Expand Down