239 lines
6.3 KiB
Markdown
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).
|
|
|
|

|
|
|
|
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 },
|
|
}
|
|
]
|
|
}
|
|
];
|
|
```
|
|
|
|

|
|
|
|
#### 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.
|
|
|
|

|
|
|
|
### 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:
|
|
|
|

|
|
|
|
|
|
### 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
|