بنقرة واحدة
ui-components
Design system, UI components, Screen, Toolbar, Sheet, and localization reference.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Design system, UI components, Screen, Toolbar, Sheet, and localization reference.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Implement UI from Figma designs via MCP with a closed-loop pixel-parity check. Extract exact values (never eyeball), translate to SwiftUI, then render→diff→fix against the Figma export until it matches. Use when implementing or auditing UI against Figma.
HTTP networking layer reference — TargetType, HTTPClient, services, error handling.
Fetch CodeRabbit review comments from batch PRs and auto-fix the issues. Pushes fixes and re-requests review.
Run multiple tasks overnight as parallel PRs. Produces a PRD per task, selects skills/rules, spawns isolated agents, and reports PR links.
Run multiple tasks overnight as parallel PRs. Produces a PRD per task, selects skills/rules, spawns isolated agents, and reports PR links.
Run SwiftLint and xcodebuild to verify the project compiles cleanly.
| name | ui-components |
| description | Design system, UI components, Screen, Toolbar, Sheet, and localization reference. |
| user-invocable | false |
Always use the Theme enum for colors and fonts. Never hardcode values.
Theme.colors.*)// Backgrounds
Theme.colors.bgPrimary // #02122B - Main background (dark navy)
Theme.colors.bgSurface1 // #061B3A - Card/container background
Theme.colors.bgSurface2 // #11284A - Elevated surface
Theme.colors.bgButtonPrimary // #33E6BF - Primary button (turquoise)
Theme.colors.bgButtonSecondary // #061B3A - Secondary button
Theme.colors.bgButtonTertiary // #2155DF - Tertiary button (blue)
// Text
Theme.colors.textPrimary // #F0F4FC - Primary text (light)
Theme.colors.textSecondary // #C9D6E8 - Secondary text
Theme.colors.textTertiary // #8295AE - Tertiary text
// Borders & Alerts
Theme.colors.border // #1B3F73 - Border color
Theme.colors.alertSuccess // #13C89D - Success (mint green)
Theme.colors.alertError // #FF5C5C - Error (red)
Theme.colors.alertWarning // #FFC25C - Warning (orange)
Theme.colors.turquoise // #33E6BF - Brand turquoise
Reference: VultisigApp/VultisigApp/Core/DesignSystem/DefaultTheme/ColorSystem.swift
Theme.fonts.*)// Brockmann family - UI text
Theme.fonts.heroDisplay // 72pt - Hero text
Theme.fonts.headline // 40pt - Headlines
Theme.fonts.title1 // 28pt - Large titles
Theme.fonts.title2 // 22pt - Medium titles
Theme.fonts.title3 // 17pt - Small titles
Theme.fonts.bodyLMedium // 18pt - Large body
Theme.fonts.bodyMMedium // 16pt - Medium body (most common)
Theme.fonts.bodySMedium // 14pt - Small body
Theme.fonts.caption12 // 12pt - Captions
Theme.fonts.buttonRegularSemibold // 16pt - Button text
// Satoshi family - ALWAYS use for numbers, prices, and balances
Theme.fonts.priceTitle1 // 28pt
Theme.fonts.priceBodyL // 18pt
Theme.fonts.priceBodyS // 14pt
Reference: VultisigApp/VultisigApp/Core/DesignSystem/DefaultTheme/FontSystem.swift
LinearGradient.primaryGradient // Turquoise -> Blue (diagonal)
LinearGradient.primaryGradientLinear // Turquoise -> Blue (vertical)
LinearGradient.primaryGradientHorizontal // Turquoise -> Blue (horizontal)
Use PrimaryButton for all buttons. Never create custom button styles.
PrimaryButton(title: "Continue", type: .primary, size: .medium) {
// action
}
// With icons
PrimaryButton(title: "Send", leadingIcon: "arrow.up", type: .primary, size: .medium) { }
// Loading state
PrimaryButton(title: "Processing", isLoading: true, type: .primary, size: .medium) { }
Button Types:
| Type | Appearance |
|---|---|
.primary | Blue background (#2155DF) |
.secondary | Dark background with border |
.primarySuccess | Turquoise background (#33E6BF) |
.alert | Red background (#FF5C5C) |
.outline | Transparent with border |
Button Sizes: .medium (full width, 14pt padding), .small (12pt), .mini (6pt), .squared (12pt radius)
Reference: VultisigApp/VultisigApp/Components/Buttons/PrimaryButton/
General-purpose text input:
@State private var text = ""
@State private var error: String? = nil
@State private var isValid: Bool? = nil
CommonTextField(
text: $text,
label: "Address",
placeholder: "Enter wallet address",
error: $error,
isValid: $isValid
)
Sizes: .normal, .small
Reference: VultisigApp/VultisigApp/Components/TextField/CommonTextField.swift
| Component | Location | Purpose |
|---|---|---|
AddressTextField | Components/Forms/AddressTextField.swift | Address input with QR/paste accessories |
AmountTextField | Components/Forms/AmountTextField.swift | Amount with percentage + ticker |
PercentageButtonsStack | Components/Forms/PercentageButtonsStack.swift | 25/50/75/100% quick-select |
PercentageSliderView | Components/Forms/PercentageSliderView.swift | Percentage slider input |
MemoTextField | Components/TextFields/MemoTextField.swift | Memo/note input |
SearchTextField | Components/TextField/SearchTextField.swift | Search input |
Standard wrapper for all full-screen views. Always use Screen for screens and suffix the struct name with Screen.
struct MyFeatureScreen: View {
var body: some View {
Screen(title: "myFeature".localized) {
ScrollView(showsIndicators: false) {
LazyVStack(spacing: 14) {
// content
}
}
}
}
}
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
title | String | "" | Navigation bar title |
showNavigationBar | Bool | true | Show/hide nav bar |
edgeInsets | ScreenEdgeInsets | .noInsets | Custom padding |
backgroundType | BackgroundType | .plain | .plain or .gradient |
Default padding: iOS 16pt horizontal / macOS 40pt horizontal, 12pt vertical
// Custom insets
Screen(title: "Title", edgeInsets: ScreenEdgeInsets(bottom: 0)) { ... }
// Gradient background (for main screens like Home)
Screen(title: "Title", backgroundType: .gradient) { ... }
Reference: VultisigApp/VultisigApp/Components/Screen/Screen.swift
Unified toolbar for iOS and macOS.
content
.crossPlatformToolbar("Screen Title") {
CustomToolbarItem(placement: .trailing) {
ToolbarButton(image: "gear", action: onSettings)
}
}
Parameters: navigationTitle: String?, ignoresTopEdge: Bool = false, showsBackButton: Bool = true, items: [CustomToolbarItem]
ToolbarButton types: .outline (default), .confirmation (blue), .destructive (red)
ToolbarButton(image: "checkmark", type: .confirmation, action: onConfirm)
ToolbarButton(image: "trash", type: .destructive, action: onDelete)
ToolbarButton(image: "x", iconSize: 16, action: onClose)
Reference: VultisigApp/VultisigApp/Components/Toolbar/CrossPlatformToolbar/
Unified sheet presentation for iOS and macOS.
// Boolean
.crossPlatformSheet(isPresented: $showSheet) {
MySheetContent()
}
// Item-based (item must be Identifiable & Equatable)
.crossPlatformSheet(item: $selectedItem) { item in
ItemDetailSheet(item: item)
}
Sheet content should include:
.presentationDetents([.medium, .large])
.presentationBackground(Theme.colors.bgSurface1)
.presentationDragIndicator(.visible)
Reference: VultisigApp/VultisigApp/Components/Sheet/CrossPlatformSheet.swift
// Modifier approach
VStack { ... }
.containerStyle(padding: 16, radius: 12, bgColor: Theme.colors.bgSurface1)
// Component approach
ContainerView { ... }
Reference: VultisigApp/VultisigApp/Components/Layout/ContainerView.swift
Icon(named: "arrow.up", color: Theme.colors.primaryAccent4, size: 20)
Icon(named: "checkmark", isSystem: true) // SF Symbol
Available in Components/Cells/:
| Cell | Purpose |
|---|---|
VaultCell | Vault display with name, share info |
ChainCell | Chain display |
CoinPickerCell | Coin selection |
TransactionCell | Transaction history row |
UTXOTransactionCell | UTXO-specific transaction |
SettingCell | Settings row |
SettingToggleCell | Settings with toggle |
SettingFAQCell | FAQ setting row |
SettingSelectionCell | Settings with selection |
SwapChainCell / SwapCoinCell | Swap selection |
PeerCell / EmptyPeerCell | Peer device display |
FolderCell / FolderVaultCell | Folder organization |
AddressBookCell | Address book entry |
Banners: Components/Banners/
InfoBannerView - Info banner with icon, title, messageBannerView - Basic bannerActionBannerView - Banner with action buttonOutlinedDisclaimer - Outlined disclaimer boxWarningView - Warning messageLoaders: Components/Loaders/
Loader - Main spinnerCircularProgressIndicator - Circular progress with percentageLoadingOverlayViewModifier - Blocking loading overlaySegmentedControl(...) // Standard variant
FilledSegmentedControl(...) // Filled/solid variant
Reference: Components/SegmentedControls/
// Conditional display
.showIf(condition)
// Conditional transformation
.if(condition) { view in view.opacity(0.5) }
// Optional unwrap
.unwrap(optionalValue) { view, value in ... }
// Plain list item (removes background, insets, separator)
.plainListItem()
// Sheet styling (platform-aware)
.sheetStyle(padding: 8)
References: Core/Extensions/ViewExtension.swift, Components/List/View+PlainListItem.swift, Components/Sheet/View+SheetStyling.swift
struct MyFeatureScreen: View {
@State private var showDetailSheet = false
@State private var selectedItem: Item?
var body: some View {
Screen(title: "myFeature".localized) {
ScrollView {
LazyVStack(spacing: 14) {
ForEach(items) { item in
ItemRow(item: item)
.onTapGesture { selectedItem = item }
}
}
}
}
.crossPlatformToolbar {
CustomToolbarItem(placement: .trailing) {
ToolbarButton(image: "plus") { showDetailSheet = true }
}
}
.crossPlatformSheet(isPresented: $showDetailSheet) {
AddItemSheet(isPresented: $showDetailSheet)
}
.crossPlatformSheet(item: $selectedItem) { item in
ItemDetailSheet(item: item)
}
}
}
| Language | Directory |
|---|---|
| English (base) | VultisigApp/VultisigApp/Core/Localizables/en.lproj/Localizable.strings |
| German | VultisigApp/VultisigApp/Core/Localizables/de.lproj/Localizable.strings |
| Spanish | VultisigApp/VultisigApp/Core/Localizables/es.lproj/Localizable.strings |
| Croatian | VultisigApp/VultisigApp/Core/Localizables/hr.lproj/Localizable.strings |
| Italian | VultisigApp/VultisigApp/Core/Localizables/it.lproj/Localizable.strings |
| Portuguese | VultisigApp/VultisigApp/Core/Localizables/pt.lproj/Localizable.strings |
| Simplified Chinese | VultisigApp/VultisigApp/Core/Localizables/zh-Hans.lproj/Localizable.strings |
"key".localized"sendCryptoTitle", "vaultSettings"sort_localizable.py after adding keys:
python3 VultisigApp/scripts/sort_localizable.py VultisigApp/VultisigApp/Core/Localizables/en.lproj/Localizable.strings
In Swift code:
Text("sendCryptoTitle".localized)
In each Localizable.strings:
// en.lproj
"sendCryptoTitle" = "Send Crypto";
// de.lproj
"sendCryptoTitle" = "Krypto senden";
// es.lproj
"sendCryptoTitle" = "Enviar Cripto";
// hr.lproj
"sendCryptoTitle" = "Posalji Kripto";
// it.lproj
"sendCryptoTitle" = "Invia Crypto";
// pt.lproj
"sendCryptoTitle" = "Enviar Cripto";
// zh-Hans.lproj
"sendCryptoTitle" = "发送加密货币";