xterm.js icon indicating copy to clipboard operation
xterm.js copied to clipboard

xterm/addon-fit: wtf why it goes width=1?

Open steve02081504 opened this issue 10 months ago • 2 comments

when I resize an terminal that using xterm/addon-fit over and over again it becomes uh.

Image

Details

  • Browser and browser version: Firefox
  • OS version: windows11
  • xterm.js version: latest

Steps to reproduce

  1. html code:
<!DOCTYPE html>
<html data-theme="dark">

<head>
	<meta charset="UTF-8">
	<meta name="darkreader-lock">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title data-i18n="terminal_assistant.title"></title>
	<link href="https://cdn.jsdelivr.net/npm/daisyui/daisyui.css" rel="stylesheet" type="text/css" />
	<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser"></script>
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm/css/xterm.min.css">
</head>

<body class="flex flex-col h-screen items-center justify-center p-4">
	<div id="terminal" class="mockup-code border"></div>

	<script type="module">
		import { Terminal } from 'https://esm.run/xterm'
		import { WebLinksAddon } from 'https://esm.run/@xterm/addon-web-links'
		import { ClipboardAddon } from 'https://esm.run/@xterm/addon-clipboard'
		import { FitAddon } from 'https://esm.run/@xterm/addon-fit'

		const terminal = new Terminal({
			linkHandler: {
				activate(event, text, range) {
					if (event.button === 2) return
					event.preventDefault()
					window.open(text, '_blank')
				}
			},
			cursorBlink: true
		})

		const fiter = new FitAddon()
		terminal.loadAddon(fiter)
		terminal.loadAddon(new WebLinksAddon())
		terminal.loadAddon(new ClipboardAddon())

		terminal.open(document.getElementById('terminal'))
		fiter.fit()
		window.addEventListener('resize', () => {
			fiter.fit()
		})
		terminal.element.addEventListener('contextmenu', async (event) => {
			event.preventDefault()
			const selectedText = terminal.getSelection()
			if (selectedText) {
				await navigator.clipboard.writeText(selectedText)
				terminal.clearSelection()
			}
			else
				terminal.paste(await navigator.clipboard.readText())
		})
	</script>
</body>

</html>

(Original code: https://github.com/steve02081504/fount/blob/master/src/public/shells/shellassist/index.html) 2. resize it over and over again.

steve02081504 avatar Mar 14 '25 16:03 steve02081504

Yeah, I ran across similar conditions using tailwind css. If it helps, I needed to add overflow to the container, i.e., relevant snippet composable code from my XtermJs component:

<div ref="monitor" class="justify-items-center m-2">
  <!-- monitor with a thin bezel -->
  <div ref="crt" class="bg-zinc-800 p-3 rounded-md w-5/6 overflow-auto resize resizer">
    <div class="m-1 min-h-full" ref="terminalContainer"></div>
  </div>
</div>

... and also force the container to fill out the height, but not necessary for width:

<div class="min-h-full" ref="terminalContainer"></div>

<script>
const terminalContainer = ref<HTMLElement | null>(null)
const term = new Terminal({ ...startup, rows:25, cols:80 })

onMounted(() => {
  if (terminalContainer.value) {
    term.open(terminalContainer.value)
    term.loadAddon(new WebglAddon())
    resize(props.session)
  }
})

theflyingape avatar Apr 05 '25 18:04 theflyingape

Full working example using Nuxt 3 with TS + Vue: page - component - composable + server socket

theflyingape avatar Apr 06 '25 11:04 theflyingape