Icon system
Skill almasumdev/awesome-mobile-design-system-agent-skills/.github/skills/assets/icon-system
Agent skills for building and maintaining mobile design systems, tokens, and component libraries.
npx -y skills add almasumdev/awesome-mobile-design-system-agent-skills --skill icon-systemAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 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.
What its author says it does
Copied from the file, not written here
Cross-platform icon pipeline — SVG source, Android VectorDrawable, SF Symbols, Flutter/RN delivery, sizing, and parity. Use this when adding or refactoring the icon set.
SKILL.md
6.0 KB, as published. Nobody here has run it
Icon System
Instructions
Icons are part of the component library, not a loose folder of assets. One SVG source, deterministic platform outputs, tokenized sizes, and a single public API per platform.
1. One Source, Many Targets
assets/icons/
├── source/ # authoring SVG (24 × 24 grid)
│ ├── check.svg
│ ├── chevron-right.svg
│ └── ...
├── android/ # generated .xml VectorDrawables
├── ios/ # generated .xcassets (+ fallback for non-SF-Symbols)
├── flutter/ # generated IconData (from a custom font) or SVG widgets
└── rn/ # generated TypeScript components (react-native-svg)
2. Authoring Rules
- 24 × 24 grid, 1.5–2pt strokes, rounded line caps/joins by default.
- Monochrome only. Color comes from the
tintColor/colorprop driven by tokens. - No hard-coded fill; use
currentColor(fill="currentColor"/stroke="currentColor"). - Export with
viewBox="0 0 24 24"; nowidth/heightattributes. - One visual per file; do not merge states into a single SVG.
3. Android / Compose
Convert SVG → VectorDrawable with Android Studio's importer or vd-tool, then expose via a generated Icons object.
object DsIcons {
val Check: ImageVector = Icons.Filled.Check
val ChevronRight: ImageVector = vectorResource(R.drawable.ic_chevron_right)
}
@Composable
fun DsIcon(icon: ImageVector, size: Dp = 24.dp, tint: Color = LocalContentColor.current) {
Icon(imageVector = icon, contentDescription = null, tint = tint, modifier = Modifier.size(size))
}
4. iOS / SwiftUI
Prefer SF Symbols for platform idiom when an exact-match symbol exists. For brand-specific icons, ship a multicolor-capable asset catalog.
public enum DSIcon: String {
case check = "checkmark" // SF Symbol
case chevronRight = "chevron.right" // SF Symbol
case brandLogo = "ds.brand.logo" // asset catalog
}
public struct DSIconView: View {
let icon: DSIcon
let size: CGFloat
public var body: some View {
if icon.rawValue.contains(".") {
Image(systemName: icon.rawValue)
.font(.system(size: size, weight: .regular))
} else {
Image(icon.rawValue).resizable().frame(width: size, height: size)
}
}
}
Rule: never ship a bespoke checkmark on iOS when checkmark exists in SF Symbols; use the system glyph so it inherits Dynamic Type.
5. Flutter
Two acceptable approaches:
- Icon font (most efficient): generate a custom font from SVGs via FontForge / IcoMoon, declare
IconData. - Vector widgets via
flutter_svg: simpler, zero font tooling, slightly heavier runtime cost.
class DsIcons {
static const IconData check = IconData(0xe001, fontFamily: 'DsIcons');
static const IconData chevronRight = IconData(0xe002, fontFamily: 'DsIcons');
}
class DsIcon extends StatelessWidget {
const DsIcon(this.data, {super.key, this.size = 24, this.color});
final IconData data; final double size; final Color? color;
@override
Widget build(BuildContext context) => Icon(data,
size: size, color: color ?? IconTheme.of(context).color);
}
6. React Native
Generate one *.tsx per icon with react-native-svg. A bundler treeshakes unused icons.
// generated
export const IconCheck = (props: SvgProps) => (
<Svg viewBox="0 0 24 24" {...props}>
<Path d="M20 6L9 17l-5-5" stroke={props.color ?? 'currentColor'} strokeWidth={2}
strokeLinecap="round" strokeLinejoin="round" fill="none" />
</Svg>
);
export const Icon = ({ name, size = 24, color }: IconProps) => {
const C = REGISTRY[name];
return <C width={size} height={size} color={color} />;
};
7. Sizing via Tokens
{
"size": {
"icon": {
"sm": { "$value": "16px", "$type": "dimension" },
"md": { "$value": "20px", "$type": "dimension" },
"lg": { "$value": "24px", "$type": "dimension" },
"xl": { "$value": "32px", "$type": "dimension" }
}
}
}
Components accept a size variant and map to the token — not arbitrary px/dp.
8. Accessibility
- Decorative icons: explicit
null/ empty content description; never auto-generate. - Icon-only buttons: provide an accessibility label that describes the action, not the glyph ("Close", not "X").
- Minimum hit target: 44×44 iOS / 48×48 Android, regardless of icon size — pad the tap area.
9. Parity Strategy
Maintain a canonical registry (icons.json) listing every icon, its semantic name, and its per-platform mapping. A CI check fails if a name exists without a mapping on every platform.
{
"check": { "android": "ic_check", "ios": "checkmark", "flutter": 57345, "rn": "IconCheck" },
"chevron-right": { "android": "ic_chevron_right", "ios": "chevron.right", "flutter": 57346, "rn": "IconChevronRight" }
}
10. Anti-Patterns
- PNG icons in a modern mobile app (except raster app icons).
- Re-drawing SF Symbols with bespoke SVGs.
- Baked-in color inside icon source.
- Icon padding inside the SVG itself (breaks hit-testing math).
- Shipping every icon of the set in the binary; tree-shake or lazy-load rarely-used ones.
Checklist
- All icons authored as 24×24 monochrome SVGs with
currentColor. - Platform outputs generated deterministically from source; manual edits to outputs are rejected in review.
- SF Symbols used on iOS when a system equivalent exists.
- Icon sizes and colors come from tokens; no raw values in components.
-
icons.jsonregistry enforces parity; CI fails on missing mappings. - Icon-only buttons have action-describing accessibility labels and 44/48pt hit areas.