TypeScript 使用 UnoCSS 的复杂案例:构建一个可定制的数据表格组件

Claude 3.5 的例子 您说得对,我们可以创建一个更复杂的示例来充分展示 Bun 环境下使用 UnoCSS 的特点。让我们构建一个更高级的应用,它将包含动态主题切换、自定义动画、响应式设计,以及与 Bun 的特性结合使用。

高级 Bun + UnoCSS 示例:构建一个交互式仪表板

这个示例将创建一个交互式仪表板,包含以下特性:

  1. 动态主题切换(明/暗模式)
  2. 自定义动画
  3. 响应式设计
  4. 实时数据更新(使用 Bun 的内置 WebSocket)
  5. 服务端渲染(SSR)与 Bun 的性能优化

步骤 1: 项目设置

bun init dashboard-app
cd dashboard-app
bun add unocss @unocss/preset-uno @unocss/preset-wind @unocss/preset-attributify @unocss/preset-icons @unocss/preset-mini react react-dom

步骤 2: UnoCSS 配置

创建 uno.config.ts:

import { defineConfig, presetUno, presetWind, presetAttributify, presetIcons, presetMini } from 'unocss'
 
export default defineConfig({
  presets: [
    presetUno(),
    presetWind(),
    presetAttributify(),
    presetIcons(),
    presetMini(),
  ],
  theme: {
    colors: {
      primary: {
        light: '#60a5fa',
        DEFAULT: '#3b82f6',
        dark: '#2563eb',
      },
    },
  },
  shortcuts: {
    'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md transition duration-300 ease-in-out transform hover:scale-105',
    'btn-primary': 'btn bg-primary text-white hover:bg-primary-dark',
    'card': 'bg-white dark:bg-gray-800 rounded-lg shadow-md p-6',
  },
  rules: [
    ['custom-animation', { animation: 'custom 1s ease-in-out infinite' }],
  ],
})

步骤 3: 创建组件

  1. 创建 src/components/ThemeToggle.tsx:
import React from 'react'
 
export const ThemeToggle = () => {
  const toggleTheme = () => {
    document.documentElement.classList.toggle('dark')
  }
 
  return (
    <button onClick={toggleTheme} className="btn-primary">
      Toggle Theme
    </button>
  )
}
  1. 创建 src/components/Dashboard.tsx:
import React, { useState, useEffect } from 'react'
import { ThemeToggle } from './ThemeToggle'
 
interface DashboardData {
  users: number
  revenue: number
  orders: number
}
 
export const Dashboard = () => {
  const [data, setData] = useState<DashboardData>({ users: 0, revenue: 0, orders: 0 })
 
  useEffect(() => {
    const ws = new WebSocket('ws://localhost:3000')
    ws.onmessage = (event) => {
      setData(JSON.parse(event.data))
    }
    return () => ws.close()
  }, [])
 
  return (
    <div className="min-h-screen bg-gray-100 dark:bg-gray-900 transition-colors duration-500">
      <div className="container mx-auto px-4 py-8">
        <div className="flex justify-between items-center mb-8">
          <h1 className="text-4xl font-bold text-gray-800 dark:text-white">Dashboard</h1>
          <ThemeToggle />
        </div>
        <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
          <div className="card custom-animation">
            <h2 className="text-2xl font-semibold mb-2">Users</h2>
            <p className="text-4xl font-bold text-primary">{data.users}</p>
          </div>
          <div className="card custom-animation">
            <h2 className="text-2xl font-semibold mb-2">Revenue</h2>
            <p className="text-4xl font-bold text-primary">${data.revenue}</p>
          </div>
          <div className="card custom-animation">
            <h2 className="text-2xl font-semibold mb-2">Orders</h2>
            <p className="text-4xl font-bold text-primary">{data.orders}</p>
          </div>
        </div>
      </div>
    </div>
  )
}

步骤 4: 创建服务器

创建 src/server.ts:

import { serve } from 'bun'
import { renderToString } from 'react-dom/server'
import { Dashboard } from './components/Dashboard'
 
const dashboardHtml = renderToString(<Dashboard />)
 
