loading
Note:
OverlaysContent is the switch that matters By default the browser handles the keyboard by shrinking the viewport and the page learns nothing. Turning on SetOverlaysContent(true) switches that off: the keyboard is drawn over the page, the viewport keeps its size, and the app becomes responsible for keeping its content out from under it - through OnGeometryChange here, or the keyboard-inset-* CSS environment variables.
Warning:
Chromium on touch devices Elsewhere IsSupported is false and every call is a no-op. Show also needs a user gesture and a focused element whose virtualkeyboardpolicy is manual - the attribute half of this API, set through ElementReferenceStateExtensions.SetVirtualKeyboardPolicy.

Support check

IsSupported

True when the runtime exposes navigator.virtualKeyboard. During prerender/SSR the check returns false rather than throwing.

C#
@inject Bit.Butil.VirtualKeyboard virtualKeyboard

var supported = await virtualKeyboard.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Take over the layout

GetOverlaysContent / SetOverlaysContent

Set this once at start-up, before anything can be focused - flipping it while the keyboard is up produces a visible jump. Until it is on, GetBoundingRect reports zeros, because the browser is resizing the viewport instead and has nothing to report.

C#
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender) await virtualKeyboard.SetOverlaysContent(true);
}
Live sample
overlaysContent output
Results will appear here when you interact with the samples.

Show and hide it yourself

Show / Hide

With virtualkeyboardpolicy set to manual on a contenteditable element, focusing it no longer raises the keyboard - Show and Hide do. That is what lets a custom editor decide when the keyboard is wanted.

Razor
@inject Bit.Butil.VirtualKeyboard virtualKeyboard

<div @ref="_editor" contenteditable="true">...</div>

@code {
    private ElementReference _editor;

    // Manual policy stops the browser showing and hiding the keyboard on focus, which is the whole
    // point: a custom editor that scrolls its own content wants to decide when it appears.
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) await _editor.SetVirtualKeyboardPolicy(VirtualKeyboardPolicy.Manual);
    }

    // From a click handler, with the editor focused - it is refused otherwise.
    private async Task ShowKeyboard()
    {
        await _editor.Focus();
        await virtualKeyboard.Show();
    }
}
Live sample
A contenteditable surface. Set the policy, focus it, then Show.
show/hide output
Results will appear here when you interact with the samples.

Follow the keyboard

GetBoundingRect / OnGeometryChange

Fires when the keyboard appears, disappears or resizes, plus once immediately with the current geometry. The Y coordinate is the line your content has to stay above. Dispose the returned subscription.

C#
_sub = await virtualKeyboard.OnGeometryChange(geometry =>
{
    _composerBottomPadding = geometry.Height;
    InvokeAsync(StateHasChanged);
});
Live sample
geometrychange output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes navigator.virtualKeyboard.
Show
ValueTask Show()
Asks for the on-screen keyboard. Needs a user gesture and a focused element whose virtualkeyboardpolicy is manual.
Hide
ValueTask Hide()
Dismisses the on-screen keyboard, leaving focus where it is.
GetOverlaysContent
ValueTask<bool> GetOverlaysContent()
True when the keyboard is drawn over the page rather than resizing the viewport.
SetOverlaysContent
ValueTask SetOverlaysContent(bool value)
Takes over (or hands back) responsibility for laying out around the keyboard.
GetBoundingRect
ValueTask<VirtualKeyboardGeometry> GetBoundingRect()
Where the keyboard is right now. All zeros when it isn't showing, or when OverlaysContent was never turned on.
OnGeometryChange
Task<ButilSubscription> OnGeometryChange(Action<VirtualKeyboardGeometry> handler)
Watches the keyboard. Fires on show, hide and resize, plus once immediately.
DisposeAsync
ValueTask DisposeAsync()
Detaches every listener registered through this instance and releases its interop reference.
An unhandled error has occurred. Reload 🗙