2025-05-28 17:55:30 +08:00

239 lines
6.3 KiB
Markdown

# vue-tournament-bracket
Vue component for rendering single elimination tournament brackets. Compatible with Vue 3. For Vue 2 support install 2.* version of the package.
Based on: [https://codepen.io/sdudnyk/pen/bWbqMb](https://codepen.io/sdudnyk/pen/bWbqMb).
Rendering is based on **flex**, see [browser support](https://caniuse.com/#feat=flexbox).
![Example](https://github.com/kamilwylegala/vue-tournament-bracket/raw/master/docs/example.png)
Real life example can be found here: [martialmatch.com](https://martialmatch.com/).
## Installation and component usage
Install component via:
```
npm install vue-tournament-bracket
```
Example:
```html
<template>
<bracket :rounds="rounds">
<template slot="player" slot-scope="{{ player }}">
{{ player.name }}
</template>
</bracket>
<template>
<script>
import Bracket from "vue-tournament-bracket";
const rounds = [
//Semi finals
{
games: [
{
player1: { id: "1", name: "Competitor 1", winner: false },
player2: { id: "4", name: "Competitor 4", winner: true },
},
{
player1: { id: "5", name: "Competitor 5", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
}
]
},
//Final
{
games: [
{
player1: { id: "4", name: "Competitor 4", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
}
]
}
];
export default {
components: {
Bracket
},
data() {
return {
rounds: rounds
}
}
}
</script>
```
#### Third place play-off
Here is the way to represent third place play-off:
```javascript
const rounds = [
//Semi finals
{
games: [
{
player1: { id: "1", name: "Competitor 1", winner: false },
player2: { id: "4", name: "Competitor 4", winner: true },
},
{
player1: { id: "5", name: "Competitor 5", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
}
]
},
//Third place play off
{
games: [
{
player1: { id: "1", name: "Competitor 1", winner: false },
player2: { id: "5", name: "Competitor 5", winner: true },
}
]
},
//Final
{
games: [
{
player1: { id: "4", name: "Competitor 4", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
}
]
}
];
```
![Third place play-off](https://github.com/kamilwylegala/vue-tournament-bracket/raw/master/docs/thirdplaceplayoff.png)
#### Bottom slot
There is slot with whole match props, use it in following way:
```html
<bracket :rounds="rounds">
<template #player="{ player }">
{{ player.name }}
</template>
<template #player-extension-bottom="{ match }">
Extra info: {{ match.title }}
</template>
</bracket>
```
May be useful for example for showing tooltips etc.
![Bottom slot for match](https://github.com/kamilwylegala/vue-tournament-bracket/raw/master/docs/bottom-slot.png)
### Game object
Game object requires `player1` and `player2` objects. You can also add your own and e.g. reuse it in `players-extension-bottom` slot.
Following properties are forbidden and are going to be replaced with `undefined`:
- `games`
- `hasParent`
See `matchProperties` in `GamePlayers` for details.
### Alternative input - flat tree
Version 2.1 introduces option to build bracket tree from flat tree structure where child node points to its parent node. Structure is a bit simple but requires two additional properties on each game object: `id`, `next`. It might be helpful in generating double elimination brackets with repechages. Example:
```
const rounds = [
//Repechage 1 of 3
{
id: 1,
next: 5, //Will be connected to game with id 5
player1: { id: "4", name: "Competitor 4", winner: true },
player2: { id: "5", name: "Competitor 5", winner: false },
},
{
id: 2,
next: 6,
player1: { id: "7", name: "Competitor 7", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
},
//Repechage 2 of 3
{
id: 5,
next: 7,
player1: { id: "1", name: "Competitor 1", winner: false },
player2: { id: "4", name: "Competitor 4", winner: true },
},
{
id: 6,
next: 7,
player1: { id: "3", name: "Competitor 3", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
},
//Repechage 3 of 3 - 3rd place match
{
id: 7,
player1: { id: "4", name: "Competitor 4", winner: false },
player2: { id: "8", name: "Competitor 8", winner: true },
},
];
```
Initialize bracket with `flatTree` props:
```html
<bracket :flat-tree="rounds">
```
It generates following bracket:
![Repechage](https://github.com/kamilwylegala/vue-tournament-bracket/raw/master/docs/flat-tree.png)
### Player object
Player object requires: `id` property, `winner` is optional, rest is up to you - rendering is customizable via scoped slot.
- `id` is being used for highlighting
- `winner` property applies color for player accordingly, can be also `null` - player's color will be gray
### Styling
Apply your custom style by overriding `Bracket` component CSS. See [BracketNode.vue](./src/components/BracketNode.vue) for all styles being used.
## Development
Required Node.js version is **14.0.0** (eslint).
Checkout repository and:
```
npm install
npm run serve
```
Then open browser and test your changes using `App.vue` main component for development purposes.
See `package.json` to discover available commands.
## Releasing
```
npm test
npm run eslint
npm run build
git commit
npm version <version>
git push
npm publish --access=public
```
## License
MIT