# MatchTeamInfoList Team Info List

A list component for displaying team information with scroll-to-load-more functionality and empty state handling.

# Import

import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';

# Code Examples

# Basic Usage

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    :loading="loading"
    :finished="finished"
    @load-more="loadMore"
    @apply="handleApply"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';

const teamList = ref([]);
const loading = ref(false);
const finished = ref(false);
const currentPage = ref(0);
const pageSize = 10;

const loadMore = () => {
  if (loading.value || finished.value) return;

  loading.value = true;

  // Simulate async data loading
  setTimeout(() => {
    const newData = generateTeamData(currentPage.value, pageSize);

    if (newData.length > 0) {
      teamList.value = [...teamList.value, ...newData];
      currentPage.value += 1;
    } else {
      finished.value = true;
    }

    loading.value = false;
  }, 1000);
};

const handleApply = (team, index) => {
  console.log('Apply to join team:', team, index);
};

// Generate mock data
const generateTeamData = (page, size) => {
  const data = [];
  const start = page * size;
  const end = start + size;

  for (let i = start; i < end && i < 50; i++) {
    data.push({
      id: `team-${i}`,
      name: `Team ${i + 1}`,
      logo: `https://example.com/logo${i}.png`,
      avatars: [
        `https://example.com/avatar${i}-1.png`,
        `https://example.com/avatar${i}-2.png`,
      ],
      currentMembers: Math.floor(Math.random() * 5) + 1,
      maxMembers: 5,
      tagItems: [
        { text: 'Popular', type: 'primary' },
      ],
    });
  }

  return data;
};
</script>

# Simple Mode

Hide member avatar list and action button.

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    :loading="loading"
    :finished="finished"
    item-type="simple"
    @load-more="loadMore"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';

const teamList = ref([
  {
    id: '1',
    name: 'Honor of Kings Team',
    logo: 'https://example.com/logo.png',
    currentMembers: 3,
    maxMembers: 5,
    tagItems: [
      { text: 'Popular', type: 'primary' },
    ],
  },
]);

const loading = ref(false);
const finished = ref(false);

const loadMore = () => {
  console.log('Load more');
};
</script>

# Custom Empty State

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    :loading="loading"
    :finished="finished"
    empty-text="No team information available"
    finish-text="All teams loaded"
    @load-more="loadMore"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';

const teamList = ref([]);
const loading = ref(false);
const finished = ref(false);

const loadMore = () => {
  console.log('Load more');
};
</script>

# Custom Tags

You can set tags for each team individually or set default tags for all teams.

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    :tag-items="defaultTags"
    :loading="loading"
    :finished="finished"
    @load-more="loadMore"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';

const defaultTags = ref([
  { text: 'Recommended', type: 'primary' },
]);

const teamList = ref([
  {
    id: '1',
    name: 'Honor of Kings Team',
    logo: 'https://example.com/logo.png',
    avatars: ['https://example.com/avatar1.png'],
    currentMembers: 3,
    maxMembers: 5,
    // Individual tags override default tags
    tagItems: [
      { text: 'Popular', type: 'primary' },
      { text: '3', type: 'quantity' },
    ],
  },
  {
    id: '2',
    name: 'PUBG Team',
    logo: 'https://example.com/logo2.png',
    avatars: ['https://example.com/avatar2.png'],
    currentMembers: 2,
    maxMembers: 5,
    // Uses default tags if not set
  },
]);

const loading = ref(false);
const finished = ref(false);

const loadMore = () => {
  console.log('Load more');
};
</script>

# API

# Props

Attribute Description Type Default
team-list Team list data TeamInfo[] []
tag-items Default tag list TagItem[] []
item-type List item display type 'with-avatars' | 'simple' 'with-avatars'
action-text Action button text string '申请加入'
custom-class Custom CSS class name string ''
empty-text Empty state text string '暂无队伍信息'
image Empty state image string -
finish-text Finish loading text string '没有更多了'
loading Whether data is loading boolean false
finished Whether all data is loaded boolean false

# TeamInfo Data Structure

interface TeamInfo {
  id: string;
  name: string;
  logo: string;
  avatars?: string[];
  currentMembers: number;
  maxMembers: number;
  tagItems?: TagItem[];
}
Property Description Type Required
id Team ID string Yes
name Team name string Yes
logo Team logo URL string Yes
avatars Member avatar list string[] No
currentMembers Current member count number Yes
maxMembers Maximum member count number Yes
tagItems Team tag list, overrides default tags TagItem[] No

# TagItem Data Structure

interface TagItem {
  text: string;
  type?: 'default' | 'quantity';
}
Property Description Type Default
text Tag text string -
type Tag type, quantity type shows user icon 'default' | 'quantity' 'default'

# Events

Event Description Callback Parameters
load-more Triggered when scrolled to bottom -
apply Triggered when apply button is clicked team: TeamInfo, index: number

# Theme Customization

# CSS Variables

The component provides the following CSS variables for custom styling.

# Spacing System

Name Default Description
--til-list-gap 0 List item gap
--til-list-item-border-offset $spacing-lg List item border offset

# Color System

Name Default Description
--til-bg-color transparent List background color
--til-list-item-border-color $color-divider-light List item border color

# Custom Style Example

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    class="custom-team-list"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';

const teamList = ref([
  {
    id: '1',
    name: 'Honor of Kings Team',
    logo: 'https://example.com/logo.png',
    avatars: ['https://example.com/avatar1.png'],
    currentMembers: 3,
    maxMembers: 5,
  },
]);
</script>

<style scoped lang="scss">
.custom-team-list {
  --til-bg-color: #f5f5f5;
  --til-list-gap: 16px;
  --til-list-item-border-color: #e0e0e0;
}
</style>

# Notes

  1. Component Dependencies:

    • Uses PressMatchTeamInfoItem component from press-next
    • Uses PressList and PressEmpty components from press-ui
    • Ensure all dependencies are properly installed
  2. Data Loading:

    • The component doesn't handle data fetching logic itself
    • Implement data loading in the parent component through the load-more event
    • Recommend paginated loading for large datasets to avoid rendering too much content at once
  3. State Management:

    • Properly manage loading and finished states in the parent component
    • Set loading: true when loading starts, loading: false when complete
    • Set finished: true when no more data is available
  4. Tag Priority:

    • tagItems in team data overrides the component's tag-items prop
    • If team data doesn't have tagItems, default tags are used
  5. Display Modes:

    • with-avatars mode: Shows member avatar list and action button
    • simple mode: Hides avatar list and action button

# FAQ

# How to implement pull-to-refresh?

Use with press-ui's pull-refresh component:

<template>
  <PressPullRefresh
    v-model="refreshing"
    @refresh="onRefresh"
  >
    <PressMatchTeamInfoList
      :team-list="teamList"
      :loading="loading"
      :finished="finished"
      @load-more="loadMore"
    />
  </PressPullRefresh>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchTeamInfoList from 'press-next/press-match-team-info-list/press-match-team-info-list.vue';
import PressPullRefresh from 'press-ui/press-pull-refresh/press-pull-refresh.vue';

const teamList = ref([]);
const loading = ref(false);
const finished = ref(false);
const refreshing = ref(false);

const onRefresh = async () => {
  // Reset state
  teamList.value = [];
  finished.value = false;

  // Reload data
  await loadMore();
  refreshing.value = false;
};

const loadMore = async () => {
  loading.value = true;
  // Data loading logic
  loading.value = false;
};
</script>

# How to customize team item styles?

The component uses PressMatchTeamInfoItem internally to render each team item. Customize using CSS variables:

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    class="custom-list"
  />
</template>

<style scoped lang="scss">
.custom-list {
  // Customize list styles
  --til-list-gap: 16px;

  // Customize team item styles
  --pmtii-container-bg: #f5f5f5;
  --pmtii-name-text-color: #1890ff;
}
</style>

# LoadingPlus state display issues?

Check your loading and finished state management logic:

<script setup lang="ts">
const loading = ref(false);
const finished = ref(false);

const loadMore = async () => {
  // Prevent duplicate loading
  if (loading.value || finished.value) return;

  loading.value = true;

  try {
    const newData = await fetchTeamData();

    if (newData.length > 0) {
      teamList.value = [...teamList.value, ...newData];
    } else {
      // No more data
      finished.value = true;
    }
  } catch (error) {
    console.error('Loading failed:', error);
  } finally {
    // Ensure loading state is reset
    loading.value = false;
  }
};
</script>

# How to handle apply logic?

Listen to the apply event and handle the logic in the callback:

<template>
  <PressMatchTeamInfoList
    :team-list="teamList"
    @apply="handleApply"
  />
</template>

<script setup lang="ts">
const handleApply = async (team, index) => {
  try {
    // Call apply API
    await applyToJoinTeam(team.id);
    console.log('Application successful');

    // Update list state
    teamList.value[index].isApplied = true;
  } catch (error) {
    console.error('Application failed:', error);
  }
};
</script>