@placeholderco/placeholder-ui

中文文档
3.2.3发布于 2026/11/02MITTypeScriptES Module构建来源已验证

A modern, customizable Svelte 5 UI component library with comprehensive theming support. Re-brand it with a single config object.

原始使用文档
文档目录13 节
  1. Install
  2. Quick start
  3. Branding
  4. 1. A config object (recommended)
  5. Light and dark values
  6. 2. Plain CSS
  7. Color roles
  8. Fonts
  9. Logo
  10. Variants
  11. Theme (light / dark)
  12. Development
  13. License

PlaceholderUI

A Svelte 5 component library that you re-brand with a single config object. Forms, overlays, layout, data display, a TipTap rich-text editor and a CodeMirror code editor, all styled through one set of --ui-* CSS tokens.

  • Svelte 5 runes, TypeScript, typed props on every component
  • Light / dark / system theme with persistence
  • Neutral default palette; swap in your own colours, font and logo in one call
  • 150+ icons exported as raw SVG strings

Install

pnpm add @placeholderco/placeholder-ui

Peer dependency: svelte ^5.

Quick start

Wrap your app in AppShell (it loads the base stylesheet), then use components:

<script lang="ts">
    import { AppShell, Navbar, Button } from '@placeholderco/placeholder-ui';
</script>

<AppShell>
    <Navbar appNav={{ href: '/', text: 'My App' }} />
    <Button variant="primary">Save</Button>
</AppShell>

Or skip AppShell and import the token stylesheet yourself:

import '@placeholderco/placeholder-ui/app.css';

Branding

Everything colour- and font-related resolves to --ui-* custom properties, so there are two ways to brand the library.

// src/routes/+layout.svelte (or any startup code)
import { applyTheme } from '@placeholderco/placeholder-ui';
import logo from '$lib/logo.svg?raw';

applyTheme({
    colors: {
        primary: '#1e3a5f', // dark brand colour: solid buttons, headings
        accent: '#93c5fd', // light brand colour: highlights, dark-mode accent
        tertiary: '#a5f3fc' // supporting color: links use its readable text color
    },
    fontFamily: "'Inter', system-ui, sans-serif",
    logo // raw SVG, rendered by <Logo />
});

Each brand color has independent *HoverColor and *PressedColor settings: primaryHoverColor, accentHoverColor, tertiaryHoverColor, primaryPressedColor, accentPressedColor and tertiaryPressedColor. They are shared by solid, outline and subtle controls; subtle variants use translucent hover fills where appropriate.

All three colors have the same two text roles:

SettingUsed for
primaryTextColor, accentTextColor, tertiaryTextColorColored text and outline borders on page/paper surfaces.
primaryContrastColor, accentContrastColor, tertiaryContrastColorText and icons on the matching solid fill, including hover and pressed fills.

For example, primaryTextColor styles a primary outline button at rest, while primaryContrastColor styles the label on a filled primary button. focusColor, link and linkHover control keyboard focus rings and links independently. Changing a hover color does not change these other roles.

All role overrides are optional. By default, primary hover uses the accent text color, accent hover uses tertiary, and tertiary hover uses accent. Primary pressed is darkened from its base color. Primary text defaults to primary; accent and tertiary text colors are darkened from their base colors. Accent and tertiary pressed colors are lightened from tertiary (or accent when tertiary is omitted). Primary contrast defaults to white; accent and tertiary contrast default to primary.

For existing configs, replace primaryDark with primaryPressedColor, accentDark with accentTextColor, and tertiaryDark with tertiaryTextColor. Replace tertiaryLight with both accentPressedColor and tertiaryPressedColor to preserve both sets of pressed states. Set the hover colors separately when customizing interactions. Rename primaryContrast and accentContrast to primaryContrastColor and accentContrastColor. Their CSS tokens also gain the -color suffix. CSS overrides use the corresponding kebab-case names, such as --ui-primary-hover-color and --ui-tertiary-text-color.

Light and dark values

Everything in the config is the light-mode value and also applies in dark mode. To change any of it while dark mode is active, add a dark block with the same shape. Only what you name is overridden; shades are derived per colour.

applyTheme({
    colors: { primary: '#1e293b', accent: '#fbbf24', tertiary: '#7dd3fc' },
    logo,
    dark: {
        colors: { accent: '#fde68a', link: '#fde68a' },
        fontFamily: "'Inter', system-ui, sans-serif", // optional
        logo: darkLogo // optional
    }
});

applyTheme injects one <style> element with a :root rule and a :root.dark rule, so values switch with the existing .dark class.

To avoid a flash of the default palette on first paint, render the same config as CSS on the server:

