Utilities

Focus Ring

Focus rings are essential for accessibility, helping users identify which element currently has keyboard focus. Panda provides comprehensive focus ring utilities that work with both regular focus and focus-visible states.

Focus Ring Variants

The focusRing utility applies focus styles using the &:is(:focus, [data-focus]) selector and supports four variants:

// Outside focus ring (default 2px offset)
<button className={css({ focusRing: 'outside' })}>
  Click me
</button>
 
// Inside focus ring (no offset, with border)
<button className={css({ focusRing: 'inside' })}>
  Click me
</button>
 
// Mixed focus ring (semi-transparent with border)
<button className={css({ focusRing: 'mixed' })}>
  Click me
</button>
 
// No focus ring
<button className={css({ focusRing: 'none' })}>
  Click me
</button>

Focus Visible Ring

The focusVisibleRing utility only applies focus styles during keyboard navigation using the &:is(:focus-visible, [data-focus-visible]) selector:

<button className={css({ focusVisibleRing: 'outside' })}>
  Only shows focus ring on keyboard navigation
</button>

Focus Ring vs. Focus Visible Ring

The Focus Visible Ring functions similarly to the Focus Ring, but with a key difference: it only applies focus indicator styles when an element receives keyboard focus.

This ensures that the focus ring is visible only when navigating via keyboard, improving accessibility without affecting mouse interactions.

Customization

You can customize focus ring appearance with additional utilities:

<button
  className={css({
    focusRing: 'outside',
    focusRingColor: 'blue.500',
    focusRingWidth: '3px',
    focusRingStyle: 'dashed',
    focusRingOffset: '4px'
  })}
>
  Custom focus ring
</button>
PropCSS PropertyToken CategoryDescription
focusRingMultipleEnumFocus ring variant
focusVisibleRingMultipleEnumKeyboard-only focus ring
focusRingColoroutline-colorcolorsFocus ring color
focusRingWidthoutline-widthborderWidthsFocus ring thickness
focusRingStyleoutline-styleborderStylesFocus ring style
focusRingOffsetoutline-offsetspacingDistance from element

Ring Color

To change the focus ring color for a specific component, use the focusRingColor prop:

<button className={css({ focusRing: 'outside', focusRingColor: 'red.500' })}>
  Red focus ring
</button>

Global Ring Color

You can set a global focus ring color by defining the CSS custom property:

// panda.config.ts
import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  globalCss: {
    html: {
      '--global-color-focus-ring': '#3b82f6'
    }
  }
})

Ring Width

To change the focus ring width for a specific component, use the focusRingWidth prop:

<button className={css({ focusRing: 'outside', focusRingWidth: '4px' })}>
  Thick focus ring
</button>

Ring Style

To change the focus ring style for a specific component, use the focusRingStyle prop:

<button className={css({ focusRing: 'outside', focusRingStyle: 'dashed' })}>
  Dashed focus ring
</button>

This color will be used as the default for all focus rings unless overridden by the focusRingColor prop.

Examples

Basic Focus Ring

import { css } from '../styled-system/css'
 
function Button({ children }) {
  return (
    <button
      className={css({
        px: '4',
        py: '2',
        bg: 'blue.500',
        color: 'white',
        rounded: 'md',
        focusRing: 'outside'
      })}
    >
      {children}
    </button>
  )
}

Keyboard-Only Focus Ring

import { css } from '../styled-system/css'
 
function Input({ ...props }) {
  return (
    <input
      className={css({
        px: '3',
        py: '2',
        borderWidth: '1px',
        borderColor: 'gray.300',
        rounded: 'md',
        focusVisibleRing: 'outside',
        focusRingColor: 'blue.500'
      })}
      {...props}
    />
  )
}

Custom Focus Ring

import { css } from '../styled-system/css'
 
function CustomButton({ children }) {
  return (
    <button
      className={css({
        px: '6',
        py: '3',
        bg: 'purple.600',
        color: 'white',
        rounded: 'lg',
        focusRing: 'mixed',
        focusRingColor: 'purple.400',
        focusRingWidth: '3px',
        focusRingOffset: '3px'
      })}
    >
      {children}
    </button>
  )
}