Token导航 LogoToken导航

Agent Skill · 研究检索

atomic-design-molecules(原子设计分子)

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

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

总安装 1,224周安装 51GitHub Stars 142下载 408核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

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

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

这个 Skill 是做什么的

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

atomic-design-molecules 组合多个原子形成功能性 UI 元素,如搜索栏、表单字段。适用于构建单一目的、可复用、最少内部状态的复合组件。仅由原子构成,不引入其他分子,确保职责清晰与测试可行性。使用前应确保原子已稳定,避免频繁调整导致分子重构成本。

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

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

上手步骤

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-molecules 怎么安装?

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

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

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

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

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

atomic-design-molecules 是免费的吗?

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

atomic-design-molecules 用的人多吗?

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

atomic-design-molecules 安全吗?

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

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

值得选的地方

  • 同时适配 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-molecules

原子设计分子 · 本页

1,224142权限未标注MIT通过

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

SKILL.md 原文

Atomic Design: Molecules

Master the creation of molecule components - functional groups of atoms that work together as a unit. Molecules combine multiple atoms to create more complex, purposeful UI elements.

What Are Molecules?

Molecules are the first level of composition in Atomic Design. They are:

  • Composed of atoms only: Never include other molecules
  • Single purpose: Do one thing well
  • Functional units: Atoms working together for a specific task
  • Reusable: Used across different organisms and contexts
  • Minimally stateful: May have limited internal state for UI concerns

Common Molecule Types

Form Molecules

  • Form fields (label + input + error)
  • Search forms (input + button)
  • Toggle groups (label + toggle)
  • Date pickers (input + calendar trigger)
  • File uploaders (dropzone + button)

Navigation Molecules

  • Nav items (icon + text + indicator)
  • Breadcrumb items (link + separator)
  • Pagination controls (buttons + page indicator)
  • Tab items (icon + label)

Display Molecules

  • Media objects (avatar + text)
  • Card headers (title + subtitle + action)
  • List items (checkbox + content + actions)
  • Stat displays (label + value + trend)

Action Molecules

  • Button groups (multiple buttons)
  • Dropdown triggers (button + icon)
  • Icon buttons (icon + tooltip)
  • Action menus (button + menu items)

FormField Molecule Example

Complete Implementation

// molecules/FormField/FormField.tsx
import React from 'react';
import { Label } from '@/components/atoms/Label';
import { Input, type InputProps } from '@/components/atoms/Input';
import { Text } from '@/components/atoms/Typography';
import styles from './FormField.module.css';

export interface FormFieldProps extends InputProps {
  /** Field label */
  label: string;
  /** Unique field identifier */
  name: string;
  /** Help text below input */
  helpText?: string;
  /** Error message */
  error?: string;
  /** Required field indicator */
  required?: boolean;
}

export const FormField = React.forwardRef<HTMLInputElement, FormFieldProps>(
  (
    {
      label,
      name,
      helpText,
      error,
      required = false,
      id,
      className,
      ...inputProps
    },
    ref
  ) => {
    const fieldId = id || `field-${name}`;
    const helpTextId = helpText ? `${fieldId}-help` : undefined;
    const errorId = error ? `${fieldId}-error` : undefined;

    const describedBy = [helpTextId, errorId].filter(Boolean).join(' ') || undefined;

    return (
      <div className={`${styles.field} ${className || ''}`}>
        <Label htmlFor={fieldId} required={required} disabled={inputProps.disabled}>
          {label}
        </Label>

        <Input
          ref={ref}
          id={fieldId}
          name={name}
          hasError={!!error}
          aria-describedby={describedBy}
          aria-required={required}
          {...inputProps}
        />

        {helpText && !error && (
          <Text id={helpTextId} size="sm" color="muted" className={styles.helpText}>
            {helpText}
          </Text>
        )}

        {error && (
          <Text id={errorId} size="sm" color="danger" className={styles.error} role="alert">
            {error}
          </Text>
        )}
      </div>
    );
  }
);

FormField.displayName = 'FormField';
/* molecules/FormField/FormField.module.css */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.helpText {
  margin-top: 2px;
}

.error {
  margin-top: 2px;
  display: flex;
  align-items: center;
  gap: 4px;
}

SearchForm Molecule Example