import { themeToCss } from '@placeholderco/placeholder-ui';
const css = themeToCss(myTheme); // ":root { ... }\n:root.dark { ... }"

and place it in a <style> tag in app.html or your root layout head.

2. Plain CSS

Override the tokens in any stylesheet loaded after the library:

:root {
    --ui-primary-rgb: 30 58 95;
    --ui-primary-rgbc: 30, 58, 95;
    --ui-primary: rgb(var(--ui-primary-rgb));
    --ui-primary-hover-color: #1d4ed8;
    --ui-primary-pressed-color: #12253d;
    --ui-primary-text-color: #1e3a5f;
    --ui-primary-contrast-color: #ffffff;
    --ui-accent-rgb: 147 197 253;
    --ui-accent-rgbc: 147, 197, 253;
    --ui-accent: rgb(var(--ui-accent-rgb));
    --ui-accent-hover-color: #a5f3fc;
    --ui-accent-pressed-color: #cffafe;
    --ui-accent-text-color: #1d4ed8;
    --ui-accent-contrast-color: #1e3a5f;
    --ui-tertiary: #a5f3fc;
    --ui-tertiary-hover-color: #93c5fd;
    --ui-tertiary-pressed-color: #cffafe;
    --ui-tertiary-text-color: #0e7490;
    --ui-tertiary-contrast-color: #1e3a5f;
    --ui-focus-color: #1d4ed8;
    --ui-font-family: 'Inter', system-ui, sans-serif;
}

The full token list, with comments on each role, is at the top of src/lib/app.css.

Color roles

Keep these relationships when choosing colours, because components assume them:

TokenRole
--ui-primaryDark by default. Solid buttons and active backgrounds.
--ui-accentLight. Hovers, highlights, the accent in dark mode.
--ui-tertiaryLight. Supporting fills; its text color is used for links

Fonts

The library never bundles a font. Set --ui-font-family (or fontFamily in the config) and load the font yourself with @font-face or a <link>.

<Logo /> renders, in order of preference: its svg prop, the logo registered via applyTheme({ logo }) / setLogo(), or a generic placeholder. Use fill="currentColor" in your SVG so it follows the theme, or register a separate dark-mode logo with dark.logo / setLogo(light, dark).

Variants

Button, Badge, ActionIcon, Dropdown, Accordion and ProgressBar share colour variants named after the tokens: primary, accent, tertiary, plus -outline and -subtle forms, and the neutral secondary, white, danger and auto-* variants.

The additional coloured buttons use tertiary, tertiary-outline and tertiary-subtle, configured through colors.tertiary and the existing --ui-tertiary* tokens. The secondary, secondary-subtle and secondary-selected variants retain their original neutral styles; existing apps do not need to rename them. Existing tertiary colours and button styles are preserved, with outline support added to the family.

Theme (light / dark)

import { themeState, setTheme } from '@placeholderco/placeholder-ui';

setTheme('dark'); // 'light' | 'dark' | 'system'
themeState.isDarkMode; // reactive boolean

The .light / .dark class is applied to <html>. In your own components use :global(.dark) .my-class { ... } or the surface tokens (--page-bg, --paper-body-bg, --text-color, --border-color, ...).

Development

pnpm install
pnpm run dev      # showcase app at http://localhost:5173
pnpm run check    # svelte-check
pnpm run build    # library + showcase
pnpm run format

src/lib is the published library; src/routes is the showcase. Every component has a demo page under src/routes/components/<name>.

License

MIT

版本与发布记录

@placeholderco/placeholder-ui 共发布 52 个版本,首次发布于 2026/02/07;过去 12 个月发布了 52 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.2.3latest2026/11/021 天前
3.2.22026/11/021 天前
3.2.12026/11/021 天前
3.2.02026/11/021 天前
3.1.32026/10/304 天前
3.1.22026/10/304 天前

关于 @placeholderco/placeholder-ui 的常见问题

@placeholderco/placeholder-ui 是什么?

一个现代的、可定制的Svelte 5 UI组件库,具有全面的主题支持。用单个配置对象重新命名它。

如何安装 @placeholderco/placeholder-ui?

在项目目录运行 npm install @placeholderco/placeholder-ui,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:svelte(^5.0.0)、@sveltejs/kit(^2.26.0 || ^3.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@placeholderco/placeholder-ui 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@placeholderco/placeholder-ui 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@placeholderco/placeholder-ui 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@placeholderco/placeholder-ui 可以商用吗?

@placeholderco/placeholder-ui 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@placeholderco/placeholder-ui 还在维护吗?

最新版本 3.2.3 发布于 2026/11/02(1 天前);至今共发布 52 个版本,其中过去 12 个月发布了 52 个;首次发布于 2026/02/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。