# MatchScheduleArena

A match schedule arena component for displaying user rankings, personal information, countdown and action buttons in competitions, suitable for competitive game schedule management.

# Import

import PressMatchScheduleArena from 'press-next/press-match-schedule-arena/press-match-schedule-arena';

# Usage

# Basic Usage

Display user ranking, personal information, countdown and action buttons.

<template>
  <PressMatchScheduleArena
    rank-text="5th Place"
    rank-title="Match in Progress"
    status-type="champion"
    :user-info="userInfo"
    :day-time="dayTime"
    @button-click="handleButtonClick"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const userInfo = ref({
  nickname: 'Game Player',
  avatar: 'https://example.com/avatar.jpg',
  killCount: 15
});

// Countdown time in milliseconds: 25 days 10 hours 30 minutes
const dayTime = ref(25 * 24 * 60 * 60 * 1000 + 10 * 60 * 60 * 1000 + 30 * 60 * 1000);

const handleButtonClick = (button, index) => {
  console.log('Button clicked:', button.text, button.action);
  if (button.action === 'viewRanking') {
    // View ranking
  } else if (button.action === 'goToMatch') {
    // Go to match
  }
};
</script>

# Custom Buttons

Customize button text, type and action identifier with a maximum of 2 buttons.

<template>
  <PressMatchScheduleArena
    rank-text="3rd Place"
    rank-title="Match in Progress"
    status-type="champion"
    :user-info="userInfo"
    :ctrl-buttons="customButtons"
    :day-time="dayTime"
    @button-click="handleButtonClick"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const userInfo = ref({
  nickname: 'Pro Player',
  avatar: 'https://example.com/avatar.jpg',
  killCount: 28
});

const dayTime = ref(10 * 60 * 60 * 1000); // 10 hours

// Custom button configuration (max 2 buttons)
const customButtons = [
  { text: 'Share Stats', type: 'default', action: 'share' },
  { text: 'Continue', type: 'primary', action: 'continue' }
];

const handleButtonClick = (button, index) => {
  console.log('Button clicked:', button.text, button.action);
  switch (button.action) {
    case 'share':
      // Share stats
      break;
    case 'continue':
      // Continue game
      break;
  }
};
</script>

# Single Button Configuration

When only one button is configured, it takes up the full width.

<template>
  <PressMatchScheduleArena
    rank-text="TBD"
    rank-title="Match Not Started"
    :user-info="userInfo"
    :day-time="0"
    :ctrl-buttons="[{ text: 'Start Match', type: 'primary', action: 'start' }]"
    @button-click="handleButtonClick"
  />
</template>

<script setup lang="ts">
const userInfo = {
  nickname: 'Rookie',
  avatar: 'https://example.com/avatar.jpg',
  killCount: 0
};

const handleButtonClick = (button) => {
  if (button.action === 'start') {
    // Start match
  }
};
</script>

# Custom Countdown

Control countdown time via the day-time prop (in milliseconds).

<template>
  <div>
    <!-- Short countdown: 2 hours -->
    <PressMatchScheduleArena
      rank-text="1st Place"
      rank-title="Ending Soon"
      :user-info="userInfo"
      :day-time="2 * 60 * 60 * 1000"
    />

    <!-- Long countdown: 30 days -->
    <PressMatchScheduleArena
      rank-text="5th Place"
      rank-title="Season in Progress"
      :user-info="userInfo"
      :day-time="30 * 24 * 60 * 60 * 1000"
    />

    <!-- Dynamic countdown update -->
    <PressMatchScheduleArena
      rank-text="3rd Place"
      rank-title="Match in Progress"
      :user-info="userInfo"
      :day-time="remainingTime"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';

const userInfo = {
  nickname: 'Competitive Player',
  avatar: 'https://example.com/avatar.jpg',
  killCount: 18
};

// Dynamic countdown
const remainingTime = ref(5 * 60 * 60 * 1000); // Initial 5 hours
let timer: number;

onMounted(() => {
  // Update countdown every second
  timer = setInterval(() => {
    if (remainingTime.value > 0) {
      remainingTime.value -= 1000;
    }
  }, 1000);
});

onUnmounted(() => {
  clearInterval(timer);
});
</script>

# Custom Button Slot

Use slot to fully customize button area styles and interactions.

<template>
  <PressMatchScheduleArena
    rank-text="2nd Place"
    rank-title="Match in Progress"
    :user-info="userInfo"
    :day-time="dayTime"
  >
    <template #ctrls-btn>
      <button class="custom-btn secondary" @click="handleViewDetails">
        View Details
      </button>
      <button class="custom-btn primary" @click="handleJoinMatch">
        Join Now
      </button>
    </template>
  </PressMatchScheduleArena>
</template>

<script setup lang="ts">
const userInfo = {
  nickname: 'Custom Player',
  avatar: 'https://example.com/avatar.jpg',
  killCount: 20
};

const dayTime = 8 * 60 * 60 * 1000; // 8 hours

const handleViewDetails = () => {
  console.log('View match details');
};

const handleJoinMatch = () => {
  console.log('Join match now');
};
</script>

<style scoped>
.custom-btn {
  flex: 1;
  padding: .16rem .32rem;
  border-radius: .08rem;
  border: none;
  font-size: .28rem;
}

.custom-btn.primary {
  background: #1e72ff;
  color: white;
}

.custom-btn.secondary {
  background: transparent;
  color: #1e72ff;
  border: .02rem solid #1e72ff;
}
</style>

# API

# Props

Attribute Description Type Default
rank-text Rank text string 第xx名
rank-title Title text string 比赛进行中
user-info User information UserInfo -
ctrl-buttons Control button configuration (max 2) CtrlButton[] [{ text: '查看榜单', type: 'default', action: 'viewRanking' }, { text: '去对局', type: 'primary', action: 'goToMatch' }]
custom-class Custom class name string ''

# UserInfo Data Structure

interface UserInfo {
  nickname: string;    // User nickname
  avatar?: string;     // User avatar
  killCount?: number;  // Kill count
}

# CtrlButton Data Structure

interface CtrlButton {
  text: string;  // Button text
  type?: 'primary' | 'default';  // Button type
  action?: string;  // Button action identifier
}

# Events

Event Description Parameters
button-click Triggered when button is clicked (button: CtrlButton, index: number)

# Slots

Name Description
ctrls-btn Custom action button area

# Features

# Core Functions

  • Ranking Display: Shows user's current ranking information with custom status types
  • User Information: Displays avatar, nickname, kill count and other info, supports long nickname truncation
  • Smart Countdown: Auto-formats remaining time (days/hours/minutes/seconds), supports external customization
  • Custom Buttons: Supports 1-2 customizable text and type action buttons

# Countdown System

  • Externally Controllable: Pass countdown time via day-time prop (milliseconds)
  • Dynamic Updates: Supports real-time countdown data updates
  • Smart Formatting: Auto-displays in "XX days XX hours XX minutes" format
  • Accurate to Seconds: Uses mini countdown component for precise display

# Button System

  • 🎯 Flexible Configuration: Supports 1-2 buttons, automatically truncates if more than 2
  • 🎯 Type Variety: Supports primary and default types
  • 🎯 Action Identifier: Distinguishes different button actions through action field
  • 🎯 Responsive Layout: Single button takes full width, dual buttons split equally
  • 🎯 Slot Extension: Supports full customization of button area via ctrls-btn slot

# Use Cases

  • Competitive game schedule management (real-time countdown)
  • Ranked match progress display (rank change tracking)
  • Tournament status tracking (season countdown)
  • Personal competitive data display (stats tracking)

# Theming

The component provides the following CSS variables, which can be used to customize styles. Please refer to the ConfigProvider component for usage.

# Style Variables

Name Default Value Description
--pmsa-card-padding $spacing-lg Card padding
--pmsa-title-mt .4rem Title top margin
--pmsa-title-mb $spacing-sm Title bottom margin
--pmsa-title-gap $spacing-sm Title inner gap
--pmsa-user-mt $spacing-sm User area top margin
--pmsa-user-gap $spacing-xs User info gap
--pmsa-stats-padding-lr $spacing-sm Stats area left-right padding
--pmsa-ctrls-gap $spacing-lg Button gap
--pmsa-ctrls-mt $spacing-lg Button top margin
--pmsa-user-padding-top $spacing-md User area top padding
--pmsa-countdown-mt $spacing-md Countdown top margin
--pmsa-title-xiushi-width 1.2rem Title decoration width
--pmsa-avatar-size 1rem Avatar size
--pmsa-nickname-max-width 2.88rem Nickname max width
--pmsa-stats-height .34rem Stats area height
--pmsa-card-bg-color $color-surface-default Card background color
--pmsa-title-text-color $color-text-primary Title text color
--pmsa-nickname-text-color $color-text-secondary Nickname text color
--pmsa-stats-bg-color $color-surface-brand-light2 Stats background color
--pmsa-stats-text-color $color-text-brand Stats text color
--pmsa-title-xiushi-left-bg linear-gradient(...) Title decoration left background
--pmsa-title-xiushi-right-bg linear-gradient(...) Title decoration right background
--pmsa-countdown-label-text-color $color-text-secondary Countdown label text color
--pmsa-countdown-info-text-color $color-text-secondary Countdown info text color
--pmsa-avatar-border-color $color-divider-default Avatar border color
--pmsa-user-bg linear-gradient(...) User background color
--pmsa-title-font-size $font-size-lg Title font size
--pmsa-nickname-font-size $font-size-md Nickname font size
--pmsa-nickname-font-weight $font-weight-bold Nickname font weight
--pmsa-stats-font-size $font-size-xs Stats font size
--pmsa-countdown-label-font-size $font-size-sm Countdown label font size
--pmsa-countdown-info-font-size $font-size-sm Countdown info font size
--pmsa-card-border-radius $border-radius-sm Card border radius
--pmsa-avatar-border-radius $border-radius-circle Avatar border radius
--pmsa-stats-border-radius $border-radius-none Stats area border radius
--pmsa-user-border-radius $border-radius-sm User area border radius
--pmsa-card-shadow none Card shadow

# Custom Style Example

<template>
  <PressMatchScheduleArena
    class="custom-arena"
    :rank-text="rankText"
    :user-info="userInfo"
  />
</template>

<style>
.custom-arena {
  --pmsa-card-bg-color: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  --pmsa-title-text-color: #ffffff;
  --pmsa-nickname-text-color: #ffffff;
  --pmsa-stats-bg-color: rgba(255, 255, 255, 0.2);
  --pmsa-stats-text-color: #ffffff;
  --pmsa-card-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
</style>