挑战用React封装100个组件【006】

项目地址
https://github.com/hismeyy/react-component-100

组件描述

组件适用于展示个人信息,别人还可以关注,发消息操作

样式展示

前置依赖

今天我们的这个挑战需要用用到了 react-icons 依赖,因此,我们需要先安装它。

cmd 复制代码
# 使用 npm
npm install react-icons

# 或者使用 yarn
yarn add react-icons

使用的话,大家可以看这个网站。大家进去可以找需要的图标。具体使用里面有介绍,非常简单。
react-icons 图标

好了,下面我们展示代码。(如果对你有用,记得点个收藏或者关注哦!)

代码展示

InfoCard.tsx
js 复制代码
import './InfoCard.css'
import { FaStar } from 'react-icons/fa';

interface InfoCardProps {
    avatarUrl: string;
    avatarAlt: string;
    name: string;
    description: string;
    labels: string[];
    isVerified?: boolean;
    onFollow?: () => void;
    onMessage?: () => void;
}

const InfoCard = ({ 
    avatarUrl, 
    avatarAlt, 
    name, 
    description, 
    labels, 
    isVerified = false,
    onFollow,
    onMessage 
}: InfoCardProps) => {
    const displayLabels = labels.slice(0, 6);

    return (
        <div className='info-card'>
            <div className="info">
                <div className='info-avatar'>
                    <div className='tip-logo'>
                        {isVerified ? <FaStar /> : null}
                    </div>

                    <div className='avatar'>
                        <img src={avatarUrl} alt={avatarAlt} />
                    </div>
                </div>
                <div className='about-me'>
                    <h6>{name}</h6>
                    <p>{description}</p>
                </div>
            </div>
            <div className='labels'>
                {displayLabels.map((label, index) => (
                    <div key={index} className='label'>{label}</div>
                ))}
            </div>
            <div className='buttons'>
                <button onClick={onFollow}>关注</button>
                <button onClick={onMessage}>发消息</button>
            </div>
        </div>
    )
}

export default InfoCard
InfoCard.css
js 复制代码
.info-card {
    box-sizing: border-box;
    width: 430px;
    height: 200px;
    border-radius: 25px;
    padding: 25px;
    background-color: #F5F5F5;
    border: 1px solid #b9b9b9;
    display: flex;
    justify-content: left;
    flex-direction: column;

}

.info-card .info {
    display: flex;

}


.info-card .info .info-avatar {
    height: 60px;
    position: relative;

}

.info-card .info .info-avatar .avatar {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    overflow: hidden;
    border: 1px solid #b9b9b9;
}

.info-card .info .info-avatar .avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.info-card .info .info-avatar .tip-logo {
    position: absolute;
    bottom: 2px;
    right: -4px;
    width: 20px;
    height: 20px;
    background-color: #FA7D73;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 50%;
    color: #fff;
    font-size: 14px;
    z-index: 1;
}

.info-card .info .about-me {
    margin-left: 20px;
    height: 60px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 10px;
}

.info-card .info .about-me h6 {
    all: unset;
    display: block;
    font-size: 16px;
    font-weight: bold;
}

.info-card .info .about-me p {
    all: unset;
    display: block;
    color: #696969;
    font-size: 14px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 300px;
}


.info-card .labels {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 20px;
    font-size: 10px;
    color: #5c5c5c;
}

.info-card .labels .label {
    background-color: #e2e2e2;
    padding: 2px 5px;
    border-radius: 20px;
    cursor: pointer;
}

.info-card .buttons {
    margin-top: 20px;
    display: flex;
    justify-content: center;
    gap: 20px;
}

.info-card .buttons button {
    all: unset;
    padding: 5px 10px;
    border-radius: 20px;
    cursor: pointer;
    font-size: 12px;
    width: 50px;
    height: 20px;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.info-card .buttons button:hover {
    transform: translateY(-2px);
    opacity: 0.8;
}

.info-card .buttons button:first-child {
    background-color: #FA7D73;
    color: #fff;
}

.info-card .buttons button:last-child {
    background-color: rgb(101, 124, 224);
    color: #fff;
}

使用

App.tsx
js 复制代码
import './App.css'
import InfoCard from './components/card/infoCard04/InfoCard';

function App() {
  const handleFollow = () => {
    console.log('关注成功');
    
  };

  const handleMessage = () => {
    console.log('打开消息框');
    
  };

  return (
    <>
      <div className="App">
        <InfoCard
          avatarUrl="https://p7.itc.cn/q_70/images03/20230309/bc24a67a4dea4ae38296967a4f8ecea5.png"
          avatarAlt="MaxCosmos Avatar"
          name="MaxCosmos"
          description="前端开发工程师 | React开发者 | 热衷于打造优秀的用户体验和高性能web应用"
          labels={["React", "Next.js", "TypeScript", "UI/UX", "Tailwind", "Node.js"]}
          isVerified={true}
          onFollow={handleFollow}
          onMessage={handleMessage}
        />
      </div>
    </>
  );
}

export default App
相关推荐
加班是不可能的,除非双倍日工资4 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi4 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip5 小时前
vite和webpack打包结构控制
前端·javascript
excel5 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国5 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼5 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy5 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT6 小时前
promise & async await总结
前端
Jerry说前后端6 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天6 小时前
A12预装app
linux·服务器·前端