# MatchUserItem

User item component for displaying user information and action buttons. Supports flexible button configuration and custom operations, suitable for team management, friend requests, member review and other scenarios.

# Features

  • πŸ‘€ User Information Display - Support avatar, nickname, tags, description and other information display
  • 🏷️ Multiple Tags Support - Support displaying multiple tags with automatic line wrapping
  • 🎯 Flexible Configuration - Define operation buttons freely through button configuration array, no hardcoded business states
  • 🎨 Theme Customization - Rich CSS variables for theme customization, support button types, sizes, and plain mode
  • πŸ”§ Slot Support - Support custom slots for each button
  • ⚑ Lightweight & Efficient - Optimized code structure with excellent performance

# Use Cases

  • Team member management
  • Friend request review
  • User list display
  • Member invitation function
  • Any scenario that requires user information + operation buttons

# Import

import PressMatchUserItem from 'press-next/press-match-user-item/press-match-user-item';

# Code Demo

# Basic Usage

<template>
  <PressMatchUserItem
    :user-info="userInfo"
    :buttons="buttons"
    @button-click="handleButtonClick"
    @image-error="handleImageError"
  />
</template>

<script setup lang="ts">
import PressMatchUserItem from 'press-next/press-match-user-item/press-match-user-item.vue';

// User information
const userInfo = {
  avatar: 'https://img.yzcdn.cn/vant/cat.jpeg',
  name: 'Zhang San',
  tags: [
    { icon: 'https://example.com/icon1.png', name: 'Honor of Kings' },
    { icon: 'https://example.com/icon2.png', name: 'PUBG Mobile' }
  ],
  description: 'Good at jungle position, King rank',
  id: '001'
};

// Button configuration
const buttons = [
  {
    key: 'ignore',
    text: 'Ignore',
    type: 'default',
    plain: false,
    size: 'normal',
  },
  {
    key: 'pass',
    text: 'Pass',
    type: 'primary',
    plain: false,
    size: 'normal',
  },
];

// Unified button click handling
const handleButtonClick = (button, userInfo) => {
  console.log('Button clicked:', button.key, 'User:', userInfo);
  
  // Execute different logic based on button key
  if (button.key === 'ignore') {
    console.log('Ignore user');
  } else if (button.key === 'pass') {
    console.log('Pass user');
  }
};

const handleImageError = (userInfo) => {
  console.log('Image load failed:', userInfo);
};
</script>

# Button Configuration for Different Scenarios

<template>
  <div class="user-list">
    <!-- Pending scenario -->
    <PressMatchUserItem
      :user-info="pendingUser"
      :buttons="pendingButtons"
      @button-click="handleButtonClick"
    />
    
    <!-- Passed scenario -->
    <PressMatchUserItem
      :user-info="passedUser"
      :buttons="passedButtons"
      @button-click="handleButtonClick"
    />
    
    <!-- Team management scenario -->
    <PressMatchUserItem
      :user-info="manageUser"
      :buttons="manageButtons"
      @button-click="handleButtonClick"
    />
  </div>
</template>

<script setup lang="ts">
// Pending scenario buttons
const pendingButtons = [
  { key: 'ignore', text: 'Ignore', type: 'default' },
  { key: 'pass', text: 'Pass', type: 'primary' }
];

// Passed scenario buttons
const passedButtons = [
  { key: 'passed', text: 'Passed', type: 'default', disabled: true }
];

// Team management scenario buttons
const manageButtons = [
  { key: 'transfer', text: 'Transfer Captain', type: 'default' },
  { key: 'kick', text: 'Kick Out', type: 'danger' }
];

const handleButtonClick = (button, userInfo) => {
  console.log(`Execute operation: ${button.key}, User: ${userInfo.name}`);
};
</script>

# Use Slots to Customize Buttons

<template>
  <PressMatchUserItem
    :user-info="userInfo"
    :buttons="buttons"
    @button-click="handleButtonClick"
  >
    <!-- Custom pass button -->
    <template #pass-btn>
      <button class="custom-btn" @click="handleCustomPass">
        βœ“ Approve Join
      </button>
    </template>
    
    <!-- Custom ignore button -->
    <template #ignore-btn>
      <button class="custom-btn-secondary" @click="handleCustomIgnore">
        βœ— Reject
      </button>
    </template>
  </PressMatchUserItem>
</template>

<script setup lang="ts">
const handleCustomPass = () => {
  console.log('Custom approve logic');
};

const handleCustomIgnore = () => {
  console.log('Custom reject logic');
};
</script>

<style scoped>
.custom-btn {
  padding: 8px 16px;
  background: #52c41a;
  color: white;
  border: none;
  border-radius: 4px;
}

.custom-btn-secondary {
  padding: 8px 16px;
  background: #f5f5f5;
  color: #666;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
}
</style>

# Custom Theme

<template>
  <PressMatchUserItem
    custom-class="my-custom-theme"
    :user-info="userInfo"
    :buttons="buttons"
  />
</template>

<style>
.my-custom-theme {
  /* Card styles */
  --pmui-user-item-bg: #f5f5f5;
  --pmui-user-item-padding: 0.32rem;
  
  /* Avatar styles */
  --pmui-avatar-wrapper-size: 1rem;
  
  /* Tag styles */
  --pmui-user-tag-bg: rgba(255, 107, 0, 0.1);
  --pmui-tag-label-color: #ff6b00;
  
  /* Button styles */
  --pmui-btn-radius: 0.4rem;
}
</style>

# API

# Props

Parameter Description Type Default
user-info User information UserInfo -
buttons Button configuration list ButtonConfig[] []
custom-class Custom CSS class string ''

# UserInfo Data Structure

// Tag interface
interface Tag {
  icon?: string; // Tag icon (optional)
  name: string; // Tag name
}

// User information interface
interface UserInfo {
  avatar?: string; // User avatar (optional)
  name: string; // User name
  tags?: Tag[]; // Tags list (optional)
  description?: string; // User description (optional)
  id?: string; // User ID (optional)
}

# ButtonConfig Data Structure

interface ButtonConfig {
  key: string; // Button unique identifier, used for slot names and event identification
  text: string; // Button text
  type?: ButtonType; // Button type
  plain?: boolean; // Whether plain button
  size?: ButtonSize; // Button size
  openType?: string; // WeChat Mini Program open capability
  disabled?: boolean; // Whether disabled
}

type ButtonType = 'primary' | 'default' | 'info' | 'warning' | 'danger';
type ButtonSize = 'normal' | 'large' | 'small' | 'mini';

# Slots

Name Description
${button.key}-btn Custom button, key is the key value in button configuration

Slot naming rule: Button's key value + -btn suffix

Example:

  • Button key is 'pass' β†’ Slot name is 'pass-btn'
  • Button key is 'ignore' β†’ Slot name is 'ignore-btn'

# Events

Event Description Parameters
button-click Button clicked (button: ButtonConfig, userInfo: UserInfo)
image-error Avatar image loading failed (userInfo: UserInfo)

# Notes

# Usage Recommendations

  1. Button Configuration: Configure buttons flexibly through buttons array, each button must have a unique key value
  2. Tags: tags is an array type, supports displaying multiple tags, tags will automatically wrap when there are too many. The icon field of tags is optional, if not passed, only text will be displayed
  3. Avatar: The avatar field is optional, if not passed, the avatar area will not be displayed
  4. Event Handling: Use unified button-click event, distinguish operations by button.key
  5. Description Information: The description field is optional and is used to display additional user information

# Design Philosophy

This component uses configuration-driven design philosophy:

  • No Hardcoded Business States: No status attribute, no preset "pending", "passed" and other states
  • Display What's Configured: Define buttons to display freely through buttons array
  • Flexible Extension: Can add, delete, or modify button configurations at any time without modifying component code
  • Unified Event Handling: All button clicks trigger button-click event, simplifying event management

# Performance Optimization

  • Use v-memo directive to optimize list rendering
  • Consider virtual scrolling for large numbers of users
  • Avatar images are recommended to use CDN acceleration

# Compatibility

  • Supports Vue 3.0+
  • Compatible with modern browsers (Chrome 60+, Firefox 60+, Safari 12+)
  • Supports WeChat Mini Program, Alipay Mini Program and other platforms

# Theme Customization

# Style Variables

The component provides the following CSS variables for custom styling. Please refer to the ConfigProvider component for usage.

# Spacing System

Name Default Description
--pmui-user-item-padding $spacing-md User item padding
--pmui-avatar-wrapper-margin 0 $spacing-lg 0 0 Avatar wrapper margin
--pmui-user-tag-margin-top 0.06rem Tag container margin top
--pmui-user-tag-gap 0.16rem Gap between tags
--pmui-user-tag-padding 0.04rem 0.16rem Single tag padding
--pmui-tag-icon-margin-right 0.04rem Tag icon margin right
--pmui-operation-gap 0.14rem Operation buttons gap
--pmui-desc-margin-top 0.24rem Description margin top
--pmui-desc-padding 0.16rem 0.24rem Description padding

# Box Model System

Name Default Description
--pmui-avatar-wrapper-size 0.8rem Avatar wrapper size
--pmui-avatar-image-size 100% Avatar image size
--pmui-content-flex 1 Content area flex
--pmui-content-info-width 100% Content info width
--pmui-user-name-max-width 2.4rem User name max width
--pmui-tag-icon-size 0.28rem Tag icon size
--pmui-tag-label-max-width 2rem Tag label max width
--pmui-btn-width 1.28rem Button width
--pmui-btn-min-width 1.2rem Button min width
--pmui-btn-height 0.5rem Button height
--pmui-desc-width 100% Description width

# Color System

Name Default Description
--pmui-user-item-bg $color-surface-default User item background
--pmui-user-tag-bg $color-divider-light Tag background
--pmui-desc-bg $color-surface-secondary Description background
--pmui-user-name-color $color-text-primary User name color
--pmui-tag-label-color $color-text-secondary Tag label color
--pmui-desc-color $color-text-invert-dark Description text color

# Typography System

Name Default Description
--pmui-user-name-font-size $font-size-md User name font size
--pmui-user-name-font-weight $font-weight-bold User name font weight
--pmui-user-name-line-height 1.5 User name line height
--pmui-tag-label-font-size $font-size-xs Tag label font size
--pmui-tag-label-font-weight $font-weight-regular Tag label font weight
--pmui-tag-label-line-height 1.5 Tag label line height
--pmui-btn-font-size $font-size-sm Button font size
--pmui-btn-font-weight $font-weight-bold Button font weight
--pmui-btn-line-height 1.5 Button line height
--pmui-desc-font-size $font-size-xs Description font size
--pmui-desc-font-weight $font-weight-regular Description font weight
--pmui-desc-line-height 1.5 Description line height

# Border Radius System

Name Default Description
--pmui-avatar-image-radius 50% Avatar border radius
--pmui-btn-radius $border-radius-999 Button border radius

# Border System

Name Default Description
--pmui-user-item-border-bottom 1px solid $color-divider-light User item bottom border

# Others

Name Default Description
--pmui-user-item-position relative User item position
--pmui-avatar-wrapper-position relative Avatar wrapper position
--pmui-avatar-image-fit cover Avatar image fit