mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
Fix mobile keyboard layout and text sizing issues (#441)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
fece79055f
commit
276dad95c9
2 changed files with 69 additions and 44 deletions
|
|
@ -165,7 +165,7 @@ First-time contributors to VibeTunnel:
|
||||||
- Fixed duplicate session creation with intelligent detection (#345) (via @lukeswitz)
|
- Fixed duplicate session creation with intelligent detection (#345) (via @lukeswitz)
|
||||||
- Added keyboard navigation in session grid (arrow keys, Enter, etc.) (#322)
|
- Added keyboard navigation in session grid (arrow keys, Enter, etc.) (#322)
|
||||||
- Fixed race conditions in network access mode (#347)
|
- Fixed race conditions in network access mode (#347)
|
||||||
- Improved SSH key manager modal layout (#325) (via @taoxugit)
|
- Improved SSH key manager modal layout (#325) (via @hewigovens)
|
||||||
- Updated all dependencies to latest stable versions
|
- Updated all dependencies to latest stable versions
|
||||||
- Enhanced TypeScript configuration with better type safety
|
- Enhanced TypeScript configuration with better type safety
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ First-time contributors to VibeTunnel:
|
||||||
First-time contributors to VibeTunnel:
|
First-time contributors to VibeTunnel:
|
||||||
- [@davidgomesdev](https://github.com/davidgomesdev) - Transformed SessionListView to clean MVVM architecture for better maintainability (#217)
|
- [@davidgomesdev](https://github.com/davidgomesdev) - Transformed SessionListView to clean MVVM architecture for better maintainability (#217)
|
||||||
- [@jeffhurray](https://github.com/jeffhurray) - Consolidated z-index management to prevent UI layer conflicts (#291)
|
- [@jeffhurray](https://github.com/jeffhurray) - Consolidated z-index management to prevent UI layer conflicts (#291)
|
||||||
- [@taoxugit](https://github.com/taoxugit) - Fixed SSH key manager modal layout and improved test compatibility (#325)
|
- [@hewigovens](https://github.com/hewigovens) - Fixed SSH key manager modal layout and improved test compatibility (#325)
|
||||||
- [@tarasenko](https://github.com/tarasenko) - Added browser keyboard shortcut support with intelligent priority handling (#298)
|
- [@tarasenko](https://github.com/tarasenko) - Added browser keyboard shortcut support with intelligent priority handling (#298)
|
||||||
|
|
||||||
## [1.0.0-beta.9] - 2025-07-11
|
## [1.0.0-beta.9] - 2025-07-11
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,29 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
this.isLandscape = window.innerWidth > window.innerHeight && window.innerWidth > 600;
|
this.isLandscape = window.innerWidth > window.innerHeight && window.innerWidth > 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getButtonSizeClass(label: string): string {
|
||||||
|
if (label.length >= 4) {
|
||||||
|
// Long text: compact with max-width constraint
|
||||||
|
return this.isLandscape ? 'px-0.5 py-1 flex-1 max-w-14' : 'px-0.5 py-1.5 flex-1 max-w-16';
|
||||||
|
} else if (label.length === 3) {
|
||||||
|
// Medium text: slightly more padding, larger max-width
|
||||||
|
return this.isLandscape ? 'px-1 py-1 flex-1 max-w-16' : 'px-1 py-1.5 flex-1 max-w-18';
|
||||||
|
} else {
|
||||||
|
// Short text: can grow freely
|
||||||
|
return this.isLandscape ? 'px-1 py-1 flex-1' : 'px-1 py-1.5 flex-1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getButtonFontClass(label: string): string {
|
||||||
|
if (label.length >= 4) {
|
||||||
|
return 'quick-key-btn-xs'; // 8px
|
||||||
|
} else if (label.length === 3) {
|
||||||
|
return 'quick-key-btn-small'; // 10px
|
||||||
|
} else {
|
||||||
|
return 'quick-key-btn-medium'; // 13px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updated(changedProperties: PropertyValues) {
|
updated(changedProperties: PropertyValues) {
|
||||||
super.updated(changedProperties);
|
super.updated(changedProperties);
|
||||||
if (changedProperties.has('keyboardHeight')) {
|
if (changedProperties.has('keyboardHeight')) {
|
||||||
|
|
@ -255,17 +278,6 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
private renderStyles() {
|
private renderStyles() {
|
||||||
return html`
|
return html`
|
||||||
<style>
|
<style>
|
||||||
/* Hide scrollbar */
|
|
||||||
.scrollbar-hide {
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
scrollbar-width: none;
|
|
||||||
overflow-x: auto !important;
|
|
||||||
overflow-y: hidden;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
.scrollbar-hide::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quick keys container - positioned above keyboard */
|
/* Quick keys container - positioned above keyboard */
|
||||||
.terminal-quick-keys-container {
|
.terminal-quick-keys-container {
|
||||||
|
|
@ -280,18 +292,19 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
/* Smooth transition when keyboard appears/disappears */
|
/* Smooth transition when keyboard appears/disappears */
|
||||||
transition: bottom 0.3s ease-out;
|
transition: bottom 0.3s ease-out;
|
||||||
|
background-color: rgb(var(--color-bg-secondary));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The actual bar with buttons */
|
/* The actual bar with buttons */
|
||||||
.quick-keys-bar {
|
.quick-keys-bar {
|
||||||
background: rgb(var(--color-bg-base));
|
background: rgb(var(--color-bg-secondary));
|
||||||
border-top: 1px solid rgb(var(--color-border-base));
|
border-top: 1px solid rgb(var(--color-border-base));
|
||||||
padding: 0.5rem 0.25rem;
|
padding: 0.5rem 0.25rem;
|
||||||
/* Prevent iOS from adding its own styling */
|
/* Prevent iOS from adding its own styling */
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
/* Add shadow for visibility */
|
/* Add shadow for visibility */
|
||||||
box-shadow: 0 -2px 10px rgb(var(--color-bg-base) / 0.5);
|
box-shadow: 0 -2px 10px rgb(var(--color-bg-secondary) / 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Quick key buttons */
|
/* Quick key buttons */
|
||||||
|
|
@ -331,6 +344,35 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
padding: 0.375rem 0.5rem;
|
padding: 0.375rem 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Medium font for short character buttons */
|
||||||
|
.quick-key-btn-medium {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Small font for mobile keyboard buttons */
|
||||||
|
.quick-key-btn-small {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extra small font for long text buttons */
|
||||||
|
.quick-key-btn-xs {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Max width constraints for buttons */
|
||||||
|
.max-w-14 {
|
||||||
|
max-width: 3.5rem; /* 56px */
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-16 {
|
||||||
|
max-width: 4rem; /* 64px */
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-18 {
|
||||||
|
max-width: 4.5rem; /* 72px */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Combo key styling (like ^C, ^Z) */
|
/* Combo key styling (like ^C, ^Z) */
|
||||||
.combo-key {
|
.combo-key {
|
||||||
background-color: rgb(var(--color-bg-tertiary));
|
background-color: rgb(var(--color-bg-tertiary));
|
||||||
|
|
@ -390,27 +432,10 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Landscape mode adjustments - reduce height/padding by 10% */
|
/* Landscape mode adjustments */
|
||||||
@media (orientation: landscape) and (max-width: 926px) {
|
@media (orientation: landscape) and (max-width: 926px) {
|
||||||
.quick-keys-bar {
|
.quick-keys-bar {
|
||||||
padding: 0.45rem 0.225rem; /* 10% less than 0.5rem 0.25rem */
|
padding: 0.45rem 0.225rem;
|
||||||
}
|
|
||||||
|
|
||||||
.quick-key-btn {
|
|
||||||
padding: 0.3375rem 0.45rem; /* 10% less than py-1.5 (0.375rem) px-0.5 (0.125rem) */
|
|
||||||
}
|
|
||||||
|
|
||||||
.arrow-key {
|
|
||||||
padding: 0.3375rem 0.45rem; /* 10% less than 0.375rem 0.5rem */
|
|
||||||
}
|
|
||||||
|
|
||||||
.ctrl-shortcut-btn, .func-key-btn {
|
|
||||||
padding: 0.3375rem 0.45rem; /* 10% less than py-1.5 px-0.5 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Row 3 buttons with py-1 become 10% less */
|
|
||||||
.quick-keys-bar .flex.gap-1.justify-center.text-xs button {
|
|
||||||
padding: 0.225rem 0.45rem; /* 10% less than py-1 (0.25rem) px-0.5 */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -433,13 +458,13 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
>
|
>
|
||||||
<div class="quick-keys-bar">
|
<div class="quick-keys-bar">
|
||||||
<!-- Row 1 -->
|
<!-- Row 1 -->
|
||||||
<div class="flex gap-1 justify-center mb-1">
|
<div class="flex gap-0.5 justify-center mb-1">
|
||||||
${TERMINAL_QUICK_KEYS.filter((k) => k.row === 1).map(
|
${TERMINAL_QUICK_KEYS.filter((k) => k.row === 1).map(
|
||||||
({ key, label, modifier, arrow, toggle }) => html`
|
({ key, label, modifier, arrow, toggle }) => html`
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="quick-key-btn flex-1 min-w-0 px-0.5 ${this.isLandscape ? 'py-1' : 'py-1.5'} bg-tertiary text-primary text-xs font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${arrow ? 'arrow-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && ((key === 'CtrlExpand' && this.showCtrlKeys) || (key === 'F' && this.showFunctionKeys)) ? 'active' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${arrow ? 'arrow-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && ((key === 'CtrlExpand' && this.showCtrlKeys) || (key === 'F' && this.showFunctionKeys)) ? 'active' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
||||||
@mousedown=${(e: Event) => {
|
@mousedown=${(e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -485,13 +510,13 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
this.showCtrlKeys
|
this.showCtrlKeys
|
||||||
? html`
|
? html`
|
||||||
<!-- Ctrl shortcuts row -->
|
<!-- Ctrl shortcuts row -->
|
||||||
<div class="flex gap-1 justify-between flex-wrap mb-1">
|
<div class="flex gap-0.5 justify-between flex-wrap mb-1">
|
||||||
${CTRL_SHORTCUTS.map(
|
${CTRL_SHORTCUTS.map(
|
||||||
({ key, label, combo, special }) => html`
|
({ key, label, combo, special }) => html`
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="ctrl-shortcut-btn flex-1 min-w-0 px-0.5 ${this.isLandscape ? 'py-1' : 'py-1.5'} bg-tertiary text-primary text-xs font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''}"
|
class="ctrl-shortcut-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''}"
|
||||||
@mousedown=${(e: Event) => {
|
@mousedown=${(e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -520,13 +545,13 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
: this.showFunctionKeys
|
: this.showFunctionKeys
|
||||||
? html`
|
? html`
|
||||||
<!-- Function keys row -->
|
<!-- Function keys row -->
|
||||||
<div class="flex gap-1 justify-between mb-1">
|
<div class="flex gap-0.5 justify-between mb-1">
|
||||||
${FUNCTION_KEYS.map(
|
${FUNCTION_KEYS.map(
|
||||||
({ key, label }) => html`
|
({ key, label }) => html`
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="func-key-btn flex-1 min-w-0 px-0.5 ${this.isLandscape ? 'py-1' : 'py-1.5'} bg-tertiary text-primary text-xs font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap"
|
class="func-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap"
|
||||||
@mousedown=${(e: Event) => {
|
@mousedown=${(e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -554,13 +579,13 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<!-- Regular row 2 -->
|
<!-- Regular row 2 -->
|
||||||
<div class="flex gap-1 justify-center mb-1">
|
<div class="flex gap-0.5 justify-center mb-1">
|
||||||
${TERMINAL_QUICK_KEYS.filter((k) => k.row === 2).map(
|
${TERMINAL_QUICK_KEYS.filter((k) => k.row === 2).map(
|
||||||
({ key, label, modifier, combo, special, toggle }) => html`
|
({ key, label, modifier, combo, special, toggle }) => html`
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="quick-key-btn flex-1 min-w-0 px-0.5 ${this.isLandscape ? 'py-1' : 'py-1.5'} bg-tertiary text-primary text-xs font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && this.showFunctionKeys ? 'active' : ''}"
|
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && this.showFunctionKeys ? 'active' : ''}"
|
||||||
@mousedown=${(e: Event) => {
|
@mousedown=${(e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -593,13 +618,13 @@ export class TerminalQuickKeys extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- Row 3 - Additional special characters (always visible) -->
|
<!-- Row 3 - Additional special characters (always visible) -->
|
||||||
<div class="flex gap-1 justify-center text-xs">
|
<div class="flex gap-0.5 justify-center">
|
||||||
${TERMINAL_QUICK_KEYS.filter((k) => k.row === 3).map(
|
${TERMINAL_QUICK_KEYS.filter((k) => k.row === 3).map(
|
||||||
({ key, label, modifier, combo, special }) => html`
|
({ key, label, modifier, combo, special }) => html`
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="quick-key-btn flex-1 min-w-0 px-0.5 ${this.isLandscape ? 'py-0.5' : 'py-1'} bg-tertiary text-primary text-xs font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
||||||
@mousedown=${(e: Event) => {
|
@mousedown=${(e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue