Token导航 LogoToken导航

Agent Skill · 研究检索

atomic-design-templates(原子设计模板)

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

atomic-design-templates 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为权限未标注;许可证为 MIT,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 37,816。

总安装 1,665周安装 68GitHub Stars 142下载 539核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill atomic-design-templates

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

atomic-design-templates 创建页面级布局骨架,排列有机体并定义内容占位结构。适用于建立响应式页面模板,分离结构与内容,提升开发效率。使用占位内容而非真实数据,确保模板可跨页面复用。使用前应规划页面区块组成,避免为单一页面定制模板。

适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/atomic-design-templates

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/thebushidocollective/han --skill atomic-design…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    权限没有明确标注,第一次使用时只给一个无关紧要的任务,观察它到底读了哪些文件和网络。

常见问题

6 条

atomic-design-templates 怎么安装?

在终端执行 npx skills add https://github.com/thebushidocollective/han --skill atomic-design-templates。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

atomic-design-templates 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

atomic-design-templates 需要什么权限?

权限级别没有明确标注。第一次使用时建议只给无关紧要的任务,观察它实际读写了哪些内容。

atomic-design-templates 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

atomic-design-templates 用的人多吗?

公开数据是累计安装 1,665 次,近一周安装 68 次,下载 539 次,GitHub 142 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

atomic-design-templates 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
atomic-design-templates

原子设计模板 · 本页

1,665142权限未标注MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Atomic Design: Templates

Master the creation of templates - page-level layouts that define content structure without actual content. Templates establish the skeletal structure that pages will use.

What Are Templates?

Templates are the page-level objects that place components into a layout and articulate the design's underlying content structure. They are:

  • Composed of organisms: Arrange organisms into page layouts
  • Content-agnostic: Use placeholder content, not real data
  • Structural: Define where content types will appear
  • Reusable: Same template can be used by multiple pages
  • Responsive: Handle all viewport sizes

Common Template Types

Marketing Templates

  • Landing page layouts
  • Homepage layouts
  • Product showcase layouts
  • About/Company layouts

Application Templates

  • Dashboard layouts
  • Settings page layouts
  • Profile page layouts
  • List/Detail page layouts

Content Templates

  • Blog post layouts
  • Article layouts
  • Documentation layouts
  • Help center layouts

E-commerce Templates

  • Product listing layouts
  • Product detail layouts
  • Checkout layouts
  • Order confirmation layouts

MainLayout Template Example

Complete Implementation

// templates/MainLayout/MainLayout.tsx
import React from 'react';
import { Header, type HeaderProps } from '@/components/organisms/Header';
import { Footer, type FooterProps } from '@/components/organisms/Footer';
import styles from './MainLayout.module.css';

export interface MainLayoutProps {
  /** Header configuration */
  headerProps: HeaderProps;
  /** Footer configuration */
  footerProps: FooterProps;
  /** Main content */
  children: React.ReactNode;
  /** Show breadcrumbs */
  showBreadcrumbs?: boolean;
  /** Breadcrumb component */
  breadcrumbs?: React.ReactNode;
  /** Maximum content width */
  maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
  /** Page background color */
  background?: 'white' | 'gray' | 'primary';
}

export const MainLayout: React.FC<MainLayoutProps> = ({
  headerProps,
  footerProps,
  children,
  showBreadcrumbs = false,
  breadcrumbs,
  maxWidth = 'lg',
  background = 'white',
}) => {
  return (
    <div className={`${styles.layout} ${styles[`bg-${background}`]}`}>
      <Header {...headerProps} />

      <main className={styles.main}>
        {showBreadcrumbs && breadcrumbs && (
          <div className={styles.breadcrumbs}>{breadcrumbs}</div>
        )}

        <div className={`${styles.content} ${styles[`max-${maxWidth}`]}`}>
          {children}
        </div>
      </main>

      <Footer {...footerProps} />
    </div>
  );
};

MainLayout.displayName = 'MainLayout';
/* templates/MainLayout/MainLayout.module.css */
.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.breadcrumbs {
  padding: 16px 24px;
  background-color: var(--color-neutral-50);
  border-bottom: 1px solid var(--color-neutral-200);
}

.content {
  flex: 1;
  margin: 0 auto;
  padding: 24px;
  width: 100%;
}

/* Max Width Variants */
.max-sm {
  max-width: 640px;
}

.max-md {
  max-width: 768px;
}

.max-lg {
  max-width: 1024px;
}

.max-xl {
  max-width: 1280px;
}

.max-full {
  max-width: 100%;
}

/* Background Variants */
.bg-white {
  background-color: var(--color-white);
}

.bg-gray {
  background-color: var(--color-neutral-50);
}

.bg-primary {
  background-color: var(--color-primary-50);
}

/* Responsive adjustments */
@media (max-width: 768px) {
  .content {
    padding: 16px;
  }
}

DashboardLayout Template Example

// templates/DashboardLayout/DashboardLayout.tsx
import React, { useState } from 'react';
import { Header } from '@/components/organisms/Header';
import { Sidebar, type SidebarProps } from '@/components/organisms/Sidebar';
import styles from './DashboardLayout.module.css';

export interface DashboardLayoutProps {
  /** Header props */
  headerProps: {
    logo: React.ReactNode;
    user?: { name: string; email: string; avatar?: string };
    onLogout?: () => void;
  };
  /** Sidebar props */
  sidebarProps: SidebarProps;
  /** Main content */
  children: React.ReactNode;
  /** Page title */
  pageTitle?: string;
  /** Page description */
  pageDescription?: string;
  /** Page actions (buttons, etc.) */
  pageActions?: React.ReactNode;
  /** Sidebar initially collapsed */
  sidebarCollapsed?: boolean;
}

export const DashboardLayout: React.FC<DashboardLayoutProps> = ({
  headerProps,
  sidebarProps,
  children,
  pageTitle,
  pageDescription,
  pageActions,
  sidebarCollapsed = false,
}) => {
  const [isCollapsed, setIsCollapsed] = useState(sidebarCollapsed);

  return (
    <div className={styles.layout}>
      {/* Top Header */}
      <Header
        logo={headerProps.logo}
        navigation={[]}
        user={headerProps.user}
        onLogout={headerProps.onLogout}
        showSearch={false}
      />

      <div className={styles.body}>
        {/* Sidebar */}
        <Sidebar
          {...sidebarProps}
          isCollapsed={isCollapsed}
          onToggleCollapse={() => setIsCollapsed(!isCollapsed)}
        />

        {/* Main Content Area */}
        <main className={styles.main}>
          {/* Page Header */}
          {(pageTitle || pageActions) && (
            <header className={styles.pageHeader}>
              <div className={styles.titleSection}>
                {pageTitle && <h1 className={styles.pageTitle}>{pageTitle}</h1>}
                {pageDescription && (
                  <p className={styles.pageDescription}>{pageDescription}</p>
                )}
              </div>
              {pageActions && (
                <div className={styles.pageActions}>{pageActions}</div>
              )}
            </header>
          )}

          {/* Page Content */}
          <div className={styles.content}>{children}</div>
        </main>
      </div>
    </div>
  );
};

DashboardLayout.displayName = 'DashboardLayout';
/* templates/DashboardLayout/DashboardLayout.module.css */
.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.body {
  display: flex;
  flex: 1;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
  background-color: var(--color-neutral-50);
}

.pageHeader {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  padding: 24px;
  background-color: var(--color-white);
  border-bottom: 1px solid var(--color-neutral-200);
}

.titleSection {
  flex: 1;
}

.pageTitle {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  color: var(--color-neutral-900);
}

.pageDescription {
  margin: 4px 0 0;
  font-size: 14px;
  color: var(--color-neutral-500);
}

.pageActions {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}

.content {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
}

@media (max-width: 768px) {
  .pageHeader {
    flex-direction: column;
    align-items: stretch;
  }

  .pageActions {
    margin-top: 16px;
  }

  .content {
    padding: 16px;
  }
}

AuthLayout Template Example

// templates/AuthLayout/AuthLayout.tsx
import React from 'react';
import styles from './AuthLayout.module.css';

export interface AuthLayoutProps {
  /** Logo element */
  logo: React.ReactNode;
  /** Page title */
  title: string;
  /** Page subtitle */
  subtitle?: string;
  /** Form content */
  children: React.ReactNode;
  /** Footer content (links, etc.) */
  footer?: React.ReactNode;
  /** Background image URL */
  backgroundImage?: string;
  /** Show decorative side panel */
  showSidePanel?: boolean;
  /** Side panel content */
  sidePanelContent?: React.ReactNode;
}

export const AuthLayout: React.FC<AuthLayoutProps> = ({
  logo,
  title,
  subtitle,
  children,
  footer,
  backgroundImage,
  showSidePanel = false,
  sidePanelContent,
}) => {
  return (
    <div className={styles.layout}>
      {/* Side Panel (optional) */}
      {showSidePanel && (
        <div
          className={styles.sidePanel}
          style={
            backgroundImage
              ? { backgroundImage: `url(${backgroundImage})` }
              : undefined
          }
        >
          <div className={styles.sidePanelContent}>{sidePanelContent}</div>
        </div>
      )}

      {/* Main Content */}
      <div className={styles.main}>
        <div className={styles.container}>
          {/* Logo */}
          <div className={styles.logo}>{logo}</div>

          {/* Header */}
          <header className={styles.header}>
            <h1 className={styles.title}>{title}</h1>
            {subtitle && <p className={styles.subtitle}>{subtitle}</p>}
          </header>

          {/* Form Content */}
          <div className={styles.content}>{children}</div>

          {/* Footer */}
          {footer && <footer className={styles.footer}>{footer}</footer>}
        </div>
      </div>
    </div>
  );
};

AuthLayout.displayName = 'AuthLayout';
/* templates/AuthLayout/AuthLayout.module.css */
.layout {
  display: flex;
  min-height: 100vh;
}

.sidePanel {
  display: none;
  width: 50%;
  background-color: var(--color-primary-600);
  background-size: cover;
  background-position: center;
  position: relative;
}

@media (min-width: 1024px) {
  .sidePanel {
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

.sidePanelContent {
  padding: 48px;
  color: var(--color-white);
  text-align: center;
}

.main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background-color: var(--color-neutral-50);
}

.container {
  width: 100%;
  max-width: 400px;
}

.logo {
  text-align: center;
  margin-bottom: 32px;
}

.header {
  text-align: center;
  margin-bottom: 32px;
}

.title {
  margin: 0;
  font-size: 28px;
  font-weight: 700;
  color: var(--color-neutral-900);
}

.subtitle {
  margin: 8px 0 0;
  font-size: 16px;
  color: var(--color-neutral-500);
}

.content {
  background-color: var(--color-white);
  padding: 32px;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.footer {
  margin-top: 24px;
  text-align: center;
  font-size: 14px;
  color: var(--color-neutral-500);
}

.footer a {
  color: var(--color-primary-500);
  text-decoration: none;
}

.footer a:hover {
  text-decoration: underline;
}

ProductListingLayout Template Example

// templates/ProductListingLayout/ProductListingLayout.tsx
import React from 'react';
import { MainLayout, type MainLayoutProps } from '../MainLayout';
import styles from './ProductListingLayout.module.css';

export interface ProductListingLayoutProps {
  /** Main layout props */
  layoutProps: Omit<MainLayoutProps, 'children'>;
  /** Category title */
  categoryTitle: string;
  /** Category description */
  categoryDescription?: string;
  /** Product count */
  productCount: number;
  /** Filter sidebar content */
  filters: React.ReactNode;
  /** Sort/view controls */
  controls: React.ReactNode;
  /** Product grid content */
  products: React.ReactNode;
  /** Pagination content */
  pagination?: React.ReactNode;
  /** Show filters on mobile */
  mobileFiltersOpen?: boolean;
  /** Toggle mobile filters */
  onToggleMobileFilters?: () => void;
}

export const ProductListingLayout: React.FC<ProductListingLayoutProps> = ({
  layoutProps,
  categoryTitle,
  categoryDescription,
  productCount,
  filters,
  controls,
  products,
  pagination,
  mobileFiltersOpen = false,
  onToggleMobileFilters,
}) => {
  return (
    <MainLayout {...layoutProps} maxWidth="xl">
      {/* Category Header */}
      <header className={styles.header}>
        <div className={styles.titleSection}>
          <h1 className={styles.title}>{categoryTitle}</h1>
          {categoryDescription && (
            <p className={styles.description}>{categoryDescription}</p>
          )}
          <span className={styles.count}>{productCount} products</span>
        </div>
      </header>

      <div className={styles.body}>
        {/* Desktop Filters */}
        <aside className={styles.sidebar}>
          <div className={styles.sidebarContent}>{filters}</div>
        </aside>

        {/* Mobile Filters Overlay */}
        {mobileFiltersOpen && (
          <div className={styles.mobileFilters}>
            <div className={styles.mobileFiltersHeader}>
              <h2>Filters</h2>
              <button onClick={onToggleMobileFilters}>Close</button>
            </div>
            <div className={styles.mobileFiltersContent}>{filters}</div>
          </div>
        )}

        {/* Main Content */}
        <div className={styles.main}>
          {/* Controls Bar */}
          <div className={styles.controls}>
            <button
              className={styles.mobileFilterButton}
              onClick={onToggleMobileFilters}
            >
              Filters
            </button>
            {controls}
          </div>

          {/* Product Grid */}
          <div className={styles.products}>{products}</div>

          {/* Pagination */}
          {pagination && (
            <div className={styles.pagination}>{pagination}</div>
          )}
        </div>
      </div>
    </MainLayout>
  );
};

ProductListingLayout.displayName = 'ProductListingLayout';

BlogPostLayout Template Example

// templates/BlogPostLayout/BlogPostLayout.tsx
import React from 'react';
import { MainLayout, type MainLayoutProps } from '../MainLayout';
import { Avatar } from '@/components/atoms/Avatar';
import { Text } from '@/components/atoms/Typography';
import styles from './BlogPostLayout.module.css';

export interface Author {
  name: string;
  avatar?: string;
  bio?: string;
}

export interface BlogPostLayoutProps {
  /** Main layout props */
  layoutProps: Omit<MainLayoutProps, 'children'>;
  /** Post title */
  title: string;
  /** Post subtitle */
  subtitle?: string;
  /** Featured image */
  featuredImage?: string;
  /** Author information */
  author: Author;
  /** Publication date */
  publishedAt: string;
  /** Reading time */
  readingTime?: string;
  /** Post categories/tags */
  tags?: React.ReactNode;
  /** Main article content */
  children: React.ReactNode;
  /** Table of contents */
  tableOfContents?: React.ReactNode;
  /** Author bio card */
  showAuthorBio?: boolean;
  /** Related posts */
  relatedPosts?: React.ReactNode;
  /** Comments section */
  comments?: React.ReactNode;
  /** Social share buttons */
  shareButtons?: React.ReactNode;
}

export const BlogPostLayout: React.FC<BlogPostLayoutProps> = ({
  layoutProps,
  title,
  subtitle,
  featuredImage,
  author,
  publishedAt,
  readingTime,
  tags,
  children,
  tableOfContents,
  showAuthorBio = true,
  relatedPosts,
  comments,
  shareButtons,
}) => {
  const formattedDate = new Date(publishedAt).toLocaleDateString('en-US', {
    month: 'long',
    day: 'numeric',
    year: 'numeric',
  });

  return (
    <MainLayout {...layoutProps} maxWidth="md">
      <article className={styles.article}>
        {/* Article Header */}
        <header className={styles.header}>
          {tags && <div className={styles.tags}>{tags}</div>}

          <h1 className={styles.title}>{title}</h1>

          {subtitle && <p className={styles.subtitle}>{subtitle}</p>}

          {/* Author & Meta */}
          <div className={styles.meta}>
            <div className={styles.author}>
              <Avatar
                src={author.avatar}
                alt={author.name}
                initials={author.name.slice(0, 2).toUpperCase()}
                size="md"
              />
              <div className={styles.authorInfo}>
                <Text weight="semibold">{author.name}</Text>
                <Text size="sm" color="muted">
                  {formattedDate}
                  {readingTime && ` · ${readingTime}`}
                </Text>
              </div>
            </div>

            {shareButtons && (
              <div className={styles.share}>{shareButtons}</div>
            )}
          </div>
        </header>

        {/* Featured Image */}
        {featuredImage && (
          <figure className={styles.featuredImage}>
            <img src={featuredImage} alt={title} />
          </figure>
        )}

        {/* Content with Optional TOC */}
        <div className={styles.contentWrapper}>
          {/* Table of Contents (Desktop) */}
          {tableOfContents && (
            <aside className={styles.toc}>
              <div className={styles.tocContent}>{tableOfContents}</div>
            </aside>
          )}

          {/* Main Content */}
          <div className={styles.content}>{children}</div>
        </div>

        {/* Author Bio */}
        {showAuthorBio && (
          <footer className={styles.authorBio}>
            <Avatar
              src={author.avatar}
              alt={author.name}
              initials={author.name.slice(0, 2).toUpperCase()}
              size="lg"
            />
            <div>
              <Text weight="semibold" size="lg">
                {author.name}
              </Text>
              {author.bio && <Text color="muted">{author.bio}</Text>}
            </div>
          </footer>
        )}

        {/* Share (Bottom) */}
        {shareButtons && (
          <div className={styles.bottomShare}>{shareButtons}</div>
        )}
      </article>

      {/* Related Posts */}
      {relatedPosts && (
        <section className={styles.relatedPosts}>
          <h2>Related Posts</h2>
          {relatedPosts}
        </section>
      )}

      {/* Comments */}
      {comments && (
        <section className={styles.comments}>{comments}</section>
      )}
    </MainLayout>
  );
};

BlogPostLayout.displayName = 'BlogPostLayout';

TwoColumnLayout Template Example

// templates/TwoColumnLayout/TwoColumnLayout.tsx
import React from 'react';
import styles from './TwoColumnLayout.module.css';

export interface TwoColumnLayoutProps {
  /** Left column (usually main content) */
  main: React.ReactNode;
  /** Right column (usually sidebar) */
  sidebar: React.ReactNode;
  /** Sidebar position */
  sidebarPosition?: 'left' | 'right';
  /** Sidebar width */
  sidebarWidth?: 'narrow' | 'medium' | 'wide';
  /** Sticky sidebar */
  stickySidebar?: boolean;
  /** Reverse on mobile (show sidebar first) */
  reverseMobile?: boolean;
  /** Gap between columns */
  gap?: 'sm' | 'md' | 'lg';
}

export const TwoColumnLayout: React.FC<TwoColumnLayoutProps> = ({
  main,
  sidebar,
  sidebarPosition = 'right',
  sidebarWidth = 'medium',
  stickySidebar = false,
  reverseMobile = false,
  gap = 'md',
}) => {
  const layoutClass = [
    styles.layout,
    styles[`sidebar-${sidebarPosition}`],
    styles[`width-${sidebarWidth}`],
    styles[`gap-${gap}`],
    reverseMobile && styles.reverseMobile,
  ]
    .filter(Boolean)
    .join(' ');

  const sidebarClass = [
    styles.sidebar,
    stickySidebar && styles.sticky,
  ]
    .filter(Boolean)
    .join(' ');

  return (
    <div className={layoutClass}>
      <main className={styles.main}>{main}</main>
      <aside className={sidebarClass}>{sidebar}</aside>
    </div>
  );
};

TwoColumnLayout.displayName = 'TwoColumnLayout';

Best Practices

1. Use Placeholder Content

// GOOD: Template with placeholder content slots
const ProductDetailLayout = ({
  productGallery,    // Placeholder for gallery component
  productInfo,       // Placeholder for product details
  productTabs,       // Placeholder for tabs
  relatedProducts,   // Placeholder for recommendations
}) => (
  <div>
    <section>{productGallery}</section>
    <section>{productInfo}</section>
    <section>{productTabs}</section>
    <section>{relatedProducts}</section>
  </div>
);

// BAD: Template with hardcoded content
const ProductDetailLayout = ({ product }) => (
  <div>
    <ProductGallery images={product.images} />      {/* Too specific */}
    <h1>{product.name}</h1>                          {/* Real content */}
    <p>{product.description}</p>
  </div>
);

2. Define Clear Content Areas

// GOOD: Clear, named content slots
interface PageTemplateProps {
  header: React.ReactNode;
  hero?: React.ReactNode;
  main: React.ReactNode;
  sidebar?: React.ReactNode;
  footer: React.ReactNode;
}

// BAD: Generic children only
interface PageTemplateProps {
  children: React.ReactNode;
}

3. Handle Responsive Layouts

// GOOD: Responsive considerations built-in
const DashboardLayout = ({ sidebar, main }) => (
  <div className={styles.layout}>
    <aside className={styles.sidebar}>{sidebar}</aside>
    <main className={styles.main}>{main}</main>
  </div>
);

// CSS handles responsive behavior
// .sidebar { @media (max-width: 768px) { display: none; } }

4. Keep Templates Thin

// GOOD: Template just arranges organisms
const MainLayout = ({ header, main, footer }) => (
  <div className={styles.layout}>
    <div className={styles.header}>{header}</div>
    <div className={styles.main}>{main}</div>
    <div className={styles.footer}>{footer}</div>
  </div>
);

// BAD: Template with business logic
const MainLayout = ({ userId }) => {
  const user = useUser(userId);          // Fetching data
  const isAdmin = user?.role === 'admin'; // Business logic

  return (
    <div>
      <Header user={user} showAdmin={isAdmin} />
      {/* ... */}
    </div>
  );
};

Anti-Patterns to Avoid

1. Templates with Real Content

// BAD: Hardcoded real content
const HomepageLayout = () => (
  <div>
    <h1>Welcome to Our Store</h1>           {/* Real content! */}
    <p>Shop our latest collection...</p>    {/* Real content! */}
  </div>
);

// GOOD: Content passed as props/children
const HomepageLayout = ({ heroTitle, heroDescription }) => (
  <div>
    <h1>{heroTitle}</h1>
    <p>{heroDescription}</p>
  </div>
);

2. Over-Nested Templates

// BAD: Templates containing templates
const AppLayout = () => (
  <BaseLayout>
    <AuthLayout>
      <DashboardLayout>
        {/* Too much nesting */}
      </DashboardLayout>
    </AuthLayout>
  </BaseLayout>
);

// GOOD: Choose appropriate template directly
const AppPage = () => (
  <DashboardLayout>
    {/* Content */}
  </DashboardLayout>
);

3. Templates with Too Many Props

// BAD: Too many configuration options
interface LayoutProps {
  showHeader: boolean;
  showFooter: boolean;
  showSidebar: boolean;
  sidebarPosition: 'left' | 'right';
  headerVariant: 'default' | 'minimal' | 'transparent';
  footerVariant: 'default' | 'minimal';
  maxWidth: 'sm' | 'md' | 'lg' | 'xl';
  // ... 20 more props
}

// GOOD: Create separate templates
const FullPageLayout = ({ ... }) => { ... };
const MinimalLayout = ({ ... }) => { ... };
const SidebarLayout = ({ ... }) => { ... };

Template Composition Patterns

Nested Layouts

// Base layout for all pages
const BaseLayout = ({ children }) => (
  <div className="base">
    <SkipLink />
    {children}
  </div>
);

// Marketing layout extending base
const MarketingLayout = ({ children }) => (
  <BaseLayout>
    <MarketingHeader />
    <main>{children}</main>
    <MarketingFooter />
  </BaseLayout>
);

// App layout extending base
const AppLayout = ({ children }) => (
  <BaseLayout>
    <AppHeader />
    <main>{children}</main>
  </BaseLayout>
);

Slot-Based Layouts

interface SlotLayoutProps {
  slots: {
    header?: React.ReactNode;
    sidebar?: React.ReactNode;
    main: React.ReactNode;
    footer?: React.ReactNode;
  };
}

const SlotLayout: React.FC<SlotLayoutProps> = ({ slots }) => (
  <div className={styles.layout}>
    {slots.header && <header>{slots.header}</header>}
    <div className={styles.body}>
      {slots.sidebar && <aside>{slots.sidebar}</aside>}
      <main>{slots.main}</main>
    </div>
    {slots.footer && <footer>{slots.footer}</footer>}
  </div>
);

When to Use This Skill

  • Creating page structure patterns
  • Building reusable layout components
  • Establishing consistent page architectures
  • Setting up responsive frameworks
  • Defining content slot patterns

Related Skills

  • atomic-design-fundamentals - Core methodology overview
  • atomic-design-organisms - Building complex organisms
  • atomic-design-integration - Framework-specific patterns

平台分布

Claude Code

28.34%
按下载量换算153

OpenCode

25.11%
按下载量换算135

Codex

17.95%
按下载量换算97

Antigravity

12.17%
按下载量换算66

Cursor

7.86%
按下载量换算42

Gemini CLI

3.54%
按下载量换算19

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限未标注

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

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills