Token导航 LogoToken导航TokenDH.com
研究检索权限需确认github未标认证来源可访问许可证需确认审计通过

stencil-atomic-design-system模板原子设计系统

Agent Skill

用于辅助界面设计、视觉规范、排版、配色、布局和交互体验优化。它适合让 Agent 根据产品场景整理页面结构、生成 UI 方案、检查视觉一致性或改进组件层级。使用时需要结合现有品牌、设计系统和用户任务,不应只堆装饰元素;涉及真实页面改动时,应通过截图或浏览器预览检查文本溢出、对齐和响应式表现。

总安装

517

周安装

22

GitHub Stars

公开资料未说明

下载量

181
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:stencil-atomic-design-system(模板原子设计系统)
来源仓库:https://github.com/corlab-tech/skills
仓库路径:skills/stencil-atomic-design-system
安装命令:
npx skills add https://github.com/corlab-tech/skills --skill stencil-atomic-design-system
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/corlab-tech/skills --skill stencil-atomic-design-system

简介

stencil-atomic-design-system 用于辅助界面设计、视觉规范和组件层级优化,适合 UI/UX 开发场景。

  • 它支持页面结构整理、UI 方案生成和视觉一致性检查,帮助 Agent 提升设计质量。
  • 通过 npx skills add 命令从 GitHub 仓库安装,具体用法可参考原始 README 和 SKILL.md。
  • 使用时需结合品牌和设计系统,避免堆砌装饰元素;涉及真实页面改动时应通过预览检查表现。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Stencil.js Atomic Design System

Build a scalable, themeable design system using Stencil.js with Atomic Design principles, design tokens, and slot-based composition patterns for multi-client deployments.

Project Structure

design-respec/
├── src/
│   ├── components/
│   │   # Atoms - Basic building blocks
│   │   ├── cor-button/
│   │   │   ├── cor-button.tsx
│   │   │   ├── cor-button.css
│   │   │   ├── cor-button.constants.ts
│   │   │   ├── cor-button.enums.ts
│   │   │   ├── cor-button.stories.ts
│   │   │   ├── readme.md
│   │   │   └── test/
│   │   │       └── cor-button.spec.tsx
│   │   ├── cor-icon/
│   │   ├── cor-typography/
│   │   ├── cor-separator/
│   │   # Molecules - Combined components
│   │   ├── cor-input-field/
│   │   ├── cor-toggle/
│   │   ├── cor-search-bar/
│   │   # Organisms - Complex UI structures
│   │   ├── cor-card/
│   │   ├── cor-navbar/
│   │   ├── cor-form/
│   │   # Templates - Page structures
│   │   ├── cor-page-layout/
│   │   └── cor-grid/
│   ├── assets/
│   │   └── css/
│   │       ├── index.css       # Main CSS imports
│   │       ├── base/           # Base HTML styles
│   │       └── utilities/      # Utility classes
│   └── utils/
│       └── theme-utils.ts
├── tokens/
│   ├── core/                   # Core design tokens
│   │   ├── color.tokens.json
│   │   ├── font.tokens.json
│   │   ├── space.tokens.json
│   │   ├── radius.tokens.json
│   │   ├── shadow.tokens.json
│   │   ├── border.tokens.json
│   │   ├── components/         # Component-specific tokens
│   │   └── style-dictionary.config.json
│   ├── respec/                 # RESPEC-specific tokens
│   │   └── [theme files]
│   ├── [client-name]/          # Client-specific tokens
│   │   └── [theme overrides]
│   └── generated/              # Auto-generated CSS
│       └── *.css
├── stencil.config.ts
└── package.json

1. Atomic Design Implementation

Atoms - Foundational Elements

// src/components/cor-button/cor-button.tsx
import { Component, Prop, h, Host } from '@stencil/core';

@Component({
  tag: 'cor-button',
  styleUrl: 'cor-button.css',
  shadow: true,
})
export class CorButton {
  /**
   * Button variant - defines the visual style
   */
  @Prop() variant: 'primary' | 'secondary' | 'tertiary' = 'primary';

  /**
   * Button size
   */
  @Prop() size: 'small' | 'medium' | 'large' = 'medium';

  /**
   * Disabled state
   */
  @Prop() disabled: boolean = false;

  render() {
    return (
      <Host
        class={{
          [`button--${this.variant}`]: true,
          [`button--${this.size}`]: true,
          'button--disabled': this.disabled,
        }}
      >
        <button disabled={this.disabled} class="button">
          <slot name="icon-left"></slot>
          <span class="button__content">
            <slot></slot>
          </span>
          <slot name="icon-right"></slot>
        </button>
      </Host>
    );
  }
}
/* cor-button.css - Component-scoped tokens */
:host {
  /* Component-level tokens */
  --button-padding-small: var(--spacing-xs) var(--spacing-sm);
  --button-padding-medium: var(--spacing-sm) var(--spacing-md);
  --button-padding-large: var(--spacing-md) var(--spacing-lg);

  display: inline-block;
}

.button {
  /* Use semantic tokens from generated CSS */
  font-family: var(--font-family-pro-display);
  border-radius: var(--radius-md);
  transition: 250ms ease;
  cursor: pointer;
  border: none;
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
}

/* Size variants */
:host(.button--small) .button {
  padding: var(--button-padding-small);
  font-size: var(--font-size-sm);
}

:host(.button--medium) .button {
  padding: var(--button-padding-medium);
  font-size: var(--font-size-md);
}

:host(.button--large) .button {
  padding: var(--button-padding-large);
  font-size: var(--font-size-lg);
}

/* Variant styles using semantic tokens */
:host(.button--primary) .button {
  background: var(--color-primary-background-default);
  color: var(--color-primary-text-default);
  border: var(--spacing-px) solid var(--color-primary-border-default);
}

:host(.button--primary) .button:hover {
  background: var(--color-primary-background-hover);
  border-color: var(--color-primary-border-hover);
}

:host(.button--secondary) .button {
  background: var(--color-secondary-background-default);
  color: var(--color-secondary-text-default);
  border: var(--spacing-px) solid var(--color-secondary-border-default);
}

:host(.button--disabled) .button {
  opacity: 0.38;
  cursor: not-allowed;
}

Molecules - Combined Elements

// src/components/cor-input-field/cor-input-field.tsx
import { Component, Prop, State, Event, EventEmitter, h, Host } from '@stencil/core';

@Component({
  tag: 'cor-input-field',
  styleUrl: 'cor-input-field.css',
  shadow: true,
})
export class CorInputField {
  @Prop() label: string;
  @Prop() value: string = '';
  @Prop() error: string;
  @Prop() helperText: string;
  @Prop() required: boolean = false;
  @Prop() disabled: boolean = false;

  @State() focused: boolean = false;

  @Event() valueChange: EventEmitter<string>;

  private handleInput = (event: Event) => {
    const value = (event.target as HTMLInputElement).value;
    this.valueChange.emit(value);
  };

  render() {
    return (
      <Host
        class={{
          'input-field--focused': this.focused,
          'input-field--error': !!this.error,
          'input-field--disabled': this.disabled,
        }}
      >
        <div class="input-field">
          {this.label && (
            <label class="input-field__label">
              {this.label}
              {this.required && <span class="input-field__required">*</span>}
            </label>
          )}

          <div class="input-field__wrapper">
            <slot name="prefix"></slot>
            <input
              class="input-field__input"
              value={this.value}
              onInput={this.handleInput}
              onFocus={() => this.focused = true}
              onBlur={() => this.focused = false}
              disabled={this.disabled}
            />
            <slot name="suffix"></slot>
          </div>

          {(this.error || this.helperText) && (
            <div class="input-field__message">
              {this.error ? this.error : this.helperText}
            </div>
          )}
        </div>
      </Host>
    );
  }
}

Organisms - Complex Structures

// src/components/cor-card/cor-card.tsx
import { Component, Prop, h, Host } from '@stencil/core';

@Component({
  tag: 'cor-card',
  styleUrl: 'cor-card.css',
  shadow: true,
})
export class CorCard {
  @Prop() elevated: boolean = false;
  @Prop() interactive: boolean = false;

  render() {
    return (
      <Host
        class={{
          'card--elevated': this.elevated,
          'card--interactive': this.interactive,
        }}
      >
        <article class="card">
          <slot name="header"></slot>
          <div class="card__body">
            <slot></slot>
          </div>
          <slot name="footer"></slot>
        </article>
      </Host>
    );
  }
}

Templates - Page Structures

// src/components/cor-page-layout/cor-page-layout.tsx
import { Component, Prop, h, Host } from '@stencil/core';