const server = serve({
  port: 3000,
  fetch(req) {
    if (req.url.endsWith('/ws')) {
      const upgraded = server.upgrade(req)
      if (upgraded) {
        setInterval(() => {
          upgraded.send(JSON.stringify({
            users: Math.floor(Math.random() * 1000),
            revenue: Math.floor(Math.random() * 10000),
            orders: Math.floor(Math.random() * 100)
          }))
        }, 1000)
        return
      }
    }
 
    return new Response(
      `<!DOCTYPE html>
      <html>
        <head>
          <title>Dashboard</title>
          <script src="https://unpkg.com/unocss"></script>
          <script type="module">
            import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
            import { Dashboard } from './components/Dashboard.tsx'
            createApp(Dashboard).mount('#app')
          </script>
        </head>
        <body>
          <div id="app">${dashboardHtml}</div>
        </body>
      </html>`,
      {
        headers: {
          'Content-Type': 'text/html',
        },
      }
    )
  },
})
 
console.log(`Server running at http://localhost:${server.port}`)

步骤 5: 运行应用

bun run src/server.ts

解释

  1. 动态主题切换:使用 UnoCSS 的 dark: 变体和 CSS 变量实现明暗主题切换。

  2. 自定义动画:在 UnoCSS 配置中定义了自定义动画规则 custom-animation

  3. 响应式设计:使用 UnoCSS 的响应式工具类(如 md:grid-cols-3)实现响应式布局。

  4. 实时数据更新:利用 Bun 的内置 WebSocket 功能实现实时数据更新。

  5. 服务端渲染(SSR):使用 Bun 的 renderToString 函数实现服务端渲染,提高首屏加载速度。

  6. 性能优化:Bun 的高性能特性自然地应用于整个应用程序,包括快速的 JavaScript 执行和高效的文件系统操作。

这个复杂的例子展示了如何在 Bun 环境中充分利用 UnoCSS 的强大功能,同时结合 Bun 的特性来创建一个高性能、实时更新的交互式仪表板。它涵盖了现代 web 应用开发中的多个方面,包括样式、交互、实时数据和服务端渲染。


Perplexity 例子

要在 Bun 环境下使用 UnoCSS,以下是一个复杂的实例,展示如何利用 Bun 的性能优势和 UnoCSS 的灵活性来构建一个功能齐全的 Web 应用程序。

步骤 1: 初始化项目

  1. 安装 Bun

    curl -fsSL https://bun.sh/install | bash
  2. 创建新项目

    bun init my-unocss-app
    cd my-unocss-app
  3. 安装依赖

    bun add react react-dom @unocss/preset-uno @unocss/preset-attributify @unocss/preset-icons unocss

步骤 2: 配置 UnoCSS

  1. 创建 UnoCSS 配置文件
    // uno.config.ts
    import { defineConfig, presetAttributify, presetIcons, presetUno } from 'unocss'
     
    export default defineConfig({
      presets: [
        presetUno(),
        presetAttributify(),
        presetIcons({
          scale: 1.2,
        }),
      ],
      theme: {
        colors: {
          primary: '#3b82f6',
          secondary: '#6b7280',
        },
      },
      rules: [
        ['m-1', { margin: '1px' }],
        ['m-2', { margin: '2px' }],
        ['text-lg', { fontSize: '18px' }],
        // 添加更多自定义规则根据需要
      ],
      shortcuts: [
        ['btn', 'px-4 py-2 rounded-md bg-blue-500 text-white cursor-pointer'],
        ['btn-blue', 'btn bg-blue-500 hover:bg-blue-700'],
        ['btn-red', 'btn bg-red-500 hover:bg-red-700'],
      ],
    })

步骤 3: 创建 React 应用

  1. 安装 React

    bun add react react-dom
  2. 创建组件

    // src/components/Navbar.tsx
    import React from 'react'
     
    export const Navbar = () => {
      return (
        <nav className="bg-primary p-4 text-white">
          <h1 className="text-3xl">My App</h1>
        </nav>
      )
    }
  3. 创建主页组件

    // src/components/Home.tsx
    import React from 'react'
    import { Button } from './Button'
     
    export const Home = () => {
      return (
        <div className="container mx-auto p-4">
          <h1 className="text-5xl mb-4">Welcome to My App</h1>
          <Button variant="blue" onClick={() => alert('Blue button clicked')}>
            Blue Button
          </Button>
          <Button variant="red" className="mt-4" onClick={() => alert('Red button clicked')}>
            Red Button
          </Button>
        </div>
      )
    }
  4. 创建按钮组件

    // src/components/Button.tsx
    import React from 'react'
     
    export const Button = ({ children, variant = 'blue', ...props }: { children: React.ReactNode; variant?: 'blue' | 'red' }) => {
      return (
        <button
          className={`btn-${variant} ${props.className || ''}`}
          {...props}
        >
          {children}
        </button>
      )
    }

