agentsclimarketplace

Figma ios component state recognition

Skill mythkiven/figma-ios-codegen/.cursor/skills/figma-ios-component-state-recognition

从 figma-ios-preload-data 数据包(design.json)提取组件各状态的视觉特征(背景色、边框、文字颜色、字体), 生成带 updateAppearance() 的状态切换代码。 Use when extracting visual states from Figma components, generating selected/unselected/disabled state code, or when user asks about 选中态、状态切换、updateAppearance。From its SKILL.md

Install
npx -y skills add mythkiven/figma-ios-codegen --skill figma-ios-component-state-recognition

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.5 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

Figma 组件状态特征提取与代码生成

职责边界

  • ✅ 从数据包 design.json 识别组件有哪些视觉状态(selected/unselected/disabled/enabled)
  • ✅ 提取每种状态的视觉特征(背景色、边框、文字颜色、字体字重)
  • ✅ 生成 updateAppearance() 状态切换代码(Pattern A / Pattern B)
  • ✅ 识别默认选中项
  • ❌ 不识别组件是什么类型(Selector/Stepper/Toggle)→ 见 figma-ios-standard-components
  • ❌ 不处理点击后的交互逻辑 → 见 figma-ios-selection-interaction
  • ❌ 不处理动画效果

⚡ QUICK_REF

⚠️  数据来源:design.json[node_id](fills / strokes / font / iconfont 已规范化)
          assets/ios/manifest.json(状态图)
          comments.json(评论修正状态颜色)
          禁止跨组件颜色复用(不同组件视觉规范可能不同)

同类节点中,主题色特征 = 已选中;灰色/低透明度 = 未选中
状态差异维度:背景色 / 边框 / 文字颜色 / 字体字重(Regular ↔ Medium)
默认选中:背景/边框/文字用了主题色的那个节点
Pattern A(简单图形)→ 代码绘制背景 + updateAppearance()
Pattern B(复杂图形)→ UIImageView + 两张 asset + updateAppearance()
生成后必查:updateAppearance() 覆盖了所有差异维度 + configure() 里调用了它

状态识别规则

规则 0:数据来源

唯一数据来源{data_dir}/design.json(图片状态切换:assets/ios/manifest.json

字段已规范化:

  • node.fills[].color / node.strokes[].colorrgba(...)TEXT 文字色也在 fills,无 text.color
  • node.text(字符串文案)/ node.font.{family,weight,size}
  • node.iconfont.{symbol,color,size_hint}
  • node.corner_radius / node.opacity
  • node.comments[](高优先级覆盖,详见 figma-ios-comments-integration)

阶段 2 不再调 MCP / REST,也不需要判断数据优先级(已在数据包内固化)。

禁止跨组件颜色复用

❌ 禁止:品类 Cell 参考性别按钮的颜色
✅ 允许:在代码注释中标注"⚠️  参考节点 X:Y(设计模式相同)"

如果某节点缺字段

1. 检查 design.json[node_id] 是否存在该节点
2. 仍缺失 → 代码加 TODO 注释 + 用语义默认色,并在 README "待人工确认" 列出

规则 A:同类节点的差异 = 状态差异

对比并列的同类节点,找视觉差异:

特征已选中(Selected)未选中(Unselected)字段
背景色主题色(如 #FFF606 alpha 0.1)灰色 / 低透明度node.fills[].color
边框主题色边框 0.5~1px无边框 或 灰色node.strokes[].color / node.stroke_weight
文字颜色主题色白色 80% / 灰色TEXT 节点 fills[].color
字体字重Medium / BoldRegularnode.font.weight
背景图片已选中 asset未选中 assetassets/ios/manifest.json

规则 B:识别默认选中项

按以下优先级判断哪个节点是默认已选中:

  1. 背景色使用主题色 → 已选中
  2. 边框色使用主题色 → 已选中
  3. 文字颜色使用主题色 → 已选中
  4. 字体字重为 Medium / Bold → 已选中
  5. 节点名包含 selected / 选中 / active → 已选中

规则 C:Stepper 的 enabled / disabled

对比减少/增加按钮的 node.opacity(数据包字段):

  • opacity = 1.0 → enabled
  • opacity < 0.5 → disabled(灰化状态)

代码生成

Pattern A:代码绘制背景(纯色/圆角/简单边框)

⚠️ 命名注意:UIKit 属性名冲突详见 figma-ios-vector-vs-code "禁止使用的属性名"(如 UICollectionViewCell.backgroundView

private class CategoryButton: UIControl {

    private var isButtonSelected: Bool = false

    private lazy var backgroundView: UIView = {
        let v = UIView()
        v.layer.cornerRadius = 8
        v.isUserInteractionEnabled = false
        return v
    }()

    private lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        return label
    }()

    init(title: String, isSelected: Bool) {
        self.isButtonSelected = isSelected
        super.init(frame: .zero)
        setupUI()
        setupConstraints()
        updateAppearance()
    }

    required init?(coder: NSCoder) { fatalError() }

    func configure(with title: String, isSelected: Bool) {
        titleLabel.text = title
        isButtonSelected = isSelected
        updateAppearance()  // ← 必须调用
    }

    private func updateAppearance() {
        if isButtonSelected {
            // 从 Figma 已选中节点提取
            backgroundView.backgroundColor = MKUIStyle.mk_cXX() /* color_map: #FFF606 alpha=0.1 */
            backgroundView.layer.borderColor = MKUIStyle.mk_cXX() /* color_map: #FFF606 */.cgColor
            backgroundView.layer.borderWidth = 0.946
            titleLabel.textColor = MKUIStyle.mk_cXX() /* color_map: #FFF606 */
            titleLabel.font = MKUIStyle.mk_f14_m() /* font_map */
        } else {
            // 从 Figma 未选中节点提取
            backgroundView.backgroundColor = /* color_map 命中或 UIColor fallback */
            backgroundView.layer.borderWidth = 0  // 未选中时移除边框
            titleLabel.textColor = /* color_map */
            titleLabel.font = MKUIStyle.mk_f14() /* font_map */
        }
    }
}

Pattern B:图片背景(渐变/阴影/特殊形状)

private func updateAppearance() {
    if isButtonSelected {
        // asset 名称从 {data_dir}/assets/ios/manifest.json 取(见 figma-ios-image-assets-download)
        backgroundImageView.image = UIImage(named: "img_xxxxx_selected")
        titleLabel.textColor = MKUIStyle.mk_cXX() /* color_map: #FFF606 */
        titleLabel.font = /* font_map */
    } else {
        backgroundImageView.image = UIImage(named: "img_xxxxx_unselected")
        titleLabel.textColor = /* color_map */
        titleLabel.font = /* font_map */
    }
}

何时用 Pattern A vs B:→ 见 figma-ios-vector-vs-code


常见错误

错误修复案例
❌ 跨组件复用颜色(最常见)design.json[node] 读取该组件自己的颜色品类 Cell 错误复用了性别按钮的文本颜色
❌ 数据包缺少节点文本颜色标注 TODO + 在 README "待人工确认" 列出,向 figma-ios-preload-data 反馈SYMBOL 节点 TEXT 颜色丢失
所有按钮用相同样式,忽略状态差异updateAppearance() 中根据 isButtonSelected 分支处理
字体不随状态变化(固定 Regular)已选中用 mk_f*_m(),未选中用 mk_f*()
边框始终存在未选中时设 borderWidth = 0
configure() 中未调用 updateAppearance()每次更新 isButtonSelected 后必须调用

生成后自检

✅ 每个有状态的组件都有 updateAppearance() 方法
✅ updateAppearance() 覆盖:背景色、边框(含 width=0)、文字颜色、字体字重
✅ configure() 或 init() 中调用了 updateAppearance()
✅ 默认选中项正确识别(主题色 → 已选中)
✅ 字体随状态切换(Regular ↔ Medium)

相关

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.