# MatchRoundSetList

Round setting list component for displaying multiple match round settings with header and round items.

# Import

import PressMatchRoundSetList from 'press-next/press-match-round-set-list/press-match-round-set-list';

# Usage

# Basic Usage

<PressMatchRoundSetList
  :list="roundSetList"
  @item-click="onItemClick"
  @action-click="onActionClick"
/>

# Custom Style

<PressMatchRoundSetList
  custom-class="custom-round-set-list"
  :list="roundSetList"
  @item-click="onItemClick"
  @action-click="onActionClick"
/>

# Custom Column Configuration

<PressMatchRoundSetList
  :list="roundSetList"
  :columns="customColumns"
  @item-click="onItemClick"
  @action-click="onActionClick"
/>
// Custom column configuration
const customColumns = [
  { key: 'rounds', title: 'Round', width: '1.5rem', align: 'left' },
  { key: 'settings', title: 'Start Settings', width: '2.5rem', align: 'center' },
  { key: 'ways', title: 'Format', width: '1.8rem', align: 'center' },
  { key: 'operate', title: 'Action', width: '2rem', align: 'center' }
];

# API

# Props

Attribute Description Type Default
custom-class Custom style class name string ''
list Round setting data list RoundSetItemData[] []
columns Table column configuration Column[] getTableColumns()

# Column Interface

interface Column {
  key: string;
  title: string;
  width?: string;
  minWidth?: string;
  align?: 'left' | 'center' | 'right';
  sortable?: boolean;
}

# RoundSetItemData Structure

interface RoundSetItemData {
  roundName: string;        // Round name
  timeText: string;         // Start time text
  formatText: string;       // Winning format text
  actionText: string;       // Action text
  selected?: boolean;       // Whether selected
  disabled?: boolean;       // Whether disabled
  editable?: boolean;       // Whether editable
  showTimeIcon?: boolean;   // Whether to show time icon
  showFormatIcon?: boolean; // Whether to show format icon
  hasStarted?: boolean;     // Whether started
  canSetTime?: boolean;     // Whether can set time
  canSetBo?: boolean;       // Whether can set best-of format
  bo_type?: number;         // Best-of type (1: Best of 1, 3: Best of 3, 5: Best of 5, 7: Best of 7)
}

# Events

Event Description Parameters
item-click Triggered when clicking round item (item: RoundSetItemData, index: number)
action-click Triggered when clicking action button (item: RoundSetItemData, index: number)
time-click Triggered when clicking time setting (item: RoundSetItemData, index: number)
format-click Triggered when clicking format setting (item: RoundSetItemData, index: number)
set-round-bo Triggered when setting round best-of format (data: { currentRound: RoundSetItemData; value: number })
set-round-time Triggered when setting round time (data: { currentRound: RoundSetItemData; value: any })
start-all-round Triggered when starting entire round (data: { currentRound: RoundSetItemData })
sort Triggered when header sorting (data: { key: string; order: 'asc' \| 'desc' \| null })

# Style Customization

# CSS Variables

The component provides rich CSS variables for style customization, all using the --mrsl- prefix:

/* Position Properties */
--mrsl-container-position: relative;    /* Container position type */
--mrsl-header-position: relative;       /* Header position type */
--mrsl-content-position: relative;      /* Content area position type */

/* Box Model Properties */
--mrsl-container-width: 100%;           /* Container width */
--mrsl-container-height: auto;          /* Container height */
--mrsl-header-width: 100%;              /* Header width */
--mrsl-header-height: .7rem;            /* Header height */
--mrsl-header-padding: .14rem .22rem;   /* Header padding */
--mrsl-content-width: 100%;             /* Content area width */
--mrsl-content-height: calc(100% - .7rem); /* Content area height */
--mrsl-header-item-round-min-width: 1.2rem; /* Round header item minimum width */
--mrsl-header-item-time-min-width: 2rem; /* Time header item minimum width */
--mrsl-header-item-format-min-width: 1.4rem; /* Format header item minimum width */
--mrsl-header-item-action-min-width: 1.6rem; /* Action header item minimum width */

/* Border Properties */
--mrsl-container-border-radius: $border-radius-none; /* Container border radius */

/* Background Properties */
--mrsl-container-bg: linear-gradient(91deg, rgba(237, 239, 241, .5) 0%, rgba(252, 252, 252, .5) 100%); /* Container background gradient */
--mrsl-header-bg: url(https://image-1251917893.file.myqcloud.com/general-match-components/img/match-round-set-list/table-header.png); /* Header background image */
--mrsl-header-bg-size: 100% 100%;       /* Header background image size */

/* Text Properties */
--mrsl-header-item-color: $color-text-invert-light; /* Header item text color */
--mrsl-header-item-font-size: $font-size-xs; /* Header item font size */
--mrsl-header-item-font-weight: $font-weight-regular; /* Header item font weight */
--mrsl-header-item-time-text-align: center; /* Time header item text alignment */
--mrsl-header-item-format-text-align: center; /* Format header item text alignment */
--mrsl-header-item-action-text-align: right; /* Action header item text alignment */

/* Other Properties */
--mrsl-content-overflow-y: auto;        /* Content area vertical overflow */

/* Header Scroll Related */
--mrsl-header-scroll-min-width: calc(1.48rem + 1.94rem + 1.6rem + 1.6rem); /* Header scroll minimum width */
--mrsl-header-scroll-overflow-x: auto;  /* Header horizontal scroll */
--mrsl-header-scrollbar-width: none;    /* Firefox scrollbar width */
--mrsl-header-scrollbar-style: none;    /* IE scrollbar style */
--mrsl-header-webkit-scrollbar-display: none; /* Webkit scrollbar display */

/* Header Cell Related */
--mrsl-header-cell-flex-shrink: 0;      /* Header cell flex shrink */

# Theme Customization Examples

/* Dark Theme */
.dark-theme {
  --mrsl-container-bg: linear-gradient(91deg, rgba(30, 30, 30, .8) 0%, rgba(50, 50, 50, .8) 100%);
  --mrsl-header-item-color: #ffffff;
}

/* Compact Layout */
.compact-layout {
  --mrsl-header-height: .6rem;
  --mrsl-header-padding: .12rem .18rem;
  --mrsl-header-item-font-size: $font-size-xxs;
}

/* Custom Size */
.custom-size {
  --mrsl-header-item-round-min-width: 1.2rem;
  --mrsl-header-item-time-min-width: 1.4rem;
  --mrsl-header-item-format-min-width: 1.3rem;
  --mrsl-header-item-action-min-width: 1.3rem;
}

# Design System Integration

The component is fully integrated with the design system using semantic variables:

  • Color System: References $color-text-invert-light and other semantic variables
  • Font System: Uses $font-size-xs, $font-weight-regular standard font variables
  • Border System: Uses $border-radius-none standard border radius variables

# Architecture Design

The component uses CSS variable passing to communicate with child components, avoiding :deep() style penetration:

// Parent component passes styles to header component
&__header {
  --pmth-header-overflow-x: auto;
  --pmth-header-min-width: calc(1.48rem + 1.94rem + 1.6rem + 1.6rem);
  --pmth-header-scrollbar-width: none;
  --pmth-header-cell-round-min-width: 1.48rem;
  --pmth-header-cell-time-min-width: 1.94rem;
  // More variables...
}

// Parent component passes styles to round item component for width synchronization
&__content {
  --mrsi-round-min-width: 1.48rem;
  --mrsi-time-min-width: 1.94rem;
  --mrsi-format-min-width: 1.6rem;
  --mrsi-action-min-width: 1.6rem;
  --mrsi-container-scrollbar-width: none;
  // More variables...
}

# Width Synchronization Mechanism

To ensure perfect width synchronization between header cells and content items, the component adopts a dual synchronization strategy:

1. CSS Variable Synchronization (Original Method)

  • Unified Variable Source: All widths come from $mrsl-header-item-*-min-width variables
  • Bidirectional Passing: Simultaneously passed to both header and round item components
  • Dynamic Calculation: Container minimum width calculated dynamically through variables
// Dynamic calculation in round item component
min-width: calc(#{$mrsi-round-min-width} + #{$mrsi-time-min-width} + #{$mrsi-format-min-width} + #{$mrsi-action-min-width});

2. Column Configuration Synchronization (New Method)

  • Unified Configuration Source: Header and content items use the same tableColumns configuration
  • Direct Passing: Pass header column configuration directly to round item components
  • Higher Priority: When both exist, column configuration takes precedence over CSS variables
// Table column configuration - consistent with press-match-table-header demo-data
const tableColumns = [
  { key: 'rounds', title: '轮次', width: '1.2rem', align: 'left' },
  { key: 'settings', title: '开赛设置', width: '2rem', align: 'center' },
  { key: 'ways', title: '决胜方式', width: '1.4rem', align: 'center' },
  { key: 'operate', title: '操作', width: '1.6rem', align: 'center' }
];

Advantages of this design:

  • Style Encapsulation: Doesn't break component style isolation
  • Width Synchronization: Ensures perfect alignment between header and content items
  • Compatibility: No need to modify existing child components
  • Maintainability: Avoids maintenance issues from style penetration
  • Performance: Reduces style calculation overhead
  • Extensibility: Facilitates future feature extensions
  • Flexible Configuration: Supports runtime dynamic column width adjustment

# Example

<template>
  <div class="demo-container">
    <PressMatchRoundSetList
      :list="roundSetList"
      @item-click="onItemClick"
      @action-click="onActionClick"
      @time-click="onTimeClick"
      @format-click="onFormatClick"
      @set-round-bo="onSetRoundBo"
      @set-round-time="onSetRoundTime"
      @start-all-round="onStartAllRound"
      @sort="onSort"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchRoundSetList from 'press-next/press-match-round-set-list/press-match-round-set-list';

const roundSetList = ref([
  {
    roundName: 'Round of 32',
    timeText: 'Mar 18 12:00',
    formatText: 'Best of 1',
    actionText: 'Start Round',
    editable: true,
    showTimeIcon: true,
    showFormatIcon: true,
    hasStarted: false,
    canSetTime: true,
    canSetBo: true,
    bo_type: 1,
  },
  {
    roundName: 'Round of 16',
    timeText: 'Mar 19 14:00',
    formatText: 'Best of 3',
    actionText: 'Start Round',
    editable: true,
    showTimeIcon: true,
    showFormatIcon: true,
    hasStarted: false,
    canSetTime: true,
    canSetBo: true,
    bo_type: 3,
  },
  // More data...
]);

const onItemClick = (item, index) => {
  console.log('Click round:', item.roundName, index);
};

const onActionClick = (item, index) => {
  console.log('Click action:', item.actionText, index);
};

const onTimeClick = (item, index) => {
  console.log('Click time setting:', item.timeText, index);
};

const onFormatClick = (item, index) => {
  console.log('Click format setting:', item.formatText, index);
};

const onSetRoundBo = (data) => {
  console.log('Set best-of format:', data.currentRound.roundName, data.value);
  // Update data
  data.currentRound.bo_type = data.value;
};

const onSetRoundTime = (data) => {
  console.log('Set time:', data.currentRound.roundName, data.value);
  // Update data
  data.currentRound.timeText = formatTime(data.value);
};

const onStartAllRound = (data) => {
  console.log('Start entire round:', data.currentRound.roundName);
  // Update status
  data.currentRound.hasStarted = true;
};

const onSort = (data) => {
  console.log('Sort:', data.key, data.order);
  // Handle sorting logic
};

const formatTime = (timestamp) => {
  const date = new Date(timestamp);
  return `${date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })} ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
};
</script>