步骤 4: 使用 UnoCSS 和 React

  1. 创建应用入口

    // src/App.tsx
    import React from 'react'
    import { Navbar } from './components/Navbar'
    import { Home } from './components/Home'
     
    const App = () => {
      return (
        <div>
          <Navbar />
          <Home />
        </div>
      )
    }
     
    export default App
  2. 创建主入口文件

    // src/index.tsx
    import React from 'react'
    import ReactDOM from 'react-dom'
    import App from './App'
     
    ReactDOM.render(<App />, document.getElementById('root'))

步骤 5: 运行应用

  1. 创建 HTML 文件

    <!-- public/index.html -->
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My App</title>
      </head>
      <body>
        <div id="root"></div>
        <script type="module" src="/src/index.tsx"></script>
      </body>
    </html>
  2. 配置 Bun 运行环境

    // package.json
    {
      "name": "my-unocss-app",
      "version": "0.1.0",
      "scripts": {
        "dev": "bun run dev",
        "build": "bun build",
        "start": "bun start"
      },
      "dependencies": {
        "@unocss/preset-attributify": "^0.0.5",
        "@unocss/preset-icons": "^0.0.5",
        "@unocss/preset-uno": "^0.0.5",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "unocss": "^0.19.4"
      }
    }
  3. 运行开发服务器

    bun run dev

解释

  • UnoCSS 配置:在 uno.config.ts 中定义了 UnoCSS 的预设和自定义规则,包括颜色主题、边距、字体大小等。
  • React 组件:创建了多个 React 组件,例如 NavbarHomeButton,并使用 UnoCSS 的类名来样式化这些组件。
  • Bun 环境:利用 Bun 的性能优势快速运行和构建 React 应用,包括热重载和开发服务器支持。

这个示例展示了如何在 Bun 环境下使用 UnoCSS 来构建一个功能齐全的 Web 应用程序,利用 UnoCSS 的灵活性和可扩展性来管理样式,并利用 Bun 的高性能来加速开发和运行过程。


这个案例将会展示如何使用 UnoCSS 和 TypeScript 构建一个具有以下特性的可定制数据表格组件:

  • 动态列: 列定义可以通过配置数组传递,支持自定义列名、数据类型、排序和格式化。
  • 排序: 点击表头可以对数据进行排序,支持升序、降序和默认排序。
  • 分页: 支持分页显示数据,可以自定义每页显示条数。
  • 搜索: 支持对表格数据进行搜索过滤。
  • 主题: 可以切换明暗主题。

1. 项目设置

bunx create-react-app my-table --template typescript
cd my-table
bun add @unocss/preset-uno @unocss/preset-attributify @unocss/preset-icons @types/react-table @tanstack/react-table uno.config.ts

2. 配置 UnoCSS

// uno.config.ts
import { defineConfig, presetAttributify, presetIcons, presetUno } from 'unocss'
 
export default defineConfig({
  presets: [
    presetUno(),
    presetAttributify(),
    presetIcons({
      scale: 1.2,
    }),
  ],
  theme: {
    // 自定义主题颜色
    colors: {
      primary: '#3b82f6',
    },
  },
})

3. 创建表格组件

// src/components/Table.tsx
import React, { useMemo, useState } from 'react'
import { useTable, useSortBy, usePagination, useGlobalFilter } from '@tanstack/react-table'
 
interface Column {
  header: string
  accessor: string
  type?: 'string' | 'number' | 'date'
  format?: (value: any) => string
}
 
interface Data {
  [key: string]: any
}
 
interface Props<T extends Data> {
  columns: Column[]
  data: T[]
}
 
export const Table = <T extends Data>({ columns, data }: Props<T>) => {
  const [globalFilter, setGlobalFilter] = useState('')
 
  const tableInstance = useTable(
    {
      columns: useMemo(() => columns, [columns]),
      data,
      globalFilter,
    },
    useGlobalFilter,
    useSortBy,
    usePagination,
  )
 
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    page,
    prepareRow,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize, globalFilter: filter },
  } = tableInstance
 
  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <input
          type="text"
          value={filter || ''}
          onChange={e => setGlobalFilter(e.target.value)}
          placeholder="Search..."
          className="border border-gray-300 rounded px-3 py-2"
        />
        <select
          value={pageSize}
          onChange={e => {
            setPageSize(Number(e.target.value))
          }}
          className="border border-gray-300 rounded px-3 py-2"
        >
          {[10, 25, 50, 100].map(pageSize => (
            <option key={pageSize} value={pageSize}>
              Show {pageSize}
            </option>
          ))}
        </select>
      </div>
      <table {...getTableProps()} className="w-full text-left table-auto">
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th
                  {...column.getHeaderProps(column.getSortByToggleProps())}
                  className="px-6 py-3 border-b text-xs font-medium uppercase tracking-wider"
                >
                  {column.render('Header')}
                  {column.isSorted ? (
                    column.isSortedDesc ? (
                      <i className="i-carbon-chevron-down ml-2"></i>
                    ) : (
                      <i className="i-carbon-chevron-up ml-2"></i>
                    )
                  ) : null}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {page.map((row, i) => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()} className={i % 2 === 0 ? 'bg-gray-50' : ''}>
                {row.cells.map(cell => {
                  return (
                    <td {...cell.getCellProps()} className="px-6 py-4 border-b">
                      {cell.column.format ? cell.column.format(cell.value) : cell.render('Cell')}
                    </td>
                  )
                })}
              </tr>
            )
          })}
        </tbody>
      </table>
      <div className="flex items-center justify-between mt-4">
        <div>
          <button onClick={() => gotoPage(0)} disabled={!canPreviousPage} className="mr-2">
            {'<<'}
          </button>
          <button onClick={() => previousPage()} disabled={!canPreviousPage} className="mr-2">
            {'<'}
          </button>
          <span className="mr-2">
            Page{' '}
            <strong>
              {pageIndex + 1} of {pageOptions.length}
            </strong>{' '}
          </span>
          <button onClick={() => nextPage()} disabled={!canNextPage} className="mr-2">
            {'>'}
          </button>
          <button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
            {'>>'}
          </button>
        </div>
      </div>
    </div>
  )
}

4. 使用表格组件

// src/App.tsx
import React from 'react'
import { Table } from './components/Table'
 
const columns = [
  { header: 'Name', accessor: 'name' },
  { header: 'Age', accessor: 'age', type: 'number' },
  {
    header: 'Date',
    accessor: 'date',
    type: 'date',
    format: (value: Date) => new Date(value).toLocaleDateString(),
  },
]
 
const data = [
  { name: 'John Doe', age: 30, date: new Date() },
  { name: 'Jane Doe', age: 25, date: new Date() },
  { name: 'Peter Pan', age: 18, date: new Date() },
]
 
const App = () => {
  return (
    <div className="container mx-auto p-4">
      <Table columns={columns} data={data} />
    </div>
  )
}
 
export default App

5. 运行项目

bun run dev

解释

  • UnoCSS: 我们使用 UnoCSS 来快速添加样式,例如 table-auto, border-gray-300, bg-gray-50 等。
  • @tanstack/react-table: 这个库提供了强大的表格功能,包括排序、分页和过滤。
  • TypeScript: 我们使用 TypeScript 来定义接口和类型,提高代码的可读性和可维护性。

这个案例展示了如何使用 UnoCSS 和 TypeScript 构建一个功能丰富、可定制的数据表格组件。你可以根据自己的需求扩展这个组件,例如添加行选择、编辑功能等.


好的,让我们使用 Bun 运行环境来创建一个使用 UnoCSS 的复杂案例。我们将构建一个交互式的仪表板组件,包含多个小部件,展示 UnoCSS 的各种特性和灵活性。

首先,让我们设置项目:

bun create vite my-unocss-dashboard --template react-ts
cd my-unocss-dashboard
bun add unocss @unocss/reset
bun add @iconify-json/carbon

现在,让我们配置 UnoCSS:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import UnoCSS from 'unocss/vite'
 
export default defineConfig({
  plugins: [
    UnoCSS(),
    react()
  ],
})
// uno.config.ts
import { defineConfig, presetUno, presetIcons, presetAttributify } from 'unocss'
 
export default defineConfig({
  presets: [
    presetUno(),
    presetIcons({
      scale: 1.2,
      cdn: 'https://esm.sh/'
    }),
    presetAttributify(),
  ],
  theme: {
    colors: {
      primary: '#3b82f6',
      secondary: '#10b981',
      accent: '#8b5cf6',
    },
  },
  shortcuts: {
    'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
    'btn-primary': 'btn bg-primary text-white hover:bg-primary-700',
    'card': 'bg-white rounded-lg shadow-md p-4',
  },
})

现在,让我们创建一些组件:

// src/components/Header.tsx
import React from 'react'
 
const Header: React.FC = () => {
  return (
    <header className="bg-primary text-white p-4">
      <h1 className="text-2xl font-bold">UnoCSS Dashboard</h1>
    </header>
  )
}
 
export default Header
 
// src/components/Sidebar.tsx
import React from 'react'
 
const Sidebar: React.FC = () => {
  return (
    <aside className="bg-gray-100 w-64 p-4 h-screen">
      <nav>
        <ul className="space-y-2">
          <li><a href="#" className="block p-2 hover:bg-gray-200 rounded">Dashboard</a></li>
          <li><a href="#" className="block p-2 hover:bg-gray-200 rounded">Analytics</a></li>
          <li><a href="#" className="block p-2 hover:bg-gray-200 rounded">Settings</a></li>
        </ul>
      </nav>
    </aside>
  )
}
 
export default Sidebar
 
// src/components/Widget.tsx
import React from 'react'
 
interface WidgetProps {
  title: string
  value: string | number
  icon: string
  color: string
}
 
const Widget: React.FC<WidgetProps> = ({ title, value, icon, color }) => {
  return (
    <div className={`card ${color} text-white`}>
      <div className="flex justify-between items-center">
        <div>
          <h3 className="text-lg font-semibold">{title}</h3>
          <p className="text-3xl font-bold">{value}</p>
        </div>
        <div className={`text-4xl i-carbon-${icon}`}></div>
      </div>
    </div>
  )
}
 
export default Widget
 
// src/components/Chart.tsx
import React from 'react'
 
const Chart: React.FC = () => {
  return (
    <div className="card h-64">
      <h3 className="text-lg font-semibold mb-4">Sales Overview</h3>
      <div className="h-48 bg-gray-200 flex items-end justify-around">
        <div className="w-8 bg-primary" style={{ height: '60%' }}></div>
        <div className="w-8 bg-primary" style={{ height: '80%' }}></div>
        <div className="w-8 bg-primary" style={{ height: '40%' }}></div>
        <div className="w-8 bg-primary" style={{ height: '70%' }}></div>
        <div className="w-8 bg-primary" style={{ height: '50%' }}></div>
      </div>
    </div>
  )
}
 
export default Chart

最后,让我们在主应用程序中使用这些组件:

// src/App.tsx
import React from 'react'
import Header from './components/Header'
import Sidebar from './components/Sidebar'
import Widget from './components/Widget'
import Chart from './components/Chart'
 
const App: React.FC = () => {
  return (
    <div className="flex flex-col h-screen">
      <Header />
      <div className="flex flex-1 overflow-hidden">
        <Sidebar />
        <main className="flex-1 p-4 overflow-y-auto">
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
            <Widget title="Total Users" value={1234} icon="user" color="bg-primary" />
            <Widget title="Revenue" value="$5,678" icon="currency-dollar" color="bg-secondary" />
            <Widget title="Orders" value={90} icon="shopping-cart" color="bg-accent" />
            <Widget title="Conversion Rate" value="2.3%" icon="chart-line" color="bg-gray-700" />
          </div>
          <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
            <Chart />
            <div className="card">
              <h3 className="text-lg font-semibold mb-4">Recent Activity</h3>
              <ul className="space-y-2">
                <li className="flex items-center">
                  <span className="i-carbon-user-avatar mr-2"></span>
                  <span>John Doe signed up</span>
                </li>
                <li className="flex items-center">
                  <span className="i-carbon-shopping-cart mr-2"></span>
                  <span>New order received</span>
                </li>
                <li className="flex items-center">
                  <span className="i-carbon-notification mr-2"></span>
                  <span>System update completed</span>
                </li>
              </ul>
            </div>
          </div>
        </main>
      </div>
    </div>
  )
}
 
export default App

最后,更新 src/main.tsx 文件以包含 UnoCSS:

// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import 'uno.css'
import '@unocss/reset/tailwind.css'
 
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

现在,你可以运行项目:

bun run dev

这个复杂案例展示了如何使用 UnoCSS 构建一个交互式仪表板。它包括以下 UnoCSS 特性:

  1. 使用预设(presets):Uno、Icons 和 Attributify
  2. 自定义主题颜色
  3. 使用快捷方式(shortcuts)定义复用样式
  4. 响应式设计
  5. 使用图标
  6. 组合多个实用工具类来创建复杂布局

这个例子展示了 UnoCSS 的强大功能和灵活性,同时也展示了如何在 Bun 环境中使用它来快速构建现代化的用户界面。


要使用 Bun 运行环境生成 UnoCSS 的复杂案例,以下是一个步骤详细的指南。这个案例将展示如何使用 UnoCSS 在 Bun 环境中创建一个具有多种功能的 UI 组件。

步骤 1: 初始化项目

  1. 安装 Bun

    curl -fsSL https://bun.sh/install | bash
  2. 创建新项目

    bun init my-unocss-app
    cd my-unocss-app
  3. 安装依赖

    bun add unocss @unocss/preset-uno @unocss/preset-attributify @unocss/preset-icons

步骤 2: 配置 UnoCSS

  1. 创建 UnoCSS 配置文件
    // uno.config.ts
    import { defineConfig, presetAttributify, presetIcons, presetUno } from 'unocss'
     
    export default defineConfig({
      presets: [
        presetUno(),
        presetAttributify(),
        presetIcons({
          scale: 1.2,
        }),
      ],
      rules: [
        ['m-1', { margin: '1px' }],
        ['m-2', { margin: '2px' }],
        ['text-lg', { fontSize: '18px' }],
        // 添加更多自定义规则根据需要
      ],
      shortcuts: [
        ['btn', 'px-4 py-2 rounded-md bg-blue-500 text-white cursor-pointer'],
        ['btn-blue', 'btn bg-blue-500 hover:bg-blue-700'],
        ['btn-red', 'btn bg-red-500 hover:bg-red-700'],
      ],
      theme: {
        colors: {
          primary: '#3b82f6',
          secondary: '#6b7280',
        },
      },
    })

步骤 3: 创建 React 组件

  1. 安装 React

    bun add react react-dom
  2. 创建组件

    // src/components/Button.tsx
    import React from 'react'
     
    export const Button = ({ children, variant = 'blue', ...props }: { children: React.ReactNode; variant?: 'blue' | 'red' }) => {
      return (
        <button
          className={`btn-${variant} ${props.className || ''}`}
          {...props}
        >
          {children}
        </button>
      )
    }
  3. 创建列表组件

    // src/components/List.tsx
    import React from 'react'
     
    export const List = ({ items, ...props }: { items: string[] }) => {
      return (
        <ul {...props} className="list-none p-0 m-0">
          {items.map((item, index) => (
            <li key={index} className="m-2 text-lg">
              {item}
            </li>
          ))}
        </ul>
      )
    }

步骤 4: 使用组件

  1. 创建应用入口

    // src/App.tsx
    import React from 'react'
    import { Button } from './components/Button'
    import { List } from './components/List'
     
    const App = () => {
      return (
        <div className="flex flex-col items-center justify-center h-screen p-4">
          <h1 className="text-3xl mb-4">UnoCSS Demo</h1>
          <Button variant="blue" onClick={() => alert('Blue button clicked')}>
            Blue Button
          </Button>
          <Button variant="red" className="mt-4" onClick={() => alert('Red button clicked')}>
            Red Button
          </Button>
          <List items={['Item 1', 'Item 2', 'Item 3']} className="mt-8" />
        </div>
      )
    }
     
    export default App
  2. 运行应用

    bun run src/App.tsx

总结

通过这些步骤,你可以在 Bun 环境中使用 UnoCSS 创建一个具有多种功能的 UI 组件。这个示例展示了如何定义自定义 CSS 规则、使用预设、并应用这些规则到 React 组件中.

参考资源

  • UnoCSS 文档:了解更多关于 UnoCSS 的配置和使用方法.
  • Bun 文档:了解更多关于 Bun 环境的配置和使用方法.
  • React 文档:了解更多关于 React 组件的配置和使用方法.

这个案例是一个基本的示例,你可以根据需要添加更多功能和样式。 UnoCSS 的灵活性和可扩展性使得它非常适合用于构建复杂的 UI 项目。