Skip to Content
react-brackets

Titles and navigation

Round titles with dates or formats, group titles, and your own round navigation.

Round titles

Bracket.RoundTitle shows the round's name. Give it children to show anything else, like a date or the match format. Compose the rounds to reach it:

QuarterfinalsFri 12 June, best of 3

  1. Falcons2
    Cobras3
  2. Lynx4
    Orcas3
  3. Wolves1
    Bison0
  4. Herons1
    Ravens0

SemifinalsSat 13 June, best of 3

  1. Cobras
    Lynx
  2. Wolves
    Herons

FinalSun 14 June, best of 5

  1. TBD
    TBD
<Bracket.Root stage={stage}>
  <Bracket.Viewport>
    <Bracket.Rounds>
      {(column, index) => (
        <Bracket.Round>
          <Bracket.RoundTitle className="flex flex-col">
            <span>{column.round.name}</span>
            <span className="text-xs">{schedule[index]}, best of {index === 2 ? 5 : 3}</span>
          </Bracket.RoundTitle>
          <Bracket.Matches />
        </Bracket.Round>
      )}
    </Bracket.Rounds>
    <Bracket.Connectors radius={8} />
  </Bracket.Viewport>
</Bracket.Root>

column.side tells you which half of a mirrored layout the column is on, and column.current whether it's the round in focus on a phone.

To only rename rounds, there's no need to compose: pass roundName when you build the stage, as in singleElimination(teams, { roundName: (index, total) => … }).

Group titles

Bracket.GroupTitle names the group, like Losers bracket. Children replace the name:

<Bracket.GroupTitle>
  {group.name} <span className="text-muted-foreground">{group.rounds.length} rounds</span>
</Bracket.GroupTitle>

Inside the root, useBracket().group gives you the group being drawn.

Your own round navigation

On narrow containers the bracket shows one round at a time with Bracket.Pagination underneath. Replace it with anything you like: useBracket() gives you the rounds, the current page and a way to change it. Leave Bracket.Pagination out and render your own control inside the root:

Quarterfinals

Quarterfinals

  1. Falcons2
    Cobras3
  2. Lynx4
    Orcas3
  3. Wolves1
    Bison0
  4. Herons1
    Ravens0

Semifinals

  1. Cobras
    Lynx
  2. Wolves
    Herons

Final

  1. TBD
    TBD
function RoundStepper() {
  const { rounds, page, setPage } = useBracket();
  return (
    <div className="flex items-center gap-3">
      <button disabled={page === 0} onClick={() => setPage(page - 1)}>Previous</button>
      <span>{rounds[page]?.name}</span>
      <button disabled={page === rounds.length - 1} onClick={() => setPage(page + 1)}>Next</button>
    </div>
  );
}

<Bracket.Root stage={stage}>
  <RoundStepper />
  <Bracket.Viewport>
    <Bracket.Rounds />
    <Bracket.Connectors />
  </Bracket.Viewport>
</Bracket.Root>

view is 'tree' when the whole bracket fits, so a control can hide itself the way Bracket.Pagination does. Swiping and arrow keys keep working either way.

The control can also live outside the bracket, like tabs in your page header. Control the page with page and onPageChange, as in controlling the round.

Labels

Every built-in string, like TBD, Bye and the button names read by screen readers, can be changed through labels. See RTL and languages.

On this page