// molecules/SearchForm/SearchForm.tsx
import React, { useState, useCallback } from 'react';
import { Input } from '@/components/atoms/Input';
import { Button } from '@/components/atoms/Button';
import { Icon } from '@/components/atoms/Icon';
import styles from './SearchForm.module.css';

export interface SearchFormProps {
  /** Placeholder text */
  placeholder?: string;
  /** Initial search value */
  defaultValue?: string;
  /** Submit handler */
  onSubmit: (query: string) => void;
  /** Change handler for live search */
  onChange?: (query: string) => void;
  /** Loading state */
  isLoading?: boolean;
  /** Size variant */
  size?: 'sm' | 'md' | 'lg';
  /** Show clear button */
  clearable?: boolean;
}

export const SearchForm: React.FC<SearchFormProps> = ({
  placeholder = 'Search...',
  defaultValue = '',
  onSubmit,
  onChange,
  isLoading = false,
  size = 'md',
  clearable = true,
}) => {
  const [query, setQuery] = useState(defaultValue);

  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const value = e.target.value;
      setQuery(value);
      onChange?.(value);
    },
    [onChange]
  );

  const handleSubmit = useCallback(
    (e: React.FormEvent) => {
      e.preventDefault();
      onSubmit(query.trim());
    },
    [onSubmit, query]
  );

  const handleClear = useCallback(() => {
    setQuery('');
    onChange?.('');
  }, [onChange]);

  return (
    <form className={styles.form} onSubmit={handleSubmit} role="search">
      <Input
        type="search"
        value={query}
        onChange={handleChange}
        placeholder={placeholder}
        size={size}
        leftAddon={<Icon name="search" size="sm" />}
        rightAddon={
          clearable && query ? (
            <button
              type="button"
              onClick={handleClear}
              className={styles.clearButton}
              aria-label="Clear search"
            >
              <Icon name="x" size="sm" />
            </button>
          ) : undefined
        }
        aria-label="Search query"
      />
      <Button type="submit" size={size} isLoading={isLoading}>
        Search
      </Button>
    </form>
  );
};

SearchForm.displayName = 'SearchForm';
/* molecules/SearchForm/SearchForm.module.css */
.form {
  display: flex;
  gap: 8px;
  align-items: stretch;
}

.clearButton {
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 4px;
  color: var(--color-neutral-500);
  transition: color 150ms;
}

.clearButton:hover {
  color: var(--color-neutral-700);
}

MediaObject Molecule Example

// molecules/MediaObject/MediaObject.tsx
import React from 'react';
import { Avatar, type AvatarProps } from '@/components/atoms/Avatar';
import { Text, Heading } from '@/components/atoms/Typography';
import styles from './MediaObject.module.css';

export interface MediaObjectProps {
  /** Avatar image source */
  avatarSrc?: string;
  /** Avatar alt text */
  avatarAlt: string;
  /** Avatar initials fallback */
  avatarInitials?: string;
  /** Avatar size */
  avatarSize?: AvatarProps['size'];
  /** Primary text/title */
  title: React.ReactNode;
  /** Secondary text/subtitle */
  subtitle?: React.ReactNode;
  /** Additional metadata */
  meta?: React.ReactNode;
  /** Right-aligned action element */
  action?: React.ReactNode;
  /** Alignment of content */
  align?: 'top' | 'center' | 'bottom';
  /** Additional class name */
  className?: string;
}

export const MediaObject: React.FC<MediaObjectProps> = ({
  avatarSrc,
  avatarAlt,
  avatarInitials,
  avatarSize = 'md',
  title,
  subtitle,
  meta,
  action,
  align = 'center',
  className,
}) => {
  const classNames = [styles.mediaObject, styles[`align-${align}`], className]
    .filter(Boolean)
    .join(' ');

  return (
    <div className={classNames}>
      <Avatar
        src={avatarSrc}
        alt={avatarAlt}
        initials={avatarInitials}
        size={avatarSize}
      />

      <div className={styles.content}>
        <div className={styles.title}>{title}</div>
        {subtitle && (
          <Text size="sm" color="muted" className={styles.subtitle}>
            {subtitle}
          </Text>
        )}
        {meta && (
          <Text size="xs" color="muted" className={styles.meta}>
            {meta}
          </Text>
        )}
      </div>

      {action && <div className={styles.action}>{action}</div>}
    </div>
  );
};

MediaObject.displayName = 'MediaObject';

NavItem Molecule Example

// molecules/NavItem/NavItem.tsx
import React from 'react';
import { Icon } from '@/components/atoms/Icon';
import { Badge } from '@/components/atoms/Badge';
import styles from './NavItem.module.css';

export interface NavItemProps {
  /** Navigation icon */
  icon?: string;
  /** Item label */
  label: string;
  /** Link destination */
  href: string;
  /** Active state */
  isActive?: boolean;
  /** Badge count */
  badge?: number;
  /** Disabled state */
  disabled?: boolean;
  /** Click handler */
  onClick?: (e: React.MouseEvent) => void;
}

export const NavItem: React.FC<NavItemProps> = ({
  icon,
  label,
  href,
  isActive = false,
  badge,
  disabled = false,
  onClick,
}) => {
  const classNames = [
    styles.navItem,
    isActive && styles.active,
    disabled && styles.disabled,
  ]
    .filter(Boolean)
    .join(' ');

  const handleClick = (e: React.MouseEvent) => {
    if (disabled) {
      e.preventDefault();
      return;
    }
    onClick?.(e);
  };

  return (
    <a
      href={href}
      className={classNames}
      onClick={handleClick}
      aria-current={isActive ? 'page' : undefined}
      aria-disabled={disabled}
    >
      {icon && <Icon name={icon} size="sm" className={styles.icon} />}
      <span className={styles.label}>{label}</span>
      {badge !== undefined && badge > 0 && (
        <Badge variant="primary" size="sm" className={styles.badge}>
          {badge > 99 ? '99+' : badge}
        </Badge>
      )}
    </a>
  );
};

NavItem.displayName = 'NavItem';

CardHeader Molecule Example

// molecules/CardHeader/CardHeader.tsx
import React from 'react';
import { Heading, Text } from '@/components/atoms/Typography';
import { Icon } from '@/components/atoms/Icon';
import { Button } from '@/components/atoms/Button';
import styles from './CardHeader.module.css';

export interface CardHeaderProps {
  /** Card title */
  title: string;
  /** Optional subtitle */
  subtitle?: string;
  /** Title icon */
  icon?: string;
  /** Action button label */
  actionLabel?: string;
  /** Action button click handler */
  onAction?: () => void;
  /** Additional class name */
  className?: string;
}

export const CardHeader: React.FC<CardHeaderProps> = ({
  title,
  subtitle,
  icon,
  actionLabel,
  onAction,
  className,
}) => {
  return (
    <div className={`${styles.header} ${className || ''}`}>
      <div className={styles.left}>
        {icon && <Icon name={icon} size="md" className={styles.icon} />}
        <div className={styles.titles}>
          <Heading level={3} className={styles.title}>
            {title}
          </Heading>
          {subtitle && (
            <Text size="sm" color="muted">
              {subtitle}
            </Text>
          )}
        </div>
      </div>

      {actionLabel && onAction && (
        <Button variant="tertiary" size="sm" onClick={onAction}>
          {actionLabel}
        </Button>
      )}
    </div>
  );
};

CardHeader.displayName = 'CardHeader';

ListItem Molecule Example

// molecules/ListItem/ListItem.tsx
import React from 'react';
import { Checkbox } from '@/components/atoms/Checkbox';
import { Text } from '@/components/atoms/Typography';
import { Icon } from '@/components/atoms/Icon';
import styles from './ListItem.module.css';

export interface ListItemProps {
  /** Item ID for selection */
  id: string;
  /** Primary content */
  primary: React.ReactNode;
  /** Secondary content */
  secondary?: React.ReactNode;
  /** Left icon */
  icon?: string;
  /** Whether item is selectable */
  selectable?: boolean;
  /** Selection state */
  selected?: boolean;
  /** Selection change handler */
  onSelect?: (id: string, selected: boolean) => void;
  /** Right-aligned action buttons */
  actions?: React.ReactNode;
  /** Click handler */
  onClick?: () => void;
}

export const ListItem: React.FC<ListItemProps> = ({
  id,
  primary,
  secondary,
  icon,
  selectable = false,
  selected = false,
  onSelect,
  actions,
  onClick,
}) => {
  const classNames = [
    styles.listItem,
    onClick && styles.clickable,
    selected && styles.selected,
  ]
    .filter(Boolean)
    .join(' ');

  const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    onSelect?.(id, e.target.checked);
  };

  return (
    <div className={classNames} onClick={onClick} role={onClick ? 'button' : undefined}>
      {selectable && (
        <Checkbox
          checked={selected}
          onChange={handleCheckboxChange}
          aria-label={`Select ${primary}`}
          onClick={(e) => e.stopPropagation()}
        />
      )}

      {icon && <Icon name={icon} size="md" className={styles.icon} />}

      <div className={styles.content}>
        <div className={styles.primary}>{primary}</div>
        {secondary && (
          <Text size="sm" color="muted" className={styles.secondary}>
            {secondary}
          </Text>
        )}
      </div>

      {actions && (
        <div className={styles.actions} onClick={(e) => e.stopPropagation()}>
          {actions}
        </div>
      )}
    </div>
  );
};

ListItem.displayName = 'ListItem';

ButtonGroup Molecule Example

// molecules/ButtonGroup/ButtonGroup.tsx
import React from 'react';
import { Button, type ButtonProps } from '@/components/atoms/Button';
import styles from './ButtonGroup.module.css';

export interface ButtonGroupItem {
  id: string;
  label: string;
  icon?: string;
  disabled?: boolean;
}

export interface ButtonGroupProps {
  /** Button items */
  items: ButtonGroupItem[];
  /** Selected item ID(s) */
  value?: string | string[];
  /** Selection change handler */
  onChange?: (value: string | string[]) => void;
  /** Allow multiple selection */
  multiple?: boolean;
  /** Size variant */
  size?: ButtonProps['size'];
  /** Disabled state */
  disabled?: boolean;
}

export const ButtonGroup: React.FC<ButtonGroupProps> = ({
  items,
  value = [],
  onChange,
  multiple = false,
  size = 'md',
  disabled = false,
}) => {
  const selectedIds = Array.isArray(value) ? value : [value].filter(Boolean);

  const handleClick = (itemId: string) => {
    if (!onChange) return;

    if (multiple) {
      const newValue = selectedIds.includes(itemId)
        ? selectedIds.filter((id) => id !== itemId)
        : [...selectedIds, itemId];
      onChange(newValue);
    } else {
      onChange(itemId);
    }
  };

  return (
    <div className={styles.group} role="group">
      {items.map((item) => {
        const isSelected = selectedIds.includes(item.id);

        return (
          <Button
            key={item.id}
            variant={isSelected ? 'primary' : 'secondary'}
            size={size}
            disabled={disabled || item.disabled}
            onClick={() => handleClick(item.id)}
            aria-pressed={isSelected}
            className={styles.button}
          >
            {item.label}
          </Button>
        );
      })}
    </div>
  );
};

ButtonGroup.displayName = 'ButtonGroup';

Stat Molecule Example

// molecules/Stat/Stat.tsx
import React from 'react';
import { Text, Heading } from '@/components/atoms/Typography';
import { Icon } from '@/components/atoms/Icon';
import styles from './Stat.module.css';

export type TrendDirection = 'up' | 'down' | 'neutral';

export interface StatProps {
  /** Stat label */
  label: string;
  /** Stat value */
  value: string | number;
  /** Previous value for comparison */
  previousValue?: string | number;
  /** Trend direction */
  trend?: TrendDirection;
  /** Trend percentage */
  trendValue?: string;
  /** Stat icon */
  icon?: string;
  /** Help text */
  helpText?: string;
}

export const Stat: React.FC<StatProps> = ({
  label,
  value,
  trend,
  trendValue,
  icon,
  helpText,
}) => {
  const getTrendColor = (direction?: TrendDirection) => {
    switch (direction) {
      case 'up':
        return 'success';
      case 'down':
        return 'danger';
      default:
        return 'muted';
    }
  };

  const getTrendIcon = (direction?: TrendDirection) => {
    switch (direction) {
      case 'up':
        return 'trending-up';
      case 'down':
        return 'trending-down';
      default:
        return 'minus';
    }
  };

  return (
    <div className={styles.stat}>
      <div className={styles.header}>
        {icon && <Icon name={icon} size="sm" className={styles.icon} />}
        <Text size="sm" color="muted">
          {label}
        </Text>
      </div>

      <div className={styles.value}>
        <Heading level={2}>{value}</Heading>
      </div>

      {(trend || trendValue) && (
        <div className={styles.trend}>
          {trend && (
            <Icon
              name={getTrendIcon(trend)}
              size="xs"
              color={`var(--color-${getTrendColor(trend)}-500)`}
            />
          )}
          {trendValue && (
            <Text size="sm" color={getTrendColor(trend)}>
              {trendValue}
            </Text>
          )}
        </div>
      )}

      {helpText && (
        <Text size="xs" color="muted" className={styles.helpText}>
          {helpText}
        </Text>
      )}
    </div>
  );
};

Stat.displayName = 'Stat';

Best Practices

1. Keep Molecules Focused

// GOOD: Single, clear purpose
const SearchForm = () => (
  <form>
    <Input placeholder="Search..." />
    <Button>Search</Button>
  </form>
);

// BAD: Doing too much
const SearchWithFiltersAndResults = () => (
  <div>
    <Input />
    <Button>Search</Button>
    <FilterDropdown />       {/* Should be separate molecule */}
    <ResultsList />          {/* Should be organism */}
    <Pagination />           {/* Should be separate molecule */}
  </div>
);

2. Only Import from Atoms

// GOOD: Only uses atoms
import { Button } from '@/components/atoms/Button';
import { Input } from '@/components/atoms/Input';
import { Icon } from '@/components/atoms/Icon';

// BAD: Importing from other molecules
import { FormField } from '@/components/molecules/FormField'; // Wrong level!
import { Button } from '@/components/atoms/Button';

3. Compose Props Carefully

// GOOD: Clear prop forwarding
interface SearchFormProps {
  onSubmit: (query: string) => void;
  inputProps?: Partial<InputProps>;
  buttonProps?: Partial<ButtonProps>;
}

// BAD: Confusing prop naming
interface SearchFormProps {
  inputPlaceholder?: string;
  inputDisabled?: boolean;
  inputSize?: string;
  buttonVariant?: string;
  buttonDisabled?: boolean;
  // ... endless prop forwarding
}

4. Manage Internal State Minimally

// GOOD: Minimal UI state
const SearchForm = ({ onSubmit }) => {
  const [query, setQuery] = useState('');

  return (
    <form onSubmit={() => onSubmit(query)}>
      <Input value={query} onChange={(e) => setQuery(e.target.value)} />
      <Button type="submit">Search</Button>
    </form>
  );
};

// BAD: Too much internal state
const SearchForm = () => {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);  // Should be in parent
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetchResults(query).then(setResults);  // Business logic in molecule!
  }, [query]);
};

Anti-Patterns to Avoid

1. Molecules Containing Molecules

// BAD: Molecule importing another molecule
// molecules/ComplexForm/ComplexForm.tsx
import { FormField } from '../FormField';  // Wrong!
import { SearchForm } from '../SearchForm'; // Wrong!

// GOOD: Keep at atom level, or promote to organism
// organisms/ComplexForm/ComplexForm.tsx
import { FormField } from '@/components/molecules/FormField';
import { SearchForm } from '@/components/molecules/SearchForm';

2. Business Logic in Molecules

// BAD: API calls in molecule
const SearchForm = ({ apiEndpoint }) => {
  const handleSubmit = async (query) => {
    const results = await fetch(`${apiEndpoint}?q=${query}`);
    // Processing results here...
  };
};

// GOOD: Delegate to parent
const SearchForm = ({ onSubmit }) => {
  const handleSubmit = (query) => {
    onSubmit(query); // Parent handles API logic
  };
};

3. Over-Abstraction

// BAD: Unnecessary molecule for single atom
const IconWrapper = ({ icon }) => <Icon name={icon} />;

// GOOD: Just use the atom directly
<Icon name="search" />

When to Use This Skill

  • Combining atoms for specific functionality
  • Creating reusable form components
  • Building navigation elements
  • Creating card and list components
  • Establishing patterns for common UI combinations

Related Skills

  • atomic-design-fundamentals - Core methodology overview
  • atomic-design-atoms - Creating atomic components
  • atomic-design-organisms - Building complex organisms

平台分布

Claude Code

26.6%
按下载量换算109

OpenCode

21.53%
按下载量换算88

Codex

17.62%
按下载量换算72

Antigravity

11.72%
按下载量换算48

Cursor

7.88%
按下载量换算32

Gemini CLI

3.52%
按下载量换算14

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限未标注

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

安装前确认

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

继续浏览同类 Skills