@3fn/core 13.0.0 → 14.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.kiro/agents/ada-prompt.md +80 -132
- package/.kiro/agents/ada-prompt.md.attribution.json +45 -0
- package/.kiro/agents/ada.json +44 -59
- package/.kiro/agents/ada.json.attribution.json +13 -0
- package/.kiro/agents/data-prompt.md +83 -74
- package/.kiro/agents/data-prompt.md.attribution.json +53 -0
- package/.kiro/agents/data.json +31 -38
- package/.kiro/agents/data.json.attribution.json +13 -0
- package/.kiro/agents/kenya-prompt.md +83 -72
- package/.kiro/agents/kenya-prompt.md.attribution.json +53 -0
- package/.kiro/agents/kenya.json +27 -35
- package/.kiro/agents/kenya.json.attribution.json +13 -0
- package/.kiro/agents/leonardo-prompt.md +176 -234
- package/.kiro/agents/leonardo-prompt.md.attribution.json +45 -0
- package/.kiro/agents/leonardo.json +28 -36
- package/.kiro/agents/leonardo.json.attribution.json +13 -0
- package/.kiro/agents/lina-prompt.md +110 -151
- package/.kiro/agents/lina-prompt.md.attribution.json +53 -0
- package/.kiro/agents/lina.json +46 -59
- package/.kiro/agents/lina.json.attribution.json +13 -0
- package/.kiro/agents/sparky-prompt.md +89 -72
- package/.kiro/agents/sparky-prompt.md.attribution.json +53 -0
- package/.kiro/agents/sparky.json +37 -37
- package/.kiro/agents/sparky.json.attribution.json +13 -0
- package/.kiro/agents/stacy-prompt.md +74 -48
- package/.kiro/agents/stacy-prompt.md.attribution.json +45 -0
- package/.kiro/agents/stacy.json +28 -30
- package/.kiro/agents/stacy.json.attribution.json +13 -0
- package/.kiro/agents/thurgood-prompt.md +94 -138
- package/.kiro/agents/thurgood-prompt.md.attribution.json +45 -0
- package/.kiro/agents/thurgood.json +31 -35
- package/.kiro/agents/thurgood.json.attribution.json +13 -0
- package/.kiro/steering/AI-Collaboration-Principles.md +3 -3
- package/.kiro/steering/Civitas-System-Overview.md +7 -16
- package/.kiro/steering/DesignerPunk-Systems-Overview.md +6 -6
- package/.kiro/steering/Spec-Feedback-Protocol.md +2 -11
- package/.kiro/steering/Task-Completion-Protocol.md +98 -17
- package/.kiro/steering/core-goals.md +3 -3
- package/.kiro/steering/personal-note.md +1 -1
- package/.kiro/steering/start-up-tasks.md +17 -6
- package/application-mcp-server/src/index.ts +26 -0
- package/dist/ComponentTokens.android.kt +12 -12
- package/dist/ComponentTokens.ios.swift +12 -12
- package/dist/ComponentTokens.web.css +3 -3
- package/dist/DesignTokens.android.kt +1 -1
- package/dist/DesignTokens.dtcg.json +8 -5
- package/dist/DesignTokens.figma.json +2 -2
- package/dist/DesignTokens.ios.swift +1 -1
- package/dist/DesignTokens.web.css +1 -1
- package/dist/android/DesignTokens.android.kt +1 -1
- package/dist/blend/OklchBlendCalculator.js +1 -0
- package/dist/blend/ThemeAwareBlendUtilities.web.d.ts +13 -2
- package/dist/blend/ThemeAwareBlendUtilities.web.js +6 -1
- package/dist/browser/designerpunk.esm.js +36 -90
- package/dist/browser/designerpunk.esm.min.js +33 -36
- package/dist/browser/designerpunk.umd.js +36 -90
- package/dist/browser/designerpunk.umd.min.js +47 -50
- package/dist/browser/tokens.css +3 -3
- package/dist/build/tokens/defineComponentTokens.d.ts +10 -0
- package/dist/build/tokens/defineComponentTokens.js +26 -0
- package/dist/components/core/Avatar-Base/avatar.tokens.d.ts +21 -26
- package/dist/components/core/Avatar-Base/avatar.tokens.js +31 -34
- package/dist/components/core/Avatar-Base/index.d.ts +1 -1
- package/dist/components/core/Avatar-Base/index.js +2 -2
- package/dist/components/core/Avatar-Base/platforms/web/Avatar.web.js +24 -5
- package/dist/components/core/Button-CTA/examples/BasicUsage.d.ts +16 -28
- package/dist/components/core/Button-CTA/examples/BasicUsage.js +18 -43
- package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.d.ts +3 -15
- package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.js +9 -58
- package/dist/components/core/Button-CTA/types.d.ts +0 -24
- package/dist/components/core/Button-CTA/types.js +6 -0
- package/dist/components/core/Button-Icon/buttonIcon.tokens.d.ts +28 -14
- package/dist/components/core/Button-Icon/buttonIcon.tokens.js +35 -20
- package/dist/components/core/Input-Text-Base/types.d.ts +13 -1
- package/dist/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.js +11 -2
- package/dist/generators/DTCGFormatGenerator.js +8 -0
- package/dist/generators/TokenFileGenerator.js +7 -2
- package/dist/integration/BuildErrorHandler.js +2 -2
- package/dist/ios/DesignTokens.ios.swift +1 -1
- package/dist/mcp/application-mcp.js +24 -0
- package/dist/mcp/docs-mcp.js +130 -15
- package/dist/mcp/product-mcp.js +25 -0
- package/dist/tokens/OpacityTokens.js +1 -1
- package/dist/tokens/component/progress.d.ts +65 -5
- package/dist/tokens/component/progress.js +79 -18
- package/dist/tokens/semantic/BlendTokens.d.ts +10 -3
- package/dist/tokens/semantic/BlendTokens.js +17 -5
- package/dist/tokens/semantic/OpacityTokens.d.ts +4 -4
- package/dist/tokens/semantic/OpacityTokens.js +4 -4
- package/dist/types/ComponentTypes.d.ts +1 -1
- package/dist/types/generated/TokenTypes.d.ts +1 -1
- package/dist/types/generated/TokenTypes.js +1 -1
- package/dist/validators/StemmaTokenUsageValidator.js +3 -2
- package/dist/web/DesignTokens.web.css +1 -1
- package/governance/BUILD-SYSTEM-SETUP.md +1 -2
- package/governance/Component-Development-Guide.md +23 -13
- package/governance/Component-Development-Standards.md +21 -20
- package/governance/Component-Family-Avatar.md +6 -7
- package/governance/Component-Family-Badge.md +19 -20
- package/governance/Component-Family-Button.md +30 -43
- package/governance/Component-Family-Chip.md +14 -15
- package/governance/Component-Family-Container.md +12 -13
- package/governance/Component-Family-Data-Display.md +1 -2
- package/governance/Component-Family-Divider.md +1 -2
- package/governance/Component-Family-Form-Inputs.md +65 -65
- package/governance/Component-Family-Icon.md +9 -10
- package/governance/Component-Family-Loading.md +1 -2
- package/governance/Component-Family-Modal.md +1 -2
- package/governance/Component-Family-Navigation.md +1 -2
- package/governance/Component-Family-Progress.md +0 -1
- package/governance/Component-Inheritance-Structures.md +219 -99
- package/governance/Component-MCP-Document-Template.md +6 -5
- package/governance/Component-Primitive-vs-Semantic-Philosophy.md +1 -1
- package/governance/Component-Quick-Reference.md +33 -33
- package/governance/Component-Readiness-Status.md +59 -44
- package/governance/Component-Templates.md +57 -61
- package/governance/Contract-System-Reference.md +7 -7
- package/governance/MCP-Integration-Guide.md +1 -1
- package/governance/Process-Cross-Reference-Standards.md +31 -13
- package/governance/Process-Development-Workflow.md +49 -59
- package/governance/Process-File-Organization.md +25 -28
- package/governance/Process-Hook-Operations.md +22 -11
- package/governance/Process-Orchestration-Model-Selection.md +92 -0
- package/governance/Process-Spec-Planning.md +98 -52
- package/governance/Process-Task-Type-Definitions.md +80 -4
- package/governance/Product-Handoff-Protocol.md +2 -0
- package/governance/Rosetta-System-Architecture.md +13 -11
- package/governance/Test-Behavioral-Contract-Validation.md +38 -31
- package/governance/Test-Failure-Audit-Methodology.md +1 -1
- package/governance/Token-Family-Accessibility.md +1 -2
- package/governance/Token-Family-Blend.md +18 -16
- package/governance/Token-Family-Blur.md +0 -1
- package/governance/Token-Family-Border.md +1 -2
- package/governance/Token-Family-Color.md +0 -1
- package/governance/Token-Family-Glow.md +1 -2
- package/governance/Token-Family-Layering.md +0 -1
- package/governance/Token-Family-Motion.md +1 -2
- package/governance/Token-Family-Opacity.md +0 -1
- package/governance/Token-Family-Radius.md +1 -2
- package/governance/Token-Family-Responsive.md +1 -2
- package/governance/Token-Family-Shadow.md +1 -2
- package/governance/Token-Family-Sizing.md +0 -1
- package/governance/Token-Family-Spacing.md +1 -2
- package/governance/Token-Family-Typography.md +1 -2
- package/governance/Token-Governance.md +8 -8
- package/governance/Token-Quick-Reference.md +47 -34
- package/governance/Token-Resolution-Patterns.md +1 -1
- package/governance/Token-Semantic-Structure.md +1 -1
- package/governance/Web-Authoring-Standards.md +5 -5
- package/governance/browser-distribution-guide.md +1 -4
- package/governance/classification-map.md +474 -0
- package/governance/completion-documentation-guide.md +23 -37
- package/governance/component-meta-authoring-guide.md +1 -1
- package/governance/cross-platform-vs-platform-specific-decision-framework.md +1 -1
- package/governance/platform-implementation-guidelines.md +2 -3
- package/governance/release-management-system.md +28 -63
- package/governance/rosetta-system-principles.md +8 -6
- package/governance/stemma-system-principles.md +18 -17
- package/mcp-server/src/index.ts +24 -6
- package/mcp-server/src/indexer/DocumentIndexer.ts +119 -9
- package/mcp-server/src/indexer/__tests__/bare-id-crossrefs.test.ts +250 -0
- package/mcp-server/src/indexer/cross-ref-parser.ts +29 -1
- package/mcp-server/src/indexer/index-health.ts +27 -2
- package/mcp-server/src/query/__tests__/find-docs-calibration.test.ts +11 -26
- package/mcp-server/src/relocation-integrity-gate/__tests__/relocation-integrity-gate.test.ts +72 -5
- package/mcp-server/src/relocation-integrity-gate/relocation-integrity-gate.ts +81 -24
- package/mcp-server/src/tools/list-cross-references.ts +2 -2
- package/package.json +24 -26
- package/src/__tests__/browser-distribution/css-bundling.test.ts +6 -4
- package/src/__tests__/console-allowlist.json +14 -0
- package/src/__tests__/console-fail-setup.ts +169 -0
- package/src/__tests__/integration/Spec107-DesignLanguageContext.test.ts +16 -0
- package/src/__tests__/stemma-system/behavioral-contract-validation.test.ts +70 -17
- package/src/__tests__/stemma-system/contract-catalog-name-validation.test.ts +28 -0
- package/src/__tests__/stemma-system/form-inputs-contracts.test.ts +223 -16
- package/src/__tests__/stemma-system/input-text-native-base-call-alignment.test.ts +298 -0
- package/src/blend/OklchBlendCalculator.ts +3 -0
- package/src/blend/ThemeAwareBlendUtilities.android.kt +3 -0
- package/src/blend/ThemeAwareBlendUtilities.ios.swift +3 -0
- package/src/blend/ThemeAwareBlendUtilities.web.ts +9 -1
- package/src/blend/__tests__/InteractionStateAudit.test.ts +12 -9
- package/src/build/errors/__tests__/ErrorHandler.integration.test.ts +8 -0
- package/src/build/errors/__tests__/ErrorHandler.test.ts +5 -0
- package/src/build/tokens/__tests__/defineComponentTokens.test.ts +113 -0
- package/src/build/tokens/defineComponentTokens.ts +43 -1
- package/src/build/workflow/__tests__/CICDIntegration.test.ts +12 -1
- package/src/cli/__tests__/init.test.ts +45 -11
- package/src/components/core/Avatar-Base/Avatar-Base.schema.yaml +1 -1
- package/src/components/core/Avatar-Base/__tests__/Avatar.accessibility.test.ts +121 -7
- package/src/components/core/Avatar-Base/__tests__/Avatar.image.test.ts +3 -0
- package/src/components/core/Avatar-Base/__tests__/Avatar.test.ts +15 -6
- package/src/components/core/Avatar-Base/avatar.tokens.ts +31 -34
- package/src/components/core/Avatar-Base/contracts.yaml +11 -1
- package/src/components/core/Avatar-Base/index.ts +1 -1
- package/src/components/core/Avatar-Base/platforms/web/Avatar.web.ts +24 -5
- package/src/components/core/Badge-Count-Base/contracts.yaml +1 -1
- package/src/components/core/Badge-Label-Base/contracts.yaml +1 -1
- package/src/components/core/Button-CTA/Button-CTA.schema.yaml +2 -12
- package/src/components/core/Button-CTA/README.md +3 -6
- package/src/components/core/Button-CTA/__tests__/ButtonCTA.test.ts +35 -89
- package/src/components/core/Button-CTA/__tests__/setup.test.ts +0 -2
- package/src/components/core/Button-CTA/__tests__/test-utils.ts +0 -2
- package/src/components/core/Button-CTA/contracts.yaml +6 -29
- package/src/components/core/Button-CTA/examples/BasicUsage.html +2 -14
- package/src/components/core/Button-CTA/examples/BasicUsage.tsx +17 -44
- package/src/components/core/Button-CTA/platforms/android/ButtonCTA.android.kt +12 -20
- package/src/components/core/Button-CTA/platforms/ios/ButtonCTA.ios.swift +12 -51
- package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.css +2 -26
- package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.ts +18 -71
- package/src/components/core/Button-CTA/types.ts +10 -28
- package/src/components/core/Button-Icon/buttonIcon.tokens.ts +43 -27
- package/src/components/core/Chip-Base/__tests__/ChipBase.test.ts +13 -0
- package/src/components/core/Chip-Filter/__tests__/ChipFilter.test.ts +13 -0
- package/src/components/core/Chip-Input/__tests__/ChipInput.test.ts +13 -0
- package/src/components/core/Input-Text-Base/Input-Text-Base.schema.yaml +30 -2
- package/src/components/core/Input-Text-Base/README.md +25 -2
- package/src/components/core/Input-Text-Base/__tests__/focusIndicators.test.ts +16 -15
- package/src/components/core/Input-Text-Base/contracts.yaml +90 -0
- package/src/components/core/Input-Text-Base/platforms/android/InputTextBase.android.kt +26 -12
- package/src/components/core/Input-Text-Base/platforms/ios/InputTextBase.ios.swift +195 -59
- package/src/components/core/Input-Text-Base/types.ts +13 -1
- package/src/components/core/Input-Text-Email/Input-Text-Email.schema.yaml +5 -1
- package/src/components/core/Input-Text-Email/README.md +8 -7
- package/src/components/core/Input-Text-Email/platforms/android/InputTextEmail.android.kt +1 -4
- package/src/components/core/Input-Text-Email/platforms/ios/InputTextEmail.ios.swift +2 -16
- package/src/components/core/Input-Text-Password/Input-Text-Password.schema.yaml +10 -3
- package/src/components/core/Input-Text-Password/README.md +9 -8
- package/src/components/core/Input-Text-Password/contracts.yaml +5 -0
- package/src/components/core/Input-Text-Password/platforms/android/InputTextPassword.android.kt +17 -7
- package/src/components/core/Input-Text-Password/platforms/ios/InputTextPassword.ios.swift +22 -20
- package/src/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.ts +11 -2
- package/src/components/core/Input-Text-PhoneNumber/Input-Text-PhoneNumber.schema.yaml +5 -1
- package/src/components/core/Input-Text-PhoneNumber/README.md +9 -8
- package/src/components/core/Input-Text-PhoneNumber/platforms/android/InputTextPhoneNumber.android.kt +2 -5
- package/src/components/core/Input-Text-PhoneNumber/platforms/ios/InputTextPhoneNumber.ios.swift +3 -17
- package/src/components/core/Nav-Header-App/contracts.yaml +1 -1
- package/src/components/core/Nav-SegmentedChoice-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Indicator-Connector-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Indicator-Label-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Indicator-Node-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Stepper-Base/__tests__/StepperBase.test.ts +5 -2
- package/src/components/core/Progress-Stepper-Detailed/__tests__/StepperDetailed.test.ts +5 -2
- package/src/generators/DTCGFormatGenerator.ts +6 -0
- package/src/generators/TokenFileGenerator.ts +7 -2
- package/src/generators/__tests__/DTCGConfigOptions.test.ts +14 -5
- package/src/integration/BuildErrorHandler.ts +2 -2
- package/src/tokens/OpacityTokens.ts +1 -1
- package/src/tokens/__tests__/OpacityTokens.test.ts +3 -1
- package/src/tokens/__tests__/ProgressTokenCompliance.test.ts +5 -3
- package/src/tokens/__tests__/ProgressTokenFormulas.test.ts +11 -11
- package/src/tokens/__tests__/ProgressTokenTranslation.test.ts +22 -20
- package/src/tokens/component/progress.ts +83 -21
- package/src/tokens/semantic/BlendTokens.ts +26 -5
- package/src/tokens/semantic/OpacityTokens.ts +4 -4
- package/src/types/ComponentTypes.ts +1 -1
- package/src/types/generated/TokenTypes.ts +1 -1
- package/src/validators/StemmaTokenUsageValidator.ts +3 -2
- package/token-index/components.yaml +8 -8
- package/token-index/semantics.yaml +1 -2
- package/src/tools/release/__tests__/ChangeClassifier.test.ts +0 -133
- package/src/tools/release/__tests__/ChangeExtractor.test.ts +0 -222
- package/src/tools/release/__tests__/GitHubPublisher.test.ts +0 -240
- package/src/tools/release/__tests__/NotesRenderer.test.ts +0 -142
- package/src/tools/release/__tests__/NpmPublisher.test.ts +0 -289
- package/src/tools/release/__tests__/PipelineIntegration.test.ts +0 -188
- package/src/tools/release/__tests__/ReleasePipeline.test.ts +0 -192
- package/src/tools/release/__tests__/SemanticVersionValidator.test.ts +0 -49
- package/src/tools/release/__tests__/SummaryScanner.test.ts +0 -141
- package/src/tools/release/__tests__/TagResolver.test.ts +0 -91
- package/src/tools/release/__tests__/VersionCalculator.test.ts +0 -270
- package/src/tools/release/__tests__/helpers/NpmMockHelper.ts +0 -80
- package/src/tools/release/cli/ReleasePipeline.ts +0 -165
- package/src/tools/release/cli/release-tool.ts +0 -107
- package/src/tools/release/pipeline/ChangeClassifier.ts +0 -61
- package/src/tools/release/pipeline/ChangeExtractor.ts +0 -87
- package/src/tools/release/pipeline/NotesRenderer.ts +0 -66
- package/src/tools/release/pipeline/SummaryScanner.ts +0 -70
- package/src/tools/release/pipeline/TagResolver.ts +0 -40
- package/src/tools/release/pipeline/VersionCalculator.ts +0 -375
- package/src/tools/release/publishers/GitHubPublisher.ts +0 -228
- package/src/tools/release/publishers/NpmPublisher.ts +0 -196
- package/src/tools/release/release-config.json +0 -5
- package/src/tools/release/types/index.ts +0 -282
- package/src/tools/release/validators/SemanticVersionValidator.ts +0 -67
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* while maintaining API consistency with web and Android platforms.
|
|
12
12
|
*
|
|
13
13
|
* Uses theme-aware blend utilities (Color extensions with SwiftUI environment) for
|
|
14
|
-
* state colors (hover, pressed,
|
|
14
|
+
* state colors (hover, pressed, icon) instead of opacity or scale workarounds.
|
|
15
15
|
* This ensures cross-platform consistency with Web and Android implementations.
|
|
16
16
|
*
|
|
17
17
|
* Part of the DesignerPunk CTA Button Component system.
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
import SwiftUI
|
|
24
24
|
|
|
25
25
|
// Import theme-aware blend utilities (Color extensions from ThemeAwareBlendUtilities.ios.swift)
|
|
26
|
-
// These provide semantic blend methods: hoverBlend(), pressedBlend(),
|
|
26
|
+
// These provide semantic blend methods: hoverBlend(), pressedBlend(), iconBlend()
|
|
27
27
|
// @see Requirements: 11.1, 11.2, 11.3 - Theme-aware utilities
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -65,8 +65,8 @@ enum ButtonCTAStyle {
|
|
|
65
65
|
* three size variants, three visual styles, optional leading icons, and
|
|
66
66
|
* theme-aware blend utilities for state colors.
|
|
67
67
|
*
|
|
68
|
-
* Uses theme-aware Color extensions (hoverBlend(), pressedBlend(),
|
|
69
|
-
*
|
|
68
|
+
* Uses theme-aware Color extensions (hoverBlend(), pressedBlend(), iconBlend())
|
|
69
|
+
* with SwiftUI environment for automatic theme color updates.
|
|
70
70
|
*
|
|
71
71
|
* Usage:
|
|
72
72
|
* ```swift
|
|
@@ -97,7 +97,7 @@ enum ButtonCTAStyle {
|
|
|
97
97
|
* Requirements:
|
|
98
98
|
* - 1.1-1.7: Size variants (small: 40px, medium: 48px, large: 56px)
|
|
99
99
|
* - 2.1-2.4: Visual styles (primary, secondary, tertiary)
|
|
100
|
-
* - 7.1-7.4: Blend utility state colors (hover, pressed,
|
|
100
|
+
* - 7.1-7.4: Blend utility state colors (hover, pressed, icon)
|
|
101
101
|
* - 8.1-8.6: Icon support with leading position
|
|
102
102
|
* - 11.1-11.3: Theme-aware blend utilities with SwiftUI environment
|
|
103
103
|
* - 13.1-13.4: Touch target accessibility (44px minimum)
|
|
@@ -125,10 +125,7 @@ struct ButtonCTA: View {
|
|
|
125
125
|
|
|
126
126
|
/// Optional test ID for automated testing
|
|
127
127
|
let testID: String?
|
|
128
|
-
|
|
129
|
-
/// Optional disabled state (default: false)
|
|
130
|
-
let disabled: Bool
|
|
131
|
-
|
|
128
|
+
|
|
132
129
|
// MARK: - State
|
|
133
130
|
|
|
134
131
|
/// Tracks pressed state for scale transform animation
|
|
@@ -149,7 +146,6 @@ struct ButtonCTA: View {
|
|
|
149
146
|
* - noWrap: Prevent text wrapping (default: false)
|
|
150
147
|
* - onPress: Click/tap handler (required)
|
|
151
148
|
* - testID: Optional test identifier
|
|
152
|
-
* - disabled: Optional disabled state (default: false)
|
|
153
149
|
*/
|
|
154
150
|
init(
|
|
155
151
|
label: String,
|
|
@@ -158,8 +154,7 @@ struct ButtonCTA: View {
|
|
|
158
154
|
icon: String? = nil,
|
|
159
155
|
noWrap: Bool = false,
|
|
160
156
|
onPress: @escaping () -> Void,
|
|
161
|
-
testID: String? = nil
|
|
162
|
-
disabled: Bool = false
|
|
157
|
+
testID: String? = nil
|
|
163
158
|
) {
|
|
164
159
|
self.label = label
|
|
165
160
|
self.size = size
|
|
@@ -168,7 +163,6 @@ struct ButtonCTA: View {
|
|
|
168
163
|
self.noWrap = noWrap
|
|
169
164
|
self.onPress = onPress
|
|
170
165
|
self.testID = testID
|
|
171
|
-
self.disabled = disabled
|
|
172
166
|
}
|
|
173
167
|
|
|
174
168
|
// MARK: - Body
|
|
@@ -213,15 +207,12 @@ struct ButtonCTA: View {
|
|
|
213
207
|
.simultaneousGesture(
|
|
214
208
|
DragGesture(minimumDistance: 0)
|
|
215
209
|
.onChanged { _ in
|
|
216
|
-
|
|
217
|
-
isPressed = true
|
|
218
|
-
}
|
|
210
|
+
isPressed = true
|
|
219
211
|
}
|
|
220
212
|
.onEnded { _ in
|
|
221
213
|
isPressed = false
|
|
222
214
|
}
|
|
223
215
|
)
|
|
224
|
-
.disabled(disabled)
|
|
225
216
|
// Requirement 13.1-13.4, 16.4: Accessibility identifier for testing
|
|
226
217
|
.accessibilityIdentifier(testID ?? "")
|
|
227
218
|
// Requirement 17.4: Respect safe area insets for full-width buttons
|
|
@@ -230,14 +221,11 @@ struct ButtonCTA: View {
|
|
|
230
221
|
|
|
231
222
|
// MARK: - Blend Color Computed Properties
|
|
232
223
|
|
|
233
|
-
/// Current background color based on state (normal,
|
|
224
|
+
/// Current background color based on state (normal, pressed)
|
|
234
225
|
/// Uses theme-aware blend utilities (Color extensions) for cross-platform consistency
|
|
235
|
-
/// @see Requirements: 7.1, 7.2,
|
|
226
|
+
/// @see Requirements: 7.1, 7.2, 11.1, 11.2, 11.3
|
|
236
227
|
private var currentBackgroundColor: Color {
|
|
237
|
-
if
|
|
238
|
-
// @see Requirements: 7.3 - Disabled uses desaturate(color.primary, blend.disabledDesaturate)
|
|
239
|
-
return disabledBackgroundColor
|
|
240
|
-
} else if isPressed {
|
|
228
|
+
if isPressed {
|
|
241
229
|
// @see Requirements: 7.2 - Pressed uses darkerBlend(color.primary, blend.pressedDarker)
|
|
242
230
|
return pressedBackgroundColor
|
|
243
231
|
} else {
|
|
@@ -260,20 +248,6 @@ struct ButtonCTA: View {
|
|
|
260
248
|
}
|
|
261
249
|
}
|
|
262
250
|
|
|
263
|
-
/// Disabled state background color using theme-aware blend utility
|
|
264
|
-
/// Uses disabledBlend() which applies desaturate with blend.disabledDesaturate (12%)
|
|
265
|
-
/// @see Requirements: 7.3, 11.1, 11.2, 11.3
|
|
266
|
-
private var disabledBackgroundColor: Color {
|
|
267
|
-
switch style {
|
|
268
|
-
case .primary:
|
|
269
|
-
return theme.colorActionPrimary.disabledBlend()
|
|
270
|
-
case .secondary:
|
|
271
|
-
return theme.colorStructureCanvas
|
|
272
|
-
case .tertiary:
|
|
273
|
-
return Color.clear
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
251
|
// MARK: - Size-Based Computed Properties
|
|
278
252
|
|
|
279
253
|
/// Typography token based on button size
|
|
@@ -532,20 +506,7 @@ struct ButtonCTA_Previews: PreviewProvider {
|
|
|
532
506
|
onPress: { print("Confirm pressed") }
|
|
533
507
|
)
|
|
534
508
|
}
|
|
535
|
-
|
|
536
|
-
Divider()
|
|
537
|
-
|
|
538
|
-
// Disabled state
|
|
539
|
-
Text("Disabled State")
|
|
540
|
-
.font(.headline)
|
|
541
|
-
|
|
542
|
-
VStack(spacing: 12) {
|
|
543
|
-
ButtonCTA(
|
|
544
|
-
label: "Disabled Button",
|
|
545
|
-
disabled: true,
|
|
546
|
-
onPress: { print("Should not print") }
|
|
547
|
-
)
|
|
548
|
-
}
|
|
509
|
+
|
|
549
510
|
}
|
|
550
511
|
.padding()
|
|
551
512
|
}
|
|
@@ -275,7 +275,7 @@
|
|
|
275
275
|
* The --_cta-hover-bg custom property is set by the component
|
|
276
276
|
* using darkerBlend(color.primary, blend.hoverDarker) = 8% darker.
|
|
277
277
|
*/
|
|
278
|
-
.button-cta--primary:hover
|
|
278
|
+
.button-cta--primary:hover {
|
|
279
279
|
background-color: var(--_cta-hover-bg);
|
|
280
280
|
}
|
|
281
281
|
|
|
@@ -288,7 +288,7 @@
|
|
|
288
288
|
* The --_cta-pressed-bg custom property is set by the component
|
|
289
289
|
* using darkerBlend(color.primary, blend.pressedDarker) = 12% darker.
|
|
290
290
|
*/
|
|
291
|
-
.button-cta--primary:active
|
|
291
|
+
.button-cta--primary:active {
|
|
292
292
|
background-color: var(--_cta-pressed-bg);
|
|
293
293
|
}
|
|
294
294
|
|
|
@@ -318,30 +318,6 @@
|
|
|
318
318
|
outline: none;
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
/**
|
|
322
|
-
* Disabled state.
|
|
323
|
-
*
|
|
324
|
-
* Uses blend utility calculated color (desaturate with blend.disabledDesaturate)
|
|
325
|
-
* instead of opacity workaround for cross-platform consistency.
|
|
326
|
-
*
|
|
327
|
-
* The --button-disabled-color custom property is set by the component
|
|
328
|
-
* using desaturate(color.primary, blend.disabledDesaturate) = 12% less saturated.
|
|
329
|
-
*
|
|
330
|
-
* - Cursor changes to not-allowed
|
|
331
|
-
* - Prevents interaction
|
|
332
|
-
* - Maintains color contrast for accessibility
|
|
333
|
-
*/
|
|
334
|
-
.button-cta:disabled,
|
|
335
|
-
.button-cta--disabled {
|
|
336
|
-
cursor: not-allowed;
|
|
337
|
-
pointer-events: none;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.button-cta--primary:disabled,
|
|
341
|
-
.button-cta--primary.button-cta--disabled {
|
|
342
|
-
background-color: var(--_cta-disabled-bg);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
321
|
/* ==========================================================================
|
|
346
322
|
Responsive Behavior
|
|
347
323
|
========================================================================== */
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* composition pattern as iOS and Android platforms. This ensures cross-platform
|
|
13
13
|
* consistency and single source of truth for icon rendering.
|
|
14
14
|
*
|
|
15
|
-
* Uses theme-aware blend utilities for state colors (hover, pressed,
|
|
15
|
+
* Uses theme-aware blend utilities for state colors (hover, pressed, icon)
|
|
16
16
|
* instead of opacity or filter workarounds. This ensures cross-platform consistency
|
|
17
17
|
* with iOS and Android implementations.
|
|
18
18
|
*
|
|
@@ -86,13 +86,12 @@ function getIconSizeForButton(buttonSize: ButtonSize): IconBaseSize {
|
|
|
86
86
|
* - Semantic `<button>` element with proper accessibility
|
|
87
87
|
* - Token-based styling via CSS custom properties
|
|
88
88
|
* - Supports text wrapping by default (accessibility-first)
|
|
89
|
-
* - Uses blend utilities for state colors (hover, pressed,
|
|
89
|
+
* - Uses blend utilities for state colors (hover, pressed, icon)
|
|
90
90
|
* - WCAG 2.1 AA compliant:
|
|
91
91
|
* - Keyboard navigation (Tab, Enter, Space)
|
|
92
92
|
* - Focus indicators with 3:1 contrast ratio
|
|
93
93
|
* - Color contrast 4.5:1 for all styles
|
|
94
94
|
* - Screen reader support with ARIA attributes
|
|
95
|
-
* - Proper disabled state handling
|
|
96
95
|
*
|
|
97
96
|
* @example
|
|
98
97
|
* ```html
|
|
@@ -106,7 +105,6 @@ function getIconSizeForButton(buttonSize: ButtonSize): IconBaseSize {
|
|
|
106
105
|
* variant="primary"
|
|
107
106
|
* icon="arrow-right"
|
|
108
107
|
* no-wrap="false"
|
|
109
|
-
* disabled="false"
|
|
110
108
|
* test-id="submit-button"
|
|
111
109
|
* ></button-cta>
|
|
112
110
|
* ```
|
|
@@ -143,7 +141,6 @@ export class ButtonCTA extends HTMLElement {
|
|
|
143
141
|
// Cached blend colors for state styling
|
|
144
142
|
private _hoverColor: string = '';
|
|
145
143
|
private _pressedColor: string = '';
|
|
146
|
-
private _disabledColor: string = '';
|
|
147
144
|
private _iconColor: string = '';
|
|
148
145
|
private _iconOpticalBalanceColor: string = '';
|
|
149
146
|
|
|
@@ -153,7 +150,7 @@ export class ButtonCTA extends HTMLElement {
|
|
|
153
150
|
* When these attributes change, attributeChangedCallback is invoked.
|
|
154
151
|
*/
|
|
155
152
|
static get observedAttributes(): string[] {
|
|
156
|
-
return ['label', 'size', 'variant', 'icon', 'no-wrap', '
|
|
153
|
+
return ['label', 'size', 'variant', 'icon', 'no-wrap', 'test-id'];
|
|
157
154
|
}
|
|
158
155
|
|
|
159
156
|
constructor() {
|
|
@@ -219,15 +216,14 @@ export class ButtonCTA extends HTMLElement {
|
|
|
219
216
|
* Calculate blend colors from CSS custom properties.
|
|
220
217
|
*
|
|
221
218
|
* Reads base colors from CSS custom properties and applies theme-aware blend
|
|
222
|
-
* utilities to generate state colors (hover, pressed,
|
|
223
|
-
*
|
|
219
|
+
* utilities to generate state colors (hover, pressed, icon).
|
|
220
|
+
*
|
|
224
221
|
* Uses getBlendUtilities() factory functions instead of direct blend calculations
|
|
225
222
|
* for cross-platform consistency with iOS and Android implementations.
|
|
226
|
-
*
|
|
223
|
+
*
|
|
227
224
|
* State color mappings:
|
|
228
225
|
* - Hover: darkerBlend(color.action.primary, blend.hoverDarker) - 8% darker
|
|
229
226
|
* - Pressed: darkerBlend(color.action.primary, blend.pressedDarker) - 12% darker
|
|
230
|
-
* - Disabled: desaturate(color.action.primary, blend.disabledDesaturate) - 12% less saturated
|
|
231
227
|
* - Icon: lighterBlend(color.contrast.onAction, blend.iconLighter) - 8% lighter
|
|
232
228
|
*
|
|
233
229
|
* @see Requirements: 7.1, 7.2, 7.3, 7.4 - Button-CTA state colors
|
|
@@ -258,10 +254,7 @@ export class ButtonCTA extends HTMLElement {
|
|
|
258
254
|
|
|
259
255
|
// @see Requirements: 7.2 - Pressed uses darkerBlend(color.action.primary, blend.pressedDarker)
|
|
260
256
|
this._pressedColor = this._blendUtils.pressedColor(primaryColor);
|
|
261
|
-
|
|
262
|
-
// @see Requirements: 7.3 - Disabled uses desaturate(color.action.primary, blend.disabledDesaturate)
|
|
263
|
-
this._disabledColor = this._blendUtils.disabledColor(primaryColor);
|
|
264
|
-
|
|
257
|
+
|
|
265
258
|
// @see Requirements: 7.4 - Icon uses lighterBlend(color.contrast.onAction, blend.iconLighter)
|
|
266
259
|
// Icon for primary buttons: provides optical balance for icons on primary background
|
|
267
260
|
this._iconColor = this._blendUtils.iconColor(onActionColor);
|
|
@@ -371,24 +364,6 @@ export class ButtonCTA extends HTMLElement {
|
|
|
371
364
|
this.setAttribute('no-wrap', value.toString());
|
|
372
365
|
}
|
|
373
366
|
|
|
374
|
-
/**
|
|
375
|
-
* Get the disabled state.
|
|
376
|
-
*/
|
|
377
|
-
get disabled(): boolean {
|
|
378
|
-
return this.hasAttribute('disabled');
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Set the disabled state.
|
|
383
|
-
*/
|
|
384
|
-
set disabled(value: boolean) {
|
|
385
|
-
if (value) {
|
|
386
|
-
this.setAttribute('disabled', '');
|
|
387
|
-
} else {
|
|
388
|
-
this.removeAttribute('disabled');
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
367
|
/**
|
|
393
368
|
* Get the test ID.
|
|
394
369
|
*/
|
|
@@ -451,17 +426,15 @@ export class ButtonCTA extends HTMLElement {
|
|
|
451
426
|
const variant = this.buttonVariant;
|
|
452
427
|
const icon = this.icon;
|
|
453
428
|
const noWrap = this.noWrap;
|
|
454
|
-
const disabled = this.disabled;
|
|
455
429
|
const testID = this.testID;
|
|
456
|
-
|
|
430
|
+
|
|
457
431
|
// Generate class names
|
|
458
432
|
const buttonClasses = [
|
|
459
433
|
'button-cta',
|
|
460
434
|
`button-cta--${size}`,
|
|
461
|
-
`button-cta--${variant}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
435
|
+
`button-cta--${variant}`
|
|
436
|
+
].join(' ');
|
|
437
|
+
|
|
465
438
|
// Get icon size for button size variant
|
|
466
439
|
// Icon sizes are type-safe mapped from button size:
|
|
467
440
|
// - Small/Medium: 24px (iconBaseSize100)
|
|
@@ -480,7 +453,6 @@ export class ButtonCTA extends HTMLElement {
|
|
|
480
453
|
const blendColorStyles = `
|
|
481
454
|
--_cta-hover-bg: ${this._hoverColor};
|
|
482
455
|
--_cta-pressed-bg: ${this._pressedColor};
|
|
483
|
-
--_cta-disabled-bg: ${this._disabledColor};
|
|
484
456
|
--_cta-icon-color: ${this._iconColor};
|
|
485
457
|
--_cta-icon-optical: ${this._iconOpticalBalanceColor};
|
|
486
458
|
`;
|
|
@@ -491,11 +463,10 @@ export class ButtonCTA extends HTMLElement {
|
|
|
491
463
|
// @see Requirements: 8.2, 8.3 (components render correctly with interactivity)
|
|
492
464
|
this._shadowRoot.innerHTML = `
|
|
493
465
|
<style>${buttonStyles}</style>
|
|
494
|
-
<button
|
|
466
|
+
<button
|
|
495
467
|
class="${buttonClasses}"
|
|
496
468
|
type="button"
|
|
497
469
|
role="button"
|
|
498
|
-
${disabled ? 'disabled aria-disabled="true"' : 'aria-disabled="false"'}
|
|
499
470
|
${testIDAttr}
|
|
500
471
|
aria-label="${label}"
|
|
501
472
|
style="${blendColorStyles}"
|
|
@@ -536,34 +507,23 @@ export class ButtonCTA extends HTMLElement {
|
|
|
536
507
|
const variant = this.buttonVariant;
|
|
537
508
|
const icon = this.icon;
|
|
538
509
|
const noWrap = this.noWrap;
|
|
539
|
-
const disabled = this.disabled;
|
|
540
510
|
const testID = this.testID;
|
|
541
|
-
|
|
511
|
+
|
|
542
512
|
// Get icon size for button size variant
|
|
543
513
|
const iconSize: IconBaseSize = getIconSizeForButton(size);
|
|
544
|
-
|
|
514
|
+
|
|
545
515
|
// ─────────────────────────────────────────────────────────────────
|
|
546
516
|
// Update button element
|
|
547
517
|
// ─────────────────────────────────────────────────────────────────
|
|
548
|
-
|
|
518
|
+
|
|
549
519
|
// Update CSS class (preserves element identity for transitions)
|
|
550
520
|
const buttonClasses = [
|
|
551
521
|
'button-cta',
|
|
552
522
|
`button-cta--${size}`,
|
|
553
|
-
`button-cta--${variant}
|
|
554
|
-
|
|
555
|
-
].filter(Boolean).join(' ');
|
|
523
|
+
`button-cta--${variant}`
|
|
524
|
+
].join(' ');
|
|
556
525
|
this._button.className = buttonClasses;
|
|
557
|
-
|
|
558
|
-
// Update disabled state
|
|
559
|
-
if (disabled) {
|
|
560
|
-
this._button.setAttribute('disabled', '');
|
|
561
|
-
this._button.setAttribute('aria-disabled', 'true');
|
|
562
|
-
} else {
|
|
563
|
-
this._button.removeAttribute('disabled');
|
|
564
|
-
this._button.setAttribute('aria-disabled', 'false');
|
|
565
|
-
}
|
|
566
|
-
|
|
526
|
+
|
|
567
527
|
// Update aria-label
|
|
568
528
|
this._button.setAttribute('aria-label', label);
|
|
569
529
|
|
|
@@ -577,7 +537,6 @@ export class ButtonCTA extends HTMLElement {
|
|
|
577
537
|
// Update blend color CSS custom properties
|
|
578
538
|
this._button.style.setProperty('--_cta-hover-bg', this._hoverColor);
|
|
579
539
|
this._button.style.setProperty('--_cta-pressed-bg', this._pressedColor);
|
|
580
|
-
this._button.style.setProperty('--_cta-disabled-bg', this._disabledColor);
|
|
581
540
|
this._button.style.setProperty('--_cta-icon-color', this._iconColor);
|
|
582
541
|
this._button.style.setProperty('--_cta-icon-optical', this._iconOpticalBalanceColor);
|
|
583
542
|
|
|
@@ -638,13 +597,6 @@ export class ButtonCTA extends HTMLElement {
|
|
|
638
597
|
* Dispatches a custom 'press' event that bubbles up to parent elements.
|
|
639
598
|
*/
|
|
640
599
|
private _handleClick = (event: Event): void => {
|
|
641
|
-
// Don't dispatch if disabled
|
|
642
|
-
if (this.disabled) {
|
|
643
|
-
event.preventDefault();
|
|
644
|
-
event.stopPropagation();
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
600
|
// Dispatch custom 'press' event
|
|
649
601
|
this.dispatchEvent(new CustomEvent('press', {
|
|
650
602
|
bubbles: true,
|
|
@@ -663,11 +615,6 @@ export class ButtonCTA extends HTMLElement {
|
|
|
663
615
|
* @param event - The keyboard event
|
|
664
616
|
*/
|
|
665
617
|
private _handleKeyDown = (event: KeyboardEvent): void => {
|
|
666
|
-
// Don't handle if disabled
|
|
667
|
-
if (this.disabled) {
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
618
|
// Handle Enter and Space keys (WCAG 2.1 AA keyboard navigation)
|
|
672
619
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
673
620
|
event.preventDefault(); // Prevent default space scrolling
|
|
@@ -82,7 +82,6 @@ export type ButtonStyle = 'primary' | 'secondary' | 'tertiary';
|
|
|
82
82
|
* variant="primary"
|
|
83
83
|
* icon="arrow-right"
|
|
84
84
|
* noWrap={false}
|
|
85
|
-
* disabled={false}
|
|
86
85
|
* testID="submit-button"
|
|
87
86
|
* onPress={handleSubmit}
|
|
88
87
|
* />
|
|
@@ -197,15 +196,13 @@ export interface ButtonProps {
|
|
|
197
196
|
|
|
198
197
|
/**
|
|
199
198
|
* Click/tap handler (required)
|
|
200
|
-
*
|
|
199
|
+
*
|
|
201
200
|
* Callback function invoked when the button is clicked or tapped.
|
|
202
|
-
*
|
|
203
|
-
*
|
|
201
|
+
*
|
|
204
202
|
* @remarks
|
|
205
203
|
* - Function signature: `() => void`
|
|
206
|
-
* - Not invoked when `disabled` is true
|
|
207
204
|
* - Triggered by click, tap, Enter key, or Space key
|
|
208
|
-
*
|
|
205
|
+
*
|
|
209
206
|
* @example
|
|
210
207
|
* ```typescript
|
|
211
208
|
* onPress={() => console.log('Clicked')}
|
|
@@ -232,26 +229,11 @@ export interface ButtonProps {
|
|
|
232
229
|
* ```
|
|
233
230
|
*/
|
|
234
231
|
testID?: string;
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Optional disabled state (default: false)
|
|
238
|
-
*
|
|
239
|
-
* When true, the button is non-interactive and visually indicates
|
|
240
|
-
* disabled state. The onPress handler is not called when disabled.
|
|
241
|
-
*
|
|
242
|
-
* @defaultValue false
|
|
243
|
-
*
|
|
244
|
-
* @remarks
|
|
245
|
-
* - Disabled buttons are not keyboard focusable
|
|
246
|
-
* - Screen readers announce disabled state
|
|
247
|
-
* - Visual styling indicates non-interactive state
|
|
248
|
-
*
|
|
249
|
-
* @example
|
|
250
|
-
* ```typescript
|
|
251
|
-
* disabled={false} // Interactive (default)
|
|
252
|
-
* disabled={true} // Non-interactive
|
|
253
|
-
* disabled={isSubmitting} // Conditional disable
|
|
254
|
-
* ```
|
|
255
|
-
*/
|
|
256
|
-
disabled?: boolean;
|
|
257
232
|
}
|
|
233
|
+
|
|
234
|
+
// NO DISABLED STATES
|
|
235
|
+
// DesignerPunk does not support disabled states for usability and
|
|
236
|
+
// accessibility reasons. If an action is unavailable, the component
|
|
237
|
+
// should not be rendered. For in-flight async actions, use the loading
|
|
238
|
+
// state (state_loading) instead.
|
|
239
|
+
// Ruled by Peter 2026-07-15 (Button-CTA disabled-state adjudication).
|
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Button-Icon Component Token Definitions
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Stemma System naming: [Family]-[Type] = Button-Icon
|
|
5
5
|
* Type: Primitive (foundational component)
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Platform-agnostic token definitions for the Button-Icon component.
|
|
8
8
|
* Uses the defineComponentTokens() API to register tokens with the global
|
|
9
9
|
* ComponentTokenRegistry for pipeline integration.
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
|
+
* Two separate defineComponentTokens() calls are used — one per token family
|
|
12
|
+
* (spacing, sizing) — following the Avatar-Base pattern (avatar.tokens.ts). Every
|
|
13
|
+
* token registered by a single call is stamped with that call's `family`, so inset
|
|
14
|
+
* (spacing) and size (sizing) tokens must NOT share a call even though they live in
|
|
15
|
+
* the same file. The two branded results are exported separately and must NOT be
|
|
16
|
+
* spread/merged into one object — the rich metadata rides on a non-enumerable brand
|
|
17
|
+
* (see src/build/tokens/defineComponentTokens.ts, TOKEN_CONTRACT_BRAND) that a spread
|
|
18
|
+
* would silently drop.
|
|
19
|
+
*
|
|
11
20
|
* The build system generates platform-specific values from these definitions:
|
|
12
21
|
* - Web: CSS custom properties (var(--buttonicon-inset-large))
|
|
13
22
|
* - iOS: Swift constants (ButtonIconTokens.insetLarge)
|
|
14
23
|
* - Android: Kotlin constants (ButtonIconTokens.insetLarge)
|
|
15
|
-
*
|
|
24
|
+
*
|
|
16
25
|
* Token Relationships:
|
|
17
|
-
* - buttonIcon.inset.large (12px) references space150
|
|
18
|
-
* - buttonIcon.inset.medium (10px) references space125 (strategic flexibility token)
|
|
19
|
-
* - buttonIcon.inset.small (8px) references space100
|
|
20
|
-
* - buttonIcon.size.large (48px) references size600
|
|
21
|
-
* - buttonIcon.size.medium (40px) references size500
|
|
22
|
-
* - buttonIcon.size.small (32px) references size400
|
|
23
|
-
*
|
|
26
|
+
* - buttonIcon.inset.large (12px) references space150 — family: spacing
|
|
27
|
+
* - buttonIcon.inset.medium (10px) references space125 (strategic flexibility token) — family: spacing
|
|
28
|
+
* - buttonIcon.inset.small (8px) references space100 — family: spacing
|
|
29
|
+
* - buttonIcon.size.large (48px) references size600 — family: sizing
|
|
30
|
+
* - buttonIcon.size.medium (40px) references size500 — family: sizing
|
|
31
|
+
* - buttonIcon.size.small (32px) references size400 — family: sizing
|
|
32
|
+
*
|
|
24
33
|
* @see .kiro/specs/035-button-icon-component/design.md for token consumption strategy
|
|
25
34
|
* @see .kiro/specs/034-component-architecture-system for Stemma System details
|
|
26
35
|
* @see .kiro/specs/037-component-token-generation-pipeline for pipeline integration
|
|
@@ -32,28 +41,21 @@ import { spacingTokens } from '../../../tokens/SpacingTokens';
|
|
|
32
41
|
import { sizingTokens } from '../../../tokens/SizingTokens';
|
|
33
42
|
|
|
34
43
|
/**
|
|
35
|
-
* Button-Icon
|
|
36
|
-
*
|
|
44
|
+
* Button-Icon inset (padding) tokens — reference spacing primitives.
|
|
45
|
+
*
|
|
37
46
|
* Each token references a primitive token and includes reasoning
|
|
38
47
|
* explaining why the token exists and its purpose in the component.
|
|
39
|
-
*
|
|
40
|
-
* Inset (padding) token values — reference spacing primitives:
|
|
48
|
+
*
|
|
41
49
|
* - inset.large: 12px (1.5 × base, references space150)
|
|
42
50
|
* - inset.medium: 10px (1.25 × base, references space125 strategic flexibility token)
|
|
43
51
|
* - inset.small: 8px (1 × base, references space100)
|
|
44
|
-
*
|
|
45
|
-
* Size (width/height) token values:
|
|
46
|
-
* - size.large: 48px (6 × base, references size600)
|
|
47
|
-
* - size.medium: 40px (5 × base, references size500)
|
|
48
|
-
* - size.small: 32px (4 × base, references size400)
|
|
49
|
-
*
|
|
52
|
+
*
|
|
50
53
|
* @see Requirements 6.1, 6.2, 6.3 in .kiro/specs/040-component-alignment/requirements.md
|
|
51
54
|
*/
|
|
52
|
-
export const
|
|
55
|
+
export const ButtonIconInsetTokens = defineComponentTokens({
|
|
53
56
|
component: 'ButtonIcon',
|
|
54
57
|
family: 'spacing',
|
|
55
58
|
tokens: {
|
|
56
|
-
// Inset (padding) tokens
|
|
57
59
|
'inset.large': {
|
|
58
60
|
reference: spacingTokens.space150,
|
|
59
61
|
reasoning: 'Large button variant requires 12px padding (1.5× base) for comfortable touch target and visual balance with larger icon sizes',
|
|
@@ -66,8 +68,22 @@ export const ButtonIconTokens = defineComponentTokens({
|
|
|
66
68
|
reference: spacingTokens.space100,
|
|
67
69
|
reasoning: 'Small button variant uses 8px padding (1× base) for minimal footprint in dense UI layouts while meeting minimum touch target requirements',
|
|
68
70
|
},
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Button-Icon size (width/height) tokens — reference sizing primitives, not spacing.
|
|
76
|
+
*
|
|
77
|
+
* - size.large: 48px (6 × base, references size600)
|
|
78
|
+
* - size.medium: 40px (5 × base, references size500)
|
|
79
|
+
* - size.small: 32px (4 × base, references size400)
|
|
80
|
+
*
|
|
81
|
+
* @see Requirements 6.1, 6.2, 6.3 in .kiro/specs/040-component-alignment/requirements.md
|
|
82
|
+
*/
|
|
83
|
+
export const ButtonIconSizeTokens = defineComponentTokens({
|
|
84
|
+
component: 'ButtonIcon',
|
|
85
|
+
family: 'sizing',
|
|
86
|
+
tokens: {
|
|
71
87
|
'size.large': {
|
|
72
88
|
reference: sizingTokens.size600,
|
|
73
89
|
reasoning: 'Large button size (48px = 6× base) provides generous touch target exceeding tapAreaRecommended, calculated as icon (24px) + padding (12px × 2)',
|
|
@@ -107,7 +123,7 @@ export type ButtonIconSizeVariant = 'large' | 'medium' | 'small';
|
|
|
107
123
|
* ```
|
|
108
124
|
*/
|
|
109
125
|
export function getButtonIconInset(variant: ButtonIconInsetVariant): number {
|
|
110
|
-
return
|
|
126
|
+
return ButtonIconInsetTokens[`inset.${variant}`];
|
|
111
127
|
}
|
|
112
128
|
|
|
113
129
|
/**
|
|
@@ -126,7 +142,7 @@ export function getButtonIconInset(variant: ButtonIconInsetVariant): number {
|
|
|
126
142
|
* @see Requirements 6.1, 6.2, 6.3 in .kiro/specs/040-component-alignment/requirements.md
|
|
127
143
|
*/
|
|
128
144
|
export function getButtonIconSize(variant: ButtonIconSizeVariant): number {
|
|
129
|
-
return
|
|
145
|
+
return ButtonIconSizeTokens[`size.${variant}`];
|
|
130
146
|
}
|
|
131
147
|
|
|
132
148
|
/**
|
|
@@ -40,11 +40,24 @@ describe('Chip-Base Web Component', () => {
|
|
|
40
40
|
beforeEach(async () => {
|
|
41
41
|
// Wait for custom element to be defined
|
|
42
42
|
await customElements.whenDefined('chip-base');
|
|
43
|
+
// Silence ONLY the known environmental warn ("Could not calculate blend colors",
|
|
44
|
+
// fired async via rAF): jsdom never applies real CSS, so the token lookup cannot
|
|
45
|
+
// succeed here and the component's designed fallback fires every run, forever.
|
|
46
|
+
// Anything ELSE passes through to the real console — a NEW warn class stays audible.
|
|
47
|
+
const realWarn = console.warn.bind(console);
|
|
48
|
+
jest.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
|
|
49
|
+
// Component-prefixed match (Lina review, PR #39): the bare substring is shared by
|
|
50
|
+
// Button components too — prefix-matching prevents accidentally swallowing a
|
|
51
|
+
// cross-component warn if this suite ever composes a Button.
|
|
52
|
+
if (typeof args[0] === 'string' && args[0].includes('ChipBase: Could not calculate blend colors')) return;
|
|
53
|
+
realWarn(...args);
|
|
54
|
+
});
|
|
43
55
|
});
|
|
44
56
|
|
|
45
57
|
afterEach(() => {
|
|
46
58
|
// Clean up any created elements
|
|
47
59
|
cleanupDOM();
|
|
60
|
+
jest.restoreAllMocks();
|
|
48
61
|
});
|
|
49
62
|
|
|
50
63
|
// ============================================================================
|
|
@@ -42,11 +42,24 @@ describe('Chip-Filter Web Component', () => {
|
|
|
42
42
|
beforeEach(async () => {
|
|
43
43
|
// Wait for custom element to be defined
|
|
44
44
|
await customElements.whenDefined('chip-filter');
|
|
45
|
+
// Silence ONLY the known environmental warn ("Could not calculate blend colors",
|
|
46
|
+
// fired async via rAF): jsdom never applies real CSS, so the token lookup cannot
|
|
47
|
+
// succeed here and the component's designed fallback fires every run, forever.
|
|
48
|
+
// Anything ELSE passes through to the real console — a NEW warn class stays audible.
|
|
49
|
+
const realWarn = console.warn.bind(console);
|
|
50
|
+
jest.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
|
|
51
|
+
// Component-prefixed match (Lina review, PR #39): the bare substring is shared by
|
|
52
|
+
// Button components too — prefix-matching prevents accidentally swallowing a
|
|
53
|
+
// cross-component warn if this suite ever composes a Button.
|
|
54
|
+
if (typeof args[0] === 'string' && args[0].includes('ChipFilter: Could not calculate blend colors')) return;
|
|
55
|
+
realWarn(...args);
|
|
56
|
+
});
|
|
45
57
|
});
|
|
46
58
|
|
|
47
59
|
afterEach(() => {
|
|
48
60
|
// Clean up any created elements
|
|
49
61
|
cleanupDOM();
|
|
62
|
+
jest.restoreAllMocks();
|
|
50
63
|
});
|
|
51
64
|
|
|
52
65
|
// ============================================================================
|
|
@@ -41,11 +41,24 @@ describe('Chip-Input Web Component', () => {
|
|
|
41
41
|
beforeEach(async () => {
|
|
42
42
|
// Wait for custom element to be defined
|
|
43
43
|
await customElements.whenDefined('chip-input');
|
|
44
|
+
// Silence ONLY the known environmental warn ("Could not calculate blend colors",
|
|
45
|
+
// fired async via rAF): jsdom never applies real CSS, so the token lookup cannot
|
|
46
|
+
// succeed here and the component's designed fallback fires every run, forever.
|
|
47
|
+
// Anything ELSE passes through to the real console — a NEW warn class stays audible.
|
|
48
|
+
const realWarn = console.warn.bind(console);
|
|
49
|
+
jest.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
|
|
50
|
+
// Component-prefixed match (Lina review, PR #39): the bare substring is shared by
|
|
51
|
+
// Button components too — prefix-matching prevents accidentally swallowing a
|
|
52
|
+
// cross-component warn if this suite ever composes a Button.
|
|
53
|
+
if (typeof args[0] === 'string' && args[0].includes('ChipInput: Could not calculate blend colors')) return;
|
|
54
|
+
realWarn(...args);
|
|
55
|
+
});
|
|
44
56
|
});
|
|
45
57
|
|
|
46
58
|
afterEach(() => {
|
|
47
59
|
// Clean up any created elements
|
|
48
60
|
cleanupDOM();
|
|
61
|
+
jest.restoreAllMocks();
|
|
49
62
|
});
|
|
50
63
|
|
|
51
64
|
// ============================================================================
|