vueckets
v1.0.6
Published
Customizable Vue component for rendering single elimination tournament brackets.
Readme
Vueckets 🏆
Vueckets is a clean and minimal Vue 3 component for rendering single-elimination brackets, with built‑in support for battle royale style matches (3+ teams per match).
✨ Features
- Battle royale mode: Auto-switches to a list view when any match has more than two teams
- Round title controls: Easily customize round title colors, borders, and min width
- Customizable list view: Tweak tab, table head, and border colors via props
- Responsive: Works across screen sizes, battle royale list is full width
- Winner/defeated states: Built-in visual states you can extend with custom classes
- Flexible data: Rounds-based or flat tree inputs
🚀 Installation
npm install vueckets📋 Basic Usage
<template>
<vueckets :rounds="rounds">
<template #team="{ team }">
{{ team.name }}
</template>
</vueckets>
</template>
<script>
import Vueckets from 'vueckets';
export default {
components: {
Vueckets
},
data() {
return {
rounds: [
{
// Classic 1v1 round
matches: [
{
team1: { id: '1', name: 'Team A', winner: true },
team2: { id: '2', name: 'Team B', winner: false }
}
]
}
]
};
}
};
</script>🎨 Styling with Props (no themes)
Pass simple props to style everything. No global themes required.
Core layout and colors
| Prop | Type | Default | What it controls |
|------|------|---------|------------------|
| backgroundColor | String | #ffffff | Match box background (classic 1v1) |
| textColor | String | #ffffff | Text color inside match boxes |
| winnerColor | String | #501696 | Background for winners (classic 1v1) |
| defeatedColor | String | #501696 | Background for defeated (classic 1v1) |
| borderColor | String | #501696 | Border color for match boxes and separators |
| borderRadius | String | 6px | Radius for match boxes and titles |
| spacing | String | 12px | Vertical spacing between items/rounds |
| fontSize | String | 14px | Base font size |
| playerPadding | String | 8px 12px | Padding inside match boxes |
| teamPadding | String | 8px 12px | Padding inside team boxes (overrides playerPadding) |
Bracket connections (classic)
| Prop | Type | Default | What it controls |
|------|------|---------|------------------|
| connectionColor | String | #85E642 | Color of connection lines between matches |
| connectionWidth | String | 24px | Horizontal connection line length |
| connectionThickness | String | 1px | Connection line thickness |
Round titles
| Prop | Type | Default | What it controls |
|------|------|---------|------------------|
| roundTitleColor | String | #64748b | Title text color |
| roundTitleBgColor | String | #f8fafc | Title background |
| roundTitleBorderColor | String | #e2e8f0 | Title border |
| roundTitleMinWidth | String | 177px | Title column min-width |
Team hover effects
| Prop | Type | Default | What it controls |
|------|------|---------|------------------|
| winnerTeamHover | String | rgba(0, 0, 0, 0.1) | Hover color for winning teams |
| defeatedTeamHover | String | rgba(0, 0, 0, 0.1) | Hover color for defeated teams |
Scrollbar customization
| Prop | Type | Default | What it controls |
|------|------|---------|------------------|
| scrollbarColor | String | #cbd5e1 | Main scrollbar color |
| scrollbarTrackColor | String | #f1f5f9 | Scrollbar track background |
Battle royale – tabs (Rounds/Matches)
| Prop | Type | Default |
|------|------|---------|
| brTabBg | String | #1A1A1A |
| brTabTextColor | String | #ffffff |
| brTabActiveBg | String | #8200DB |
| brTabActiveTextColor | String | #ffffff |
Battle royale – table header
| Prop | Type | Default |
|------|------|---------|
| brTableHeadBg | String | #1C1C1C |
| brTableHeadTextColor | String | #ffffff |
Battle royale – team list
| Prop | Type | Default | What it controls |
|------|------|---------|------------------|
| brListBg | String | #000000 | List background |
| brListTextColor | String | #ffffff | Text color in list |
| brListRowBg | String | '' | Individual row background (falls back to brListBg) |
| brListRowHoverBg | String | '' | Row hover background (falls back to #2A2A2A) |
| brRowDividerColor | String | #1C1C1C | Row divider lines |
Utility
| Prop | Type | Default | Notes |
|------|------|---------|------|
| rounds | Array | [] | Primary input (supports classic matches with team1/team2, or teams array for battle royale) |
| flatTree | Array | [] | Alternative input format (flat) |
| wrapperClass | String | '' | Extra classes on root wrapper |
| wrapperStyle | Object | {} | Inline styles for root wrapper |
| customClasses | Object | {} | { wrapper, item, itemParent, itemChild, player, winner, defeated, team } overrides |
You can pass only what you need; everything has sensible defaults.
📚 API Reference
See the props tables above. Most styles can be changed at runtime by binding reactive values.
Custom Styles Object
{
backgroundColor: '#999999', // Player container background
textColor: 'white', // Text color
winnerColor: 'darkgreen', // Winner background color
defeatedColor: 'firebrick', // Defeated player background color
winnerTeamHover: 'rgba(0,0,0,0.1)', // Winner hover color
defeatedTeamHover: 'rgba(0,0,0,0.1)', // Defeated hover color
connectionColor: 'gray', // Bracket connection lines color
borderRadius: '0px', // Border radius for player containers
spacing: '10px', // Spacing between elements
fontSize: '14px', // Font size
teamPadding: '8px 12px', // Team padding (overrides playerPadding)
scrollbarColor: '#cbd5e1', // Scrollbar color
scrollbarTrackColor: '#f1f5f9' // Scrollbar track color
}Custom Classes Object
{
wrapper: '', // Wrapper container class
item: '', // Bracket item class
itemParent: '', // Parent bracket item class
itemChild: '', // Child bracket item class
player: '', // Player container class
winner: '', // Winner player class
defeated: '' // Defeated player class
}Data Structure
Classic 1v1
[
{
matches: [
{
team1: { id: '1', name: 'Team A', winner: true },
team2: { id: '2', name: 'Team B', winner: false }
}
]
}
]Battle Royale (3+ teams)
[
{
name: 'Group Stage',
matches: [
{
teams: [
{ id: 't1', name: 'Team 1', points: 10 },
{ id: 't2', name: 'Team 2', points: 14 },
{ id: 't3', name: 'Team 3', points: 9 }
]
}
]
}
]Team Object shape
type Team = {
id: string | number
name: string
// optional fields
winner?: boolean // true when team won the match
points?: number // numeric points shown in battle royale list (also supported in classic)
};Notes:
- In classic (1v1), put optional
pointsonteam1/team2if you want to display it in your custom team slot. - In battle royale,
pointsis shown in the right column by default.
Battle Royale Mode
Battle royale is enabled automatically when any match within any round contains more than two teams using a teams array. The UI switches to a list view with scrollable round and match buttons.
Data format (battle royale)
const rounds = [
{
name: 'Group Stage',
matches: [
{
teams: [
{ id: 'g1-1', name: 'Team 1', points: 10 },
{ id: 'g1-2', name: 'Team 2', points: 14 },
{ id: 'g1-3', name: 'Team 3', points: 9 }
]
}
]
}
];Slots (battle royale)
#team: customize team row rendering.
<template #team="{ team }">
{{ team.name }}
<!-- you can include badges, logos, etc. -->
<span v-if="team.points">{{ team.points }}</span>
</template>Customizable props (round titles and battle royale)
- Round titles:
roundTitleColor,roundTitleBgColor,roundTitleBorderColor - Battle royale tabs:
brTabBg,brTabTextColor,brTabActiveBg,brTabActiveTextColor - Battle royale table head:
brTableHeadBg,brTableHeadTextColor - Battle royale team list:
brListBg,brListTextColor,brListRowBg,brListRowHoverBg,brRowDividerColor
Example usage:
<template>
<vueckets
:rounds="rounds"
:round-title-color="'#94a3b8'"
:round-title-bg-color="'#0f172a'"
:round-title-border-color="'#1e293b'"
:winner-team-hover="'rgba(255, 255, 255, 0.1)'"
:defeated-team-hover="'rgba(255, 0, 0, 0.1)'"
:br-tab-bg="'#111827'"
:br-tab-text-color="'#e5e7eb'"
:br-tab-active-bg="'#374151'"
:br-tab-active-text-color="'#ffffff'"
:br-table-head-bg="'#111827'"
:br-table-head-text-color="'#9ca3af'"
:br-list-row-bg="'#1f2937'"
:br-list-row-hover-bg="'#374151'"
:br-row-divider-color="'#374151'"
>
<template #team="{ team }">{{ team.name }}</template>
</vueckets>
</template>Slots
#team: customize how a team is rendered (used for both classic and battle royale)#team-extension-bottom: content under a two‑team match box
🎯 Advanced Examples
Tournament with Team Logos
<template>
<vueckets :rounds="rounds" theme="dark">
<template #player="{ player }">
<div class="team-player">
<img :src="player.logo" :alt="player.name" class="team-logo" />
<div class="team-info">
<div class="team-name">{{ player.name }}</div>
<div class="team-score">{{ player.score }}</div>
</div>
</div>
</template>
</vueckets>
</template>
<style>
.team-player {
display: flex;
align-items: center;
gap: 8px;
}
.team-logo {
width: 24px;
height: 24px;
border-radius: 50%;
}
.team-info {
flex: 1;
}
.team-name {
font-weight: bold;
}
.team-score {
font-size: 0.8em;
opacity: 0.8;
}
</style>Responsive Bracket
<template>
<vueckets
:rounds="rounds"
:custom-styles="responsiveStyles"
wrapper-class="responsive-bracket"
>
<template #player="{ player }">{{ player.name }}</template>
</vueckets>
</template>
<script>
export default {
computed: {
responsiveStyles() {
return {
fontSize: window.innerWidth < 768 ? '12px' : '16px',
spacing: window.innerWidth < 768 ? '8px' : '12px'
};
}
}
};
</script>
<style>
.responsive-bracket {
max-width: 100%;
overflow-x: auto;
}
@media (max-width: 768px) {
.responsive-bracket {
font-size: 0.875rem;
}
}
</style>🛠️ Development
# Install dependencies
npm install
# Serve development app
npm run serve
# Build library
npm run build
# Run tests
npm test
# Lint code
npm run lint📄 Migration from vue-tournament-bracket
Vueckets is designed to be backward compatible with vue-tournament-bracket. Simply replace your import and add customization props as needed:
// Before
import Bracket from 'vue-tournament-bracket';
// After
import Vueckets from 'vueckets';🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📜 License
MIT License - see LICENSE file for details.
🙏 Acknowledgments
- Built upon the foundation of vue-tournament-bracket
- Inspired by modern tournament bracket designs
- Thanks to the Vue.js community for their amazing ecosystem
Made with ❤️ for the Vue.js community
