react19【系列实用教程】实用组件封装

必要的全局样式

src/index.css

c 复制代码
@import "tailwindcss";
/* 当根元素有 class="dark" 时 → 激活 dark: 样式,用于在页面上切换主题为暗黑模式 */
@custom-variant dark (&:where(.dark, .dark *));

@theme {
  /* 主配色 */
  --color-apple-light: #f5f5f7;
  --color-apple-dark: #1d1d1f;
  /* 标准色 */
  --color-apple-black: #000000;
  --color-apple-white: #ffffff;
  /* 品牌配色 */
  --color-apple-blue: #0071e3;
  --color-apple-red: #b64400;
  /* 灰阶系统(Gray Scale) */
  --color-apple-gray-100: #f5f5f7;
  --color-apple-gray-200: #d2d2d7;
  --color-apple-gray-300: #86868b;
  --color-apple-gray-800: #424245;
  --color-apple-gray-900: #1d1d1f;
  /* 字体 */
  --font-sans: "Inter", "Roboto", "Open Sans", "Helvetica Neue", sans-serif;
  --font-display: "Poppins", "Inter", "sans-serif";
  --font-text: "Source Sans Pro", "Open Sans", "sans-serif";
  /* 文字颜色*/
  --color-apple-text-light: #1d1d1f;
  --color-apple-text-dark: #f5f5f7;
  /* 阴影 */
  --shadow-apple-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
  --shadow-apple-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-apple-lg: 0 8px 24px rgba(0, 0, 0, 0.06);
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--color-apple-text-light);
  background-color: var(--color-apple-light);
}

按钮

src/components/Button.tsx

c 复制代码
export interface ButtonProps {
  title?: React.ReactNode;
  variant?: "primary" | "outline";
  disabled?: boolean;
  onClick?: () => void;
}

const Button = ({
  title,
  variant = "primary",
  disabled = false,
  onClick,
}: ButtonProps) => {
  let className = `px-5 py-2 rounded-md border
                   transition-colors duration-200
                   inline-flex items-center justify-center gap-2`;
  if (variant === "primary") {
    className +=
      " bg-apple-blue text-white border-apple-blue hover:bg-apple-blue/90";
  } else if (variant === "outline") {
    className +=
      " bg-transparent text-apple-blue border-apple-blue hover:bg-apple-blue hover:text-white";
  }

  if (disabled) {
    className += " opacity-50 cursor-not-allowed pointer-events-none";
  }

  return (
    <button className={className} disabled={disabled} onClick={onClick}>
      {title}
    </button>
  );
};

export default Button;

使用

c 复制代码
<Button title="购买" variant="outline" />

图标按钮

src/components/IconButton.tsx

c 复制代码
import Button, { type ButtonProps } from "./Button.tsx";

export interface IconButtonProps extends ButtonProps {
  icon: React.ReactNode;
  ioconPosition?: "left" | "right";
}

const IconButton = ({
  icon,
  ioconPosition = "left",
  title,
  ...rest
}: IconButtonProps) => {
  return (
    <Button
      title={
        <span className="flex items-center gap-2">
          {ioconPosition === "left" && icon}
          <span>{title}</span>
          {ioconPosition === "right" && icon}
        </span>
      }
      {...rest}
    />
  );
};

export default IconButton;

使用

c 复制代码
import IconButton from "./IconButton.tsx";
import { MdOutlineNavigateNext } from "react-icons/md";
c 复制代码
          <IconButton
            icon={<MdOutlineNavigateNext />}
            ioconPosition="right"
            title="进一步了解"
            variant="primary"
          />
相关推荐
quantdash_cc几秒前
如何检查滚动收益率计算中的窗口长度不足?——从数学定义到 Pandas 实现
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
陈随易3 分钟前
副业搞钱点子之赛事与活动
前端·后端·程序员
电梯界知识分子5 分钟前
景德镇老房重新设计阶段规划楼梯与电梯,1.7m×1.6m空间装400kg观光电梯,棕色框架茶色玻璃适配中式装修
大数据·服务器·前端·网络·家用电梯
Shell运维手记15 分钟前
Shell 脚本入门课堂讲解
前端·chrome
衍生星球17 分钟前
【Java 语言】— 方法(方法定义、调用、参数、返回值、方法重载)
java·开发语言·方法
Profile排查笔记18 分钟前
有哪些开源指纹浏览器项目?先核对客户端、内核与许可证
前端·人工智能·后端·自动化
CodeGL23 分钟前
16、Python Web开发
开发语言·前端·python
喵了几个咪25 分钟前
GoWind UBA 拆解:把 Doris UNIQUE KEY 翻译成 ClickHouse——读数正确性对齐实录
开发语言·后端·clickhouse·微服务·golang·gowind
FRing0330 分钟前
JavaScript入门到精通二十九(内置构造函数(Object、Array))
开发语言·前端·javascript
syagain_zsx33 分钟前
ODB 与 MySQL:C++ 里的 ORM 实践(类即表、事务铁律与查询封装)
开发语言·数据库·c++·mysql·工具库·1024程序员节