@Component({
  tag: 'cor-page-layout',
  styleUrl: 'cor-page-layout.css',
  shadow: true,
})
export class CorPageLayout {
  @Prop() sidebarPosition: 'left' | 'right' = 'left';
  @Prop() hasHeader: boolean = true;
  @Prop() hasFooter: boolean = false;

  render() {
    return (
      <Host class={`layout--sidebar-${this.sidebarPosition}`}>
        <div class="layout">
          {this.hasHeader && (
            <header class="layout__header">
              <slot name="header"></slot>
            </header>
          )}

          <div class="layout__container">
            <aside class="layout__sidebar">
              <slot name="sidebar"></slot>
            </aside>

            <main class="layout__main">
              <slot></slot>
            </main>
          </div>

          {this.hasFooter && (
            <footer class="layout__footer">
              <slot name="footer"></slot>
            </footer>
          )}
        </div>
      </Host>
    );
  }
}

2. Design Tokens Framework

Three-Tier Token Hierarchy

Tokens are defined in JSON format and processed by Style Dictionary to generate CSS variables.

Core Tokens (Foundation)

/* tokens/core/color.tokens.json */
{
  "color": {
    "palette": {
      "blue": {
        "50": { "value": "#e3f2fd" },
        "100": { "value": "#bbdefb" },
        "200": { "value": "#90caf9" },
        "300": { "value": "#64b5f6" },
        "400": { "value": "#42a5f5" },
        "500": { "value": "#2196f3" },
        "600": { "value": "#1e88e5" },
        "700": { "value": "#1976d2" },
        "800": { "value": "#1565c0" },
        "900": { "value": "#0d47a1" }
      },
      "neutral": {
        "50": { "value": "#fafafa" },
        "100": { "value": "#f5f5f5" },
        "200": { "value": "#eeeeee" },
        "300": { "value": "#e0e0e0" },
        "400": { "value": "#bdbdbd" },
        "500": { "value": "#9e9e9e" },
        "600": { "value": "#757575" },
        "700": { "value": "#616161" },
        "800": { "value": "#424242" },
        "900": { "value": "#212121" }
      }
    }
  }
}
/* tokens/core/font.tokens.json */
{
  "font": {
    "family": {
      "pro-display": {
        "value": "SF Pro Display, -apple-system, BlinkMacSystemFont, sans-serif"
      },
      "pro-text": {
        "value": "SF Pro Text, -apple-system, BlinkMacSystemFont, sans-serif"
      },
      "mono": {
        "value": "SF Mono, Monaco, monospace"
      }
    },
    "size": {
      "xs": { "value": "0.75rem" },
      "sm": { "value": "0.875rem" },
      "md": { "value": "1rem" },
      "lg": { "value": "1.125rem" },
      "xl": { "value": "1.25rem" },
      "2xl": { "value": "1.5rem" },
      "3xl": { "value": "1.875rem" },
      "4xl": { "value": "2.25rem" }
    },
    "weight": {
      "light": { "value": "300" },
      "regular": { "value": "400" },
      "medium": { "value": "500" },
      "semi-bold": { "value": "600" },
      "bold": { "value": "700" }
    }
  },
  "lineHeight": {
    "tight": { "value": "1.25" },
    "base": { "value": "1.5" },
    "relaxed": { "value": "1.75" }
  }
}
/* tokens/core/space.tokens.json */
{
  "space": {
    "px": { "value": "1px" },
    "2xs": { "value": "0.125rem" },
    "xs": { "value": "0.25rem" },
    "sm": { "value": "0.5rem" },
    "md": { "value": "0.75rem" },
    "lg": { "value": "1rem" },
    "xl": { "value": "1.5rem" },
    "2xl": { "value": "2rem" },
    "3xl": { "value": "2.5rem" },
    "4xl": { "value": "3rem" },
    "5xl": { "value": "4rem" },
    "6xl": { "value": "5rem" },
    "7xl": { "value": "6rem" }
  }
}

/* tokens/core/radius.tokens.json */
{
  "radius": {
    "none": { "value": "0" },
    "sm": { "value": "0.25rem" },
    "md": { "value": "0.5rem" },
    "lg": { "value": "0.75rem" },
    "xl": { "value": "1rem" },
    "2xl": { "value": "1.5rem" },
    "3xl": { "value": "2rem" },
    "full": { "value": "9999px" }
  }
}

Component Tokens

/* tokens/core/components/button.tokens.json */
{
  "button": {
    "primary": {
      "background": {
        "default": { "value": "{color.palette.blue.600}" },
        "hover": { "value": "{color.palette.blue.700}" },
        "active": { "value": "{color.palette.blue.800}" },
        "disabled": { "value": "{color.palette.blue.200}" }
      },
      "text": {
        "default": { "value": "#ffffff" },
        "disabled": { "value": "{color.palette.neutral.400}" }
      },
      "border": {
        "default": { "value": "{color.palette.blue.600}" },
        "hover": { "value": "{color.palette.blue.700}" }
      }
    },
    "secondary": {
      "background": {
        "default": { "value": "transparent" },
        "hover": { "value": "{color.palette.neutral.100}" },
        "active": { "value": "{color.palette.neutral.200}" }
      },
      "text": {
        "default": { "value": "{color.palette.neutral.900}" },
        "disabled": { "value": "{color.palette.neutral.400}" }
      },
      "border": {
        "default": { "value": "{color.palette.neutral.300}" },
        "hover": { "value": "{color.palette.neutral.400}" }
      }
    }
  }
}

Theme Support

/* src/tokens/semantic/themes.css */
/* Light theme (default) */
:root,
[data-theme="light"] {
  --ds-color-background: white;
  --ds-color-surface: white;
  --ds-color-text-primary: var(--ds-color-gray-900);
  --ds-color-text-secondary: var(--ds-color-gray-600);
}

/* Dark theme */
[data-theme="dark"] {
  --ds-color-background: var(--ds-color-gray-900);
  --ds-color-surface: var(--ds-color-gray-800);
  --ds-color-text-primary: white;
  --ds-color-text-secondary: var(--ds-color-gray-300);
  --ds-border-color: var(--ds-color-gray-700);
}

Global CSS Setup

/* src/assets/css/index.css */
@import 'base/html.css';
@import 'utilities/scrollbars.css';
@import 'utilities/overlays.css';

/* Import generated tokens - these are auto-generated from JSON */
/* Tokens will be available as CSS variables like:
   --color-primary-background-default
   --font-family-pro-display
   --spacing-md
   --radius-lg
   etc.
*/

Token Processing with Style Dictionary

/* tokens/core/style-dictionary.config.json */
{
  "source": ["tokens/core/**/*.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "buildPath": "../generated/",
      "files": [
        {
          "destination": "core.css",
          "format": "css/variables"
        }
      ]
    }
  }
}

3. Slot-Based Component Architecture

Why Slots Over Props

Slots provide better flexibility, composability, and performance for content projection:

// ❌ Prop-based (avoid)
@Component({ tag: 'ds-button-bad' })
export class BadButton {
  @Prop() label: string;
  @Prop() iconLeft: string;
  @Prop() iconRight: string;

  render() {
    return (
      <button>
        {this.iconLeft && <ds-icon name={this.iconLeft} />}
        {this.label}
        {this.iconRight && <ds-icon name={this.iconRight} />}
      </button>
    );
  }
}

// ✅ Slot-based (preferred)
@Component({ tag: 'ds-button' })
export class Button {
  render() {
    return (
      <button>
        <slot name="icon-left"></slot>
        <slot></slot>
        <slot name="icon-right"></slot>
      </button>
    );
  }
}

Slot Patterns

Default and Named Slots

@Component({ tag: 'ds-modal' })
export class Modal {
  render() {
    return (
      <div class="modal">
        <div class="modal__header">
          <slot name="header"></slot>
        </div>
        <div class="modal__body">
          <slot></slot> {/* Default slot */}
        </div>
        <div class="modal__footer">
          <slot name="footer"></slot>
        </div>
      </div>
    );
  }
}

Usage:

<ds-modal>
  <h2 slot="header">Modal Title</h2>
  <p>This is the body content in the default slot</p>
  <div slot="footer">
    <ds-button>Cancel</ds-button>
    <ds-button variant="primary">Confirm</ds-button>
  </div>
</ds-modal>

Conditional Slot Rendering

@Component({ tag: 'ds-alert' })
export class Alert {
  @Element() el: HTMLElement;
  @State() hasIcon: boolean = false;

  componentWillLoad() {
    // Check if slot has content
    this.hasIcon = !!this.el.querySelector('[slot="icon"]');
  }

  render() {
    return (
      <div class={{ 'alert': true, 'alert--has-icon': this.hasIcon }}>
        {this.hasIcon && (
          <div class="alert__icon">
            <slot name="icon"></slot>
          </div>
        )}
        <div class="alert__content">
          <slot></slot>
        </div>
      </div>
    );
  }
}

