Early bird: 30% off Dashral ProSee pricing

Dashral

Floating ToolbarPro

A floating toolbar whose tools grow into a field inside it: Link widens the bar into a URL field while the other tools step back, and narrows back when done.

Installation

When to use

  • Over a text selection in an editor, or over a selected row: a few tools where the work is, without a menu.
  • Tools that need a word or a link: the field opens inside the toolbar, so nothing else covers the text.

When not to use

  • A toolbar that's always there at the top of an editor: a fixed bar (Button Group, Toggle Group) is steadier.
  • Many tools: past seven or so, a menu or a command palette finds them faster.

Usage

Floating Toolbar with your own data: a whole component you can paste as a page.

example.tsx
"use client"

import { FloatingToolbar } from "@/components/dashral/pro/floating-toolbar"

import { useState } from "react"
import { Bold, Italic, Link2 } from "lucide-react"

export default function SelectionTools() {
  const [bold, setBold] = useState(false)
  const [italic, setItalic] = useState(false)
  const [link, setLink] = useState<string | undefined>()
  return (
    <FloatingToolbar
      tools={[
        { id: "bold", label: "Bold", icon: <Bold />, shortcut: ["mod", "B"], active: bold, onClick: () => setBold(!bold) },
        { id: "italic", label: "Italic", icon: <Italic />, shortcut: ["mod", "I"], active: italic, onClick: () => setItalic(!italic) },
        {
          id: "link",
          label: "Link",
          icon: <Link2 />,
          active: !!link,
          group: "insert",
          field: { type: "url", placeholder: "Paste a link", value: link, onSubmit: setLink, onRemove: () => setLink(undefined) },
        },
      ]}
    />
  )
}

API reference

FloatingToolbar

A floating toolbar: tools along one pill with a gliding highlight and their names above; a tool with a field (Link, Comment) widens the bar into that field, in place, and back when it's applied or left.

PropTypeDefault
toolsToolbarTool[]

Required.

—
openboolean

Shown or not (a selection there or not); it fades and settles in place.

true
labelstring

Named for screen readers; "Formatting" by default.

"Formatting"
fieldWidthnumber

A field's width, in px (never wider than the screen).

320
onEscape() => void

Escape on the tools (not in a field): close it, put the focus back in the text.

—
classNamestring—
classNamesFloatingToolbarClassNames—

type ToolbarField

PropTypeDefault
placeholderstring—
valuestring

What it starts with (the link already there).

—
type"text" | "url"—
submitLabelstring

The button that applies it; a check by default.

—
onSubmit(value: string) => void—
onRemove() => void

Adds a remove button (unlink, delete the comment).

—

type ToolbarTool

PropTypeDefault
idstring—
labelstring—
iconReact.ReactNode—
shortcutstring[]

Shown in its name above it (["mod", "B"]). Shown only: wire the keys in your editor.

—
activeboolean

On (bold already applied): pressed, and drawn so.

—
onClick() => void—
fieldToolbarField

Or a field it grows into, inside the toolbar.

—
groupstring

Tools of the same group sit together; a line separates groups.

—
disabledboolean—

type FloatingToolbarClassNames

PropTypeDefault
rootstring—
barstring—

Keyboard

KeysAction
TabReach the toolbar (one stop)
←or→Along the tools
HomeorEndThe first or last tool
EnterorSpaceUse the tool, or open its field
EnterIn a field: apply it, back to the tools
EscIn a field: back to its tool; on the tools: onEscape (close, back to the text)

Accessibility

  • A toolbar (role toolbar, horizontal) named by label, with one tab stop and roving focus; each tool is named, a toggle reports aria-pressed, a tool with a field says it opens one.
  • A field is a group named after its tool; its input, Apply, Remove and Back to the tools are all named, and the focus returns to the tool after.
  • A tool's name and keys show above it on hover or focus; its keys are in aria-keyshortcuts.

Motion

  • It appears settling up 6px with a fade, and leaves the same way.
  • Opening a field, the tools step back (a fade, to 97%, a 2px blur) while the bar's width tweens to the field's (0.38 s) and the field slides in; closing, the reverse.
  • One highlight glides along the tools, and the name above follows it. Smooth tweens on [0.4, 0, 0.2, 1], never springs, except the small press on Apply. With reduced motion it only fades.