Skip Link
A skip link for application layouts: visually hidden until it takes keyboard focus, then it jumps to the main content element.
Preview
Press Tab: the skip link appears at the top and jumps to the content below.
<div class="flex w-full max-w-md flex-col gap-4">
<x-ui.skip-link target="skip-link-demo-content" />
<p class="text-sm text-muted-foreground">{{ __('Press Tab: the skip link appears at the top and jumps to the content below.') }}</p>
<div id="skip-link-demo-content" tabindex="-1" class="rounded-md border border-border p-4 text-sm focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring">
{{ __('Main content') }}
</div>
</div>
Installation
php artisan ui:add skip-link
Registry contract
php artisan ui:add skip-link
writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.
-
resources/views/components/ui/skip-link.blade.php
- Registry dependencies
- None — installs on its own.
- Packages
-
composer: jml/brok:^0.2
Use with AI
A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.
# Brok UI: Skip Link (`skip-link`)
A skip link for application layouts: visually hidden until it takes keyboard focus, then it jumps to the main content element.
Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.
## Install
```bash
php artisan ui:add skip-link
```
## Usage
```blade
<div class="flex w-full max-w-md flex-col gap-4">
<x-ui.skip-link target="skip-link-demo-content" />
<p class="text-sm text-muted-foreground">{{ __('Press Tab: the skip link appears at the top and jumps to the content below.') }}</p>
<div id="skip-link-demo-content" tabindex="-1" class="rounded-md border border-border p-4 text-sm focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring">
{{ __('Main content') }}
</div>
</div>
```
## Props
- `target` (string, default `main-content`) — Id of the main content element, with or without the leading #. Give that element tabindex="-1".
- `label` (string|null, default `null`) — Link text; null uses the translated "Skip to content". The default slot wins over it.
## Use when
- Use to orient users and help them move across pages, sections, or commands.
- Placing the first focusable element of an application or site layout, so keyboard users can jump past the navigation to the main content (WCAG 2.4.1).
## Avoid when
- Do not hide primary wayfinding in novelty interactions or deep nested structures if straightforward navigation would be clearer.
- Linking to a section inside the content; use an ordinary link or table-of-contents.
## Anti-patterns
- Hiding primary wayfinding in novelty interactions
## Rules
- Use the `<brok:skip-link>` tag (or `<x-ui.skip-link>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.
## Links
- Docs: https://brokui.dev/docs/components/skip-link
- Registry JSON (files, props, contract): https://brokui.dev/r/open/skip-link.json
Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.
Examples
Long Content
<div class="flex w-full max-w-xs flex-col gap-4">
<x-ui.skip-link target="skip-link-long-content" :label="__('Skip the navigation and go straight to the list of captured items')" />
<div id="skip-link-long-content" tabindex="-1" class="rounded-md border border-border p-4 text-sm">{{ __('Main content') }}</div>
</div>
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| target | string | main-content | Id of the main content element, with or without the leading #. Give that element tabindex="-1". |
| label | string | null | null | Link text; null uses the translated "Skip to content". The default slot wins over it. |
Slots
default— Custom link text; wins over label.
Data slots
Stable hooks for CSS overrides and browser tests.
Behavior
- Visually hidden (sr-only) until it has focus; then it shows at the start of the top edge above every layer, including sticky headers and overlays.
- Pure markup: no JavaScript, no inline style or script, so it works under a strict Content-Security-Policy.
- Declares registry capability flags: a11y, authoredStateFixtures, responsive, rtl, darkMode, localized.
Guidance
Orient users and move between destinations.
Use when
- Use to orient users and help them move across pages, sections, or commands.
- Placing the first focusable element of an application or site layout, so keyboard users can jump past the navigation to the main content (WCAG 2.4.1).
Avoid when
- Do not hide primary wayfinding in novelty interactions or deep nested structures if straightforward navigation would be clearer.
- Linking to a section inside the content; use an ordinary link or table-of-contents.
Use instead
- Visible links and local navigation
Anti-patterns
- Hiding primary wayfinding in novelty interactions
- Anatomy
- Theming hooks
Accessibility
- Keyboard
- native
- Focus
native
- Render it as the first focusable element inside <body>, before the navigation.
- The target needs tabindex="-1" (for example <main id="main-content" tabindex="-1">) so focus, not only the scroll position, moves to the content.
- Semantic HTML and a stable
data-slotattribute for styling and scripting hooks. - Focus-visible rings use the
ringtoken, so keyboard focus is always visible. - Disabled and invalid states are conveyed to assistive tech, not by color alone.
- Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
- Labels go through
__()and layout uses logical properties (ms-*,text-start), so it mirrors underdir="rtl"— flip the preview to RTL to confirm. - Dark mode uses the same semantic tokens under the
darkclass; high contrast follows forced-color system tokens.
Livewire
Livewire can update this component through forwarded wire:* attributes.
Source
The exact, editable file ui:add writes
into your app. Previews render this same code; there are no preview-only components.
@props([
// Id of the main content element, without the leading #. Give that
// element tabindex="-1" so focus moves into it in every browser.
'target' => 'main-content',
// Link text. Null uses the translated "Skip to content".
'label' => null,
])
@php
// A skip link: the first focusable element of an application layout. It
// stays visually hidden until it takes keyboard focus, then shows above
// every layer (the tooltip tier, so a sticky header or an open overlay
// cannot cover it) at the start edge of the viewport.
$target = ltrim((string) $target, '#');
$target = $target !== '' ? $target : 'main-content';
@endphp
<a
href="#{{ $target }}"
data-slot="skip-link"
{{ $attributes->merge(['class' => 'sr-only focus:not-sr-only focus:fixed focus:start-4 focus:top-4 focus:z-tooltip focus:rounded-md focus:bg-primary focus:px-4 focus:py-2 focus:text-sm focus:font-medium focus:text-primary-foreground focus:shadow-lg focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring focus-visible:ring-offset-[length:var(--ring-offset-width)] focus-visible:ring-offset-background']) }}
>{{ $slot->isEmpty() ? ($label ?? __('Skip to content')) : $slot }}</a>
Ownership & lifecycle
Owner, release state, review evidence and adoption for this item.
- Owner
- Platform UI (@JoshJML)
- Current version
-
1.0.0 - Status
- Stable
- License
-
open - Accessibility reviewed
- No review date recorded
- Last breaking change
- No date recorded
- Deprecation
- Not deprecated
- Contract
-
v6 - Foundation
-
≥ 1.0.0