@epixisbad/bracketeer
v0.1.1
Published
Beautiful tournament bracket Web Component
Maintainers
Readme
bracketeer
Beautiful, zero-dependency tournament bracket Web Component. Renders SVG brackets for any format.
Install
npm install bracketeerQuick Start
<bracket-view id="bracket" format="single-elim" theme="dark"></bracket-view>
<script type="module">
import 'bracketeer';
document.getElementById('bracket').matches = [
{ id: 1, round: 1, position: 0, teams: [{ name: 'Cloud9', score: 7, seed: 1, winner: true }, { name: 'FaZe', score: 3, seed: 8 }] },
{ id: 2, round: 1, position: 1, teams: [{ name: 'TSM', score: 5, seed: 4 }, { name: 'NaVi', score: 7, seed: 5, winner: true }] },
{ id: 3, round: 2, position: 0, teams: [{ name: 'Cloud9', score: 7, seed: 1, winner: true }, { name: 'NaVi', score: 5, seed: 5 }] },
];
</script>Supported Formats
| Format | Description |
|---|---|
| single-elim | Standard single elimination bracket. Losers are out. |
| double-elim | Double elimination with winners, losers, and grand finals brackets. |
| round-robin | Every team plays every other team. Grid layout. |
| swiss | Swiss-system rounds where matchups are based on current standings. |
| group-knockout | Group stage round-robin followed by a knockout bracket. |
API Reference
<bracket-view> accepts the following attributes and properties:
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
| matches | -- | Match[] | [] | Array of match objects (set via JS property) |
| format | format | BracketFormat | 'single-elim' | Tournament format |
| theme | theme | 'light' \| 'dark' | 'light' | Color theme |
| fit | fit | 'auto' \| 'fixed' | 'auto' | auto fills container; fixed uses exact width/height |
| width | width | number | 800 | SVG layout width |
| height | height | number | 400 | SVG layout height |
Data Format
interface Team {
name: string;
score?: number;
seed?: number;
logo?: string;
winner?: boolean;
}
interface Match {
id: string | number;
round: number;
position: number;
teams: [Team, Team];
bracket?: 'winners' | 'losers' | 'grand-finals'; // double-elim only
group?: string; // group-knockout only
}Theming
CSS Custom Properties
Override any of these on the <bracket-view> element or in a parent:
bracket-view {
--bracket-bg: #ffffff;
--bracket-card-bg: #f8f9fa;
--bracket-card-border: #dee2e6;
--bracket-text: #212529;
--bracket-text-secondary: #6c757d;
--bracket-accent: #0d6efd;
--bracket-winner: #198754;
--bracket-connector: #adb5bd;
--bracket-connector-width: 2px;
--bracket-card-radius: 6px;
--bracket-font: inherit;
}Shadow DOM Parts
Style internal elements with ::part():
| Part | Element |
|---|---|
| svg | Root SVG element |
| match-card | Individual match card group |
| connector | Bracket connector lines |
| round-label | Round header text |
Framework Usage
<bracket-view> is a standard Web Component. It works in any framework.
React
import 'bracketeer';
function Bracket({ matches }) {
const ref = useRef(null);
useEffect(() => {
ref.current.matches = matches;
}, [matches]);
return <bracket-view ref={ref} format="single-elim" theme="dark" />;
}Vue
<template>
<bracket-view ref="bracket" format="single-elim" theme="dark" />
</template>
<script setup>
import 'bracketeer';
import { ref, onMounted, watch } from 'vue';
const props = defineProps({ matches: Array });
const bracket = ref(null);
onMounted(() => { bracket.value.matches = props.matches; });
watch(() => props.matches, (val) => { bracket.value.matches = val; });
</script>Svelte
<script>
import 'bracketeer';
export let matches = [];
let el;
$: if (el) el.matches = matches;
</script>
<bracket-view bind:this={el} format="single-elim" theme="dark" />Plain HTML
<script type="module" src="https://unpkg.com/bracketeer"></script>
<bracket-view id="b" format="single-elim" theme="light"></bracket-view>
<script>
document.getElementById('b').matches = [ /* ... */ ];
</script>License
MIT
