Fit addon does not fit exactly to parent element dimensions #5299
Replies: 2 comments 1 reply
-
Yes thats as designed - the fix addon operates under the assumption, that you control the font size yourself and would only try to fill a given container to fully hold a certain grid size w'o partial row/column drawing. If you want a more sophisticated solution trying to change the font size to perfectly match the container size - well thats not possible with the fit addon currently, so yeah you'd have to implement that logic yourself. But note that this is almost impossible to get done right, as a certain fontsize always defines both dimensions, so you might be able to perfectly fit things in one dimension only (preferably in width, as you can tweak line height by Plz see the fit addon impl here for how to get the exact metrics for a given font size: xterm.js/addons/addon-fit/src/FitAddon.ts Line 62 in d81b25c @Tyriar Should we expose the IRenderDimensions on the public API? |
Beta Was this translation helpful? Give feedback.
-
Btw in case anyone stumbles here in the future, there was some nuance around correcting the initial terminal height, so I packaged everything into a small react hook: function useAutoFitAddon(initialHeight = 320, padding = 20) {
const [terminalRowHeight, setTerminalRowHeight] = useState(0);
const [terminalHeight, setTerminalHeightInternal] = useState(0);
const setTerminalHeight = useCallback(
(height) => {
if (!terminalRowHeight) return;
setTerminalHeightInternal(
Math.floor(
(height + terminalRowHeight / 2 - 2 * padding) / terminalRowHeight
) * terminalRowHeight + 2 * padding
);
},
[terminalRowHeight, padding]
);
useEffect(() => {
if (terminalRowHeight && terminalHeight === 0) {
setTerminalHeight(initialHeight);
}
}, [terminalRowHeight, terminalHeight, initialHeight, setTerminalHeight]);
const openAutofitTerminal = useCallback((term, anchorElem) => {
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(anchorElem);
setTerminalRowHeight(
(term)._core._renderService.dimensions.css.cell.height
);
fitAddon.fit();
const observer = new ResizeObserver(() => fitAddon.fit());
observer.observe(anchorElem);
return () => observer.disconnect();
}, []);
return { terminalHeight, setTerminalHeight, openAutofitTerminal };
} Then you use it as follows: function MyTerminal() {
const [terminalElement, setTerminalElement] = useState(null);
const { terminalHeight, setTerminalHeight, openAutofitTerminal } = useAutoFitAddon();
useEffect(() => {
if (!terminalElement) return;
const term = createTerminal();
const disposeAutofit = openAutofitTerminal(term, terminalElement);
return () => {
term.dispose();
disposeAutofit();
};
}, [terminalElement, openAutofitTerminal]);
// Realistically this would be a height obtained from a mouse event after dragging for resize
const handleHeightChange = () => {
const randomHeight = Math.floor(Math.random() * (600 - 100 + 1)) + 100;
setTerminalHeight(randomHeight);
};
return (
<>
<div
ref={setTerminalElement}
style={{ height: terminalHeight }}
/>
<button onClick={handleHeightChange}>Change Height</button>
</>
);
} |
Beta Was this translation helpful? Give feedback.
-
Hi there! I'm using xterm-fit-addon to resize the terminal to the anchoring div's size. It works mostly fine, but it doesn't expand to fill the last modulus of pixels past the last row:
This is kind of expected since the terminal ideally should only be sized to an amount divisible with the number of rows, but then there's no simple way to determine what the row height is. As far as I can see, there's no API to read the font's character height (I think xterm does this internally automatically). So IMO to have the addon be realistically useful I think it should do one of two things:
Am I missing some existing API / approach to do this easier or does this seem like a reasonable request?
Here is a code sandbox containing code to reproduce.
Update: Actually the following workaround isn't too bad:
Beta Was this translation helpful? Give feedback.
All reactions