Slot Fallback Content

@Component({ tag: 'ds-avatar' })
export class Avatar {
  @Prop() name: string;

  render() {
    const initials = this.name
      ?.split(' ')
      .map(word => word[0])
      .join('')
      .toUpperCase();

    return (
      <div class="avatar">
        <slot>
          {/* Fallback content when slot is empty */}
          <span class="avatar__initials">{initials}</span>
        </slot>
      </div>
    );
  }
}

4. Multi-Client Theming Architecture

Theme Structure

tokens/
├── core/                   # Base design tokens
├── respec/                # RESPEC-specific overrides
├── [client-name]/         # Client-specific tokens
└── generated/             # Auto-generated CSS from Style Dictionary
    ├── core.css
    ├── respec.css
    └── [client-name].css

Build Configuration

// stencil.config.ts
import { Config } from '@stencil/core';
import { reactOutputTarget as react } from '@stencil/react-output-target';
import { postcss } from '@stencil/postcss';
import postcssNested from 'postcss-nested';

export const config: Config = {
  namespace: 'design-system',
  srcDir: 'src',
  globalStyle: 'src/assets/css/index.css',
  outputTargets: [
    {
      type: 'dist',
      esmLoaderPath: '../loader',
      copy: [
        {
          src: '../tokens/generated/*.css',
          dest: 'tokens',
          warn: false,
        },
      ],
    },
    {
      type: 'dist-custom-elements',
      copy: [
        {
          src: '**/*.{jpg,png}',
          dest: 'dist/components/assets',
          warn: true,
        },
      ],
    },
    {
      type: 'docs-readme',
    },
    {
      type: 'www',
      serviceWorker: null,
    },
    // Conditional React output
    react({
      outDir: '../react-design-system/src/components/stencil-generated/',
    }),
  ],
  plugins: [
    postcss({
      plugins: [postcssNested()],
    }),
  ],
};

Build Scripts

// package.json
{
  "scripts": {
    "build": "npm run tokens:build && stencil build",
    "build:react": "npm run tokens:build && stencil build --react",
    "start": "stencil build --dev --watch --serve",
    "test": "stencil test --spec --e2e",
    "test:watch": "stencil test --spec --e2e --watchAll",
    "tokens:build": "style-dictionary build --config ./tokens/core/style-dictionary.config.json",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  }
}

5. Component File Structure

Each component follows this structure:

src/components/cor-[component-name]/
├── cor-[component-name].tsx           # Component implementation
├── cor-[component-name].css           # Component styles
├── cor-[component-name].enums.ts      # Enums for props
├── cor-[component-name].constants.ts  # Constants
├── cor-[component-name].stories.ts    # Storybook stories
├── readme.md                          # Auto-generated docs
└── test/
    ├── cor-[component-name].spec.tsx  # Unit tests
    └── cor-[component-name].e2e.ts   # E2E tests

6. CSS Variable Naming Convention

The project uses flat CSS variable naming without prefixes:

/* Generated from tokens */
--color-primary-background-default
--color-primary-background-hover
--font-family-pro-display
--font-size-md
--spacing-lg
--radius-md
--shadow-sm
--line-height-base
--font-weight-semi-bold

7. Best Practices

Component Development

  1. Use cor- prefix for all components
  2. Slot-based composition over props for content
  3. Enums for prop values in separate.enums.ts files
  4. Constants in separate.constants.ts files
  5. TypeScript strict mode for type safety
  6. CSS variables for all design tokens
  7. PostCSS with nested syntax for styles

Token Management

  1. JSON format for token definitions
  2. Style Dictionary for token processing
  3. Three-tier hierarchy: Core → Theme → Component
  4. Reference tokens using {token.path} syntax
  5. Auto-generate CSS from JSON tokens

Testing

  1. Unit tests with @stencil/core/testing
  2. E2E tests for user interactions
  3. Storybook stories for visual testing
  4. Test file naming: *.spec.tsx for unit, *.e2e.ts for E2E

Documentation

  1. JSDoc comments for public APIs
  2. Auto-generated readme from component metadata
  3. Storybook for interactive documentation
  4. Component stories showing all variations

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

35.98%
按下载量换算65

Claude

31.18%
按下载量换算56

Cursor

21.02%
按下载量换算38

Gemini CLI

9.78%
按下载量换算18

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限需确认

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills