# Remix

> 在 Remix 或 React Router v7 中配置 React 颜色选择器：安装、通过 links 导出引入样式表，再在路由中渲染。

Source: https://chroma-panel.jscrate.dev/zh/react/frameworks/remix
Last updated: 2026-09-21

在 Remix 中使用 chroma-panel，不需要包装组件、`ClientOnly`，也不需要 `typeof window` 判断。通过 `links` 导出加入样式表，然后在路由中渲染 React 颜色选择器即可。同样的配置也适用于 React Router v7 的框架模式。

## 安装

```bash
npm install chroma-panel
```

这个包没有任何依赖。`react` 和 `react-dom` 是 peer 依赖，所以用的就是你应用里已有的那一份。

## 引入样式表

面板在 effect 中注入自己的样式表，因此在水合完成之前，服务端渲染出的标记是没有样式的。Remix 有自己加载 CSS 的方式：导入文件的 URL，并在 `links` 导出中返回它。

```tsx
// app/root.tsx
import type { LinksFunction } from "@remix-run/node";
import chromaPanelStyles from "chroma-panel/style.css?url";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: chromaPanelStyles },
];
```

在 React Router v7 中，类型改从 `react-router` 导入：

```tsx
import type { LinksFunction } from "react-router";
import chromaPanelStyles from "chroma-panel/style.css?url";
```

然后在渲染面板的地方都传入 `injectStyles={false}`，免得它再往 `<style>` 标签里写一份。

> **?url 是 Vite 的功能，不是 Remix 的**
>
> Vite 会去掉查询参数来解析这个导入路径，然后返回构建后文件的
> URL。`chroma-panel` 在 `exports` 映射中列出了
> `"./style.css"`，所以这个子路径会解析到 `dist/style.css`。Remix v2 和 React
> Router v7 都用 Vite 构建，所以两者都能这样用。如果你的构建不使用 Vite，就去掉
> `?url`，改用其他方式加载 CSS。

如果你的应用使用 Tailwind，层级顺序比加载方式更重要。[使用 Tailwind 样式](https://chroma-panel.jscrate.dev/zh/react/handbook/tailwind)给出了能让你的工具类始终优先生效的导入顺序。

## 路由示例

```tsx
// app/routes/brand.tsx
import { useState } from "react";
import { ColorInput, type ColorChangeResult } from "chroma-panel";

export default function BrandRoute() {
  const [color, setColor] = useState<string>("#3366cc");

  const handleChange = (result: ColorChangeResult): void => {
    setColor(result.hex);
  };

  return (
    <main>
      <h2>Brand color</h2>
      <ColorInput value={color} onChange={handleChange} injectStyles={false} />
      <p style={{ color }}>{color}</p>
    </main>
  );
}
```

如果想把颜色提交给 action，而不是保存在状态中，就给 `ColorInput` 传一个 `name`，并去掉 `value` 和 `onChange`。它会渲染一个隐藏输入框，像其他控件一样随表单提交，详见[表单](https://chroma-panel.jscrate.dev/zh/react/handbook/forms)。

## 服务端渲染

不需要做任何防护。上面的路由原样就能在服务端渲染：

- 包中所有涉及浏览器的文件都带有 `'use client'`，模块顶层也不会读取 `window`。
- 当 `document` 未定义时，`injectStyles` 会提前返回，所以服务端渲染时不会尝试创建 `<style>` 标签。
- 首次渲染会把颜色以 CSS 自定义属性的形式写到面板的根元素上，因此服务端渲染出的标记已经带有正确的颜色，水合之前不会闪烁。

[服务端渲染](https://chroma-panel.jscrate.dev/zh/react/handbook/server-rendering)针对 Next.js 和其他 SSR 方案讲了同样的要点；如果你不想打包默认导入注册的全部模式，[入口](https://chroma-panel.jscrate.dev/zh/react/utils/entry-points)列出了所有子路径。
