Focus ring

The one cue that shows where the keyboard is. Every part draws the same ring: 2 pixels of the accent, 2 pixels outside it.

Part of a Downloads window with a list under the heading Today: a picture, a PDF with the keyboard ring around its whole row, and a text file.

Every kit part already draws the ring, so an app using them adds none. Use FocusRing yourself only in a part of your own, such as a tile or a custom control that takes the keyboard, so that it looks like the rest. Do not draw an outline of your own. Do not use the ring for selection or for the pointer: those are washes. A line of text to type in is a field, which shows its own ring whenever it has the keyboard.

Anatomy

A quiet Slab at 2.4 times its size with the keyboard ring on. Numbered callouts above name the ring and the gap between the ring and the Slab; one below names the Slab.
A Slab with the keyboard ring on, at 2.4 times its size.
  1. Ring2 pixels in the accent, round at the corner.
  2. Gap2 pixels of whatever is behind the part, so the ring never touches the part's own edge.
  3. PartWhatever has the keyboard. The ring's corner is the part's own plus 4, so it runs parallel to the part's edge.

The ring is drawn outside the part and never over its words, and it appears at once, with no motion.

The ring on five parts, numbered: an icon button, a Slab, a switch, tabs and a list row.
The same ring on five kinds of part.
  1. Icon buttonA circle.
  2. SlabA pill.
  3. SwitchAround the track.
  4. TabsAround the chosen word.
  5. List rowAround the whole row, over its wash.

Only one part has the keyboard at a time, so only one ring shows. Here five are shown together to compare them.

States

The ring is either shown or not, and the rule is the same for the whole app.

Four parts, numbered: a Slab with no ring, a Slab with the ring, a field with its ring while its text is edited, and a field in error with the ring in the risk ink.
  1. Not shownThe part has the focus because the pointer put it there, or no key has been pressed yet.
  2. ShownThe first key press turns the ring on, for every part, until the next pointer press on a part.
  3. Field in useA field shows its ring whenever it has the keyboard, key or no key, as typing needs it.
  4. Field in errorThe same ring in the risk ink, and always shown.

The switch is Kit.focusVisible: a key pressed on any kit part sets it, and a pointer press on one clears it. A pointer press on something that is not a kit part leaves it as it was. States gives the ring with the washes.

Sizes

An icon button at 5 times its size with the ring on: 36 pixels across, the ring 4 pixels outside it on each side for 44 in all.
PartValue
Ring2 pixels wide, in the accent (state.focusRing)
Gap2 pixels (state.focusGap)
Reach4 pixels past the part on every side
CornerThe part's corner plus 4

Leave room for the ring: it is drawn outside the part, so a clip (a list's, a scroll view's) that sits on the part's edge cuts it off. The cover grid keeps 6 pixels inside its clip for this.

Keys and pointer

Do thisTo
Tab or Shift TabMove the focus to the next or previous part; the ring shows on it
Any key on a partShow the ring, on the part that has the focus
Press the pointer on a partHide the ring; the focus stays where it is
First Tab in a windowShows the ring on the part it lands on, if the app has called Kit.watchKeys(window)

Accessibility

Do and don't

A Slab with the 2-pixel accent ring round it.
DoUse the kit's ring. It is the same on every part, so people learn it once.
A Slab with a thin outline in the main ink round it, 4 pixels out.
Don'tDraw an outline of your own. A different colour and weight reads as a second kind of focus.
A selected row with its ring whole inside a thin frame that leaves room around it.
DoLeave 4 pixels or more round the part, inside any clip.
A selected row in a thin frame that leaves room at its sides but none above and below: the ring shows at the ends and is cut off along the top and bottom.
Don'tClip at the part's own edge. The ring is outside the part and is cut away.

Code

import QtQuick
import Tacit.Kit

ApplicationWindow {
    id: window
    Component.onCompleted: Kit.watchKeys(window)    // the first Tab shows the ring

    Item {
        id: tile
        width: 120; height: 40
        activeFocusOnTab: true
        Keys.onPressed: Kit.focusVisible = true
        TapHandler { onTapped: Kit.focusVisible = false }
        FocusRing { shown: tile.activeFocus && Kit.focusVisible; corner: 8 }
    }
}
Property or functionWhat it does
shownWhether the ring is drawn; usually activeFocus && Kit.focusVisible
cornerThe part's own corner radius; the ring adds 4 to it (the row's, 8, by default)
Kit.focusVisibleThe app's one switch: true from a key press on a part, false from a pointer press on one
Kit.watchKeys(window)Call it once for each window: a key nothing else handled, Tab included, turns the ring on

Experimental, in Tacit.Kit 0.1.