spark-component-token
Create or update a token file in the Token folder in Sources of a spark-ios-component-XXX and add or update unit tests.
Files9
View on GitHubSKILL.md.claude/skills/spark-component-token/SKILL.md
GitHubAdd Repository Skill
Overview & Prerequisites
This skill guides you to implement/update a token in spark component.
Component Selection
Parameter Handling:
If the skill is invoked with a parameter (e.g.,
/spark-component-token button):- Use the parameter as the component name
- Verify the folder exists in
Modules/Components/{component-name}/ - If found, use that component and skip the selection step
If no parameter is provided:
- List all folders in the
Modules/Components/directory - Use AskUserQuestion to let the user select ONE component from the list
- Format: Display folder names as options (e.g., "button", "card", "checkbox")
- List all folders in the
Once the component is selected, all operations must be performed in Modules/Components/{component-name}/ folder.
Use the files in the template folder as reference to manage the token and the unit tests. See Modules/Components/Chip/Sources/Core/Token for a full real-world example.
The template uses
Border,Size, andTypographypurely as illustrations of three recurring patterns (see Rules below). A real component's token categories are whatever it actually needs — e.g.Opacity,Layout,Spacing,Color,Icon,Animation, ... Determine the category names and count from the component's design/usage, not from the template names.
Rules
The Token file must respect theses rules :
- must be located in Sources/Core/Token and in Tests/UnitTests/Token.
- the root file is named XXXToken.swift and contains a
public struct XXXToken: Equatablewith one property per token category the component actually needs (there is no fixed list or fixed count — could be one category or a dozen), plus apublic init(theme: any Theme)that forwards the theme to every category that needs it. - each token category lives in its own file named XXXToken+CategoryName.swift (e.g.
XXXToken+Opacity.swift), containing apublic extension XXXTokenwith a nestedstruct CategoryName: Equatable. - a category that only exposes fixed constants (no theme-dependent values, illustrated by
Sizein the template) must have a parameterlesspublic init(). On the root struct, its property is a stored default value (public let size = Size()), not assigned in the rootinit(theme:)body. - a category that depends on the theme (illustrated by
Borderin the template) must havepublic init(theme: any Theme), and its property must be assigned in the rootinit(theme:). - a category holding an
any ColorToken,any TypographyFontToken, or any other non-natively-Equatableexistential (illustrated byTypographyin the template) must provide a manualstatic func ==using.equals()— the synthesizedEquatableconformance does not work for existential protocol types. - every public struct and property must be documented with a doc comment (
///). - the root XXXToken.swift file must have a top-level doc comment that:
- lists every category actually present, each with a doc link (e.g.
XXXToken/CategoryName: description) - includes a "Creating a Custom XXX" section with a full SwiftUI usage example
- includes a section showing how to use individual sub-structs directly (e.g. a constant-only category instantiated without a theme, if the component has one)
- lists every category actually present, each with a doc link (e.g.
Workflow
- Add/Update the code.
- Add/Update the documentation (the token file and its categories are always public).
- Run swiftlint
$ swiftlint. - Run sourcery
$ sourcery - Implement the unit tests. Read theses folders to get mocks :
- spark-ios-component-XXX/Sources/Testing
- spark-ios-common/Sources/Testing
- spark-ios-theming/Sources/Testing
Code Conventions
- File headers follow pattern:
Created by {firstname.lastname} on DD/MM/YYYY - Copyright line includes current year
- No empty lines contain whitespace or tabs
- All class members accessed with
self. - Protocol marked with
// sourcery: AutoMockable - Proper MARK comments in place
Test Implementation
- Tests must be written in Swift Testing framework
- Proper imports (SparkComponentXXX, SparkCommon, SparkTheming, @testable, @_spi(SI_SPI) @testable import SparkComponentXXXTesting, Testing, ...)
- Use
ThemeGeneratedMock.mocked()andThemeGeneratedMock.mocked2()to cover theme-dependent values and equality/inequality - For each category, test: initialization sets every property from the theme (or from its fixed constant), equatable returns true when equal, equatable returns false when different
- The root
XXXTokenTestsmust verify that each property matches a freshly-constructed instance of its own sub-struct (e.g.#expect(token.border == XXXToken.Border(theme: self.theme))), plus equatable true/false at the root level
When to Ask for Help
If you encounter:
- A token value that doesn't map to any existing theme property
- A property type that isn't natively
Equatableand it's unclear whether a manual==is needed - Component doesn't follow standard patterns
Use AskUserQuestion to clarify with the user before proceeding.