- v3.2.0 → v3.3.0
- v3.0.0 → v3.2.0
- v2.3.0 → v3.0.0
- v2.2.0 → v2.3.0
- v2.0.0 → v2.2.0
- v1.4.0 → v2.0.0
- v1.3.0 → v1.4.0
- v1.2.0 → v1.3.0
- v1.1.0 → v1.2.0
- v1.0.0 → v1.1.0
- Support
The version 3.3.0 embeds tokens library v2.8.0 with several changes.
| Before (v3.2 — deprecated in v3.3) | After (v3.3) |
|---|---|
theme.listItem.colorBgBadgeSafetyArea |
theme.listItem.colorBadgeSafetyArea |
// Before (v3.2)
theme.listItem.colorBgBadgeSafetyArea
// After (v3.3)
theme.listItem.colorBadgeSafetyAreaThe former token remains available as a deprecated alias forwarding to colorBadgeSafetyArea.
Update call sites and custom providers, including overrides: components now use the new token,
so overriding only the deprecated property no longer customizes the value used by those components.
Required action: Rename colorBgBadgeSafetyArea to colorBadgeSafetyArea
| Before (v3.2 — deprecated in v3.3) | After (v3.3) |
|---|---|
theme.pinCodeInput.sizeMinWidth |
theme.pinCodeInput.sizeMinWidthDigitInput |
theme.pinCodeInput.sizeMaxWidth |
theme.pinCodeInput.sizeMaxWidthDigitInput |
// Before (v3.2)
theme.pinCodeInput.sizeMinWidth
theme.pinCodeInput.sizeMaxWidth
// After (v3.3)
theme.pinCodeInput.sizeMinWidthDigitInput
theme.pinCodeInput.sizeMaxWidthDigitInputThe former names remain available as deprecated aliases forwarding to the new tokens.
Required action: Rename these tokens in PIN code input usages, custom provider declarations,
overrides and associated tests. Components now read the new tokens, so custom providers must
override the new properties to customize their rendering. Do not rename sizeMinWidth or
sizeMaxWidth globally: other components can still use those names.
| Before (v3.2 — deprecated in v3.3) | After (v3.3) |
|---|---|
theme.textInput.spacePaddingBlockTopHelperText |
theme.textInput.spacePaddingBlockHelperText |
theme.textInput.spacePaddingInlineTrailingAction |
theme.textInput.spacePaddingInlineLeadingTrailingAction |
// Before (v3.2)
theme.textInput.spacePaddingBlockTopHelperText
theme.textInput.spacePaddingInlineTrailingAction
// After (v3.3)
theme.textInput.spacePaddingBlockHelperText
theme.textInput.spacePaddingInlineLeadingTrailingActionThe former names are deprecated in TextInputComponentTokens, not removed from the protocol.
Required action: Rename these tokens in text input usages, custom provider declarations, overrides and associated tests. Components now read the new tokens, so custom providers must override the new properties to customize their rendering. Scope these renames to text input tokens rather than replacing similarly named properties of other components.
| Before (v3.2 — deprecated in v3.3) | After (v3.3) |
|---|---|
theme.colors.overlayFloating |
theme.colors.overlaySticky |
theme.colors.overlayFloatingLight |
theme.colors.overlayStickyLight |
theme.colors.overlayFloatingDark |
theme.colors.overlayStickyDark |
// Before (v3.2)
theme.colors.overlayFloating
theme.colors.overlayFloatingLight
theme.colors.overlayFloatingDark
// After (v3.3)
theme.colors.overlaySticky
theme.colors.overlayStickyLight
theme.colors.overlayStickyDarkThe former names remain available as deprecated aliases forwarding to the new tokens in all four themes.
overlaySticky combines overlayStickyLight and overlayStickyDark without changing the theme's values.
Required action: Rename usages, custom color provider overrides and associated tests.
Custom implementations of ColorSemanticTokens and ColorMultipleSemanticTokens must implement
the new requirements. Override the new names to customize the values consumed by updated code;
overriding only a deprecated alias does not customize the new token.
The following semantic tokens are now internal to Figma and have been removed from the Swift protocols:
contentStatusInversePositiveLightandcontentStatusInversePositiveDarkcontentStatusInverseInfoLightandcontentStatusInverseInfoDarkcontentStatusInverseWarningLightandcontentStatusInverseWarningDarkcontentStatusInverseNegativeLightandcontentStatusInverseNegativeDarkopacityTransparentInverseLightandopacityTransparentInverseDarkopacityTransparentInverse(the light/dark composite token)
Required action: Remove their usages, declarations and overrides from custom color providers,
and adapt associated tests. There is no automatic replacement: review the visual context before
choosing another supported token. Internal to Figma does not mean these tokens remain accessible
through a Swift internal API.
Unchanged: opacityTransparent, opacityTransparentLight and opacityTransparentDark
remain available. Do not remove or rename these non-inverse tokens.
To detect the removed families and deprecated overlay names in application sources, including custom provider declarations:
grep -rnE \
'contentStatusInverse|opacityTransparentInverse|overlayFloating' \
--include="*.swift" .The following tokens have been removed from IconComponentTokens and are now internal to Figma.
theme.icon.colorContentStatusWarningInverseInternalShapetheme.icon.colorContentStatusWarningInverseExternalShape
Required action: Remove them.
FontRawTokens.familyMonospaceMonaco has been removed, not deprecated, in v3.3.0
(tokens library v2.8.0).
There is no automatic replacement. Choose a remaining font family according to your needs; do not assume that Menlo or another font is an equivalent replacement for Monaco.
The OUDSListItemData API has been reorganized so that every textual field
(label, description, overline, extraLabel, helperText) can accept a raw String,
a localized string or a styled AttributedString, instead of only the overline.
The six former initializers (one per combination of label type × overline type) are now
deprecated and replaced by two unified initializers. The OUDSListItemData.Label.text case is
deprecated in favor of the new .textual case.
The OUDSBulletList.Item and OUDSAlertMessage initializers follow the same logic: the String, AttributedString
(and LocalizedStringKey for the bullet list item) initializers are deprecated and replaced by initializers taking OUDSTextualContent.
- Use version 3.0.0 or later.
The previously-internal OUDSTextualContent enum is now public and @frozen. It represents
a textual value that can be a raw String, a localized string or a styled AttributedString:
@frozen
public enum OUDSTextualContent: @unchecked Sendable, ExpressibleByStringLiteral {
case raw(String)
case localized(_: LocalizedStringKey, tableName: String? = nil, bundle: Bundle = .main)
case rich(AttributedString)
}Thanks to the ExpressibleByStringLiteral conformance, a string literal is implicitly
converted to .raw(…), so plain-text call sites stay concise.
public enum Label: ExpressibleByStringLiteral {
@available(*, deprecated) case text(_: String, isBold: Bool = false)
case textual(_: OUDSTextualContent, isBold: Bool = false) // new in v3.2.0
case custom(_ view: AnyView, accessibilityLabel: String)
}Label also conforms to ExpressibleByStringLiteral: a string literal converts to
.textual(.raw(literal), isBold: false). A styled label is .textual(.rich(myAttributedString))
and a localized one is .textual(.localized("key")).
// Replaces the initializers with `label: String` / `key: LocalizedStringKey`
public init(
label: Label,
description: OUDSTextualContent? = nil,
overline: OUDSTextualContent? = nil,
extraLabel: OUDSTextualContent? = nil,
helperText: OUDSTextualContent? = nil,
textSlot: Slot? = nil,
bottomSlot: Slot? = nil)
// Replaces the initializers with `label: some View`
public init(
label: some View,
accessibilityLabel: String,
description: OUDSTextualContent? = nil,
overline: OUDSTextualContent? = nil,
extraLabel: OUDSTextualContent? = nil,
helperText: OUDSTextualContent? = nil,
textSlot: Slot? = nil,
bottomSlot: Slot? = nil)In v4,
.textualwill be renamed.text, when the deprecated API is removed.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (v3.0 — deprecated) | After (v3.2) |
|---|---|
OUDSListItemData(label: "Foo") |
OUDSListItemData(label: .textual("Foo")) |
OUDSListItemData(label: "Foo", hasBoldLabel: true) |
OUDSListItemData(label: .textual("Foo", isBold: true)) |
OUDSListItemData(label: "Foo", description: "Bar", overline: "Over") |
unchanged (description and overline are now OUDSTextualContent) |
OUDSListItemData(label: "Foo", overline: myAttr) |
OUDSListItemData(label: "Foo", overline: .rich(myAttr)) |
OUDSListItemData(label: myView, accessibilityLabel: "Foo") |
unchanged |
OUDSListItemData(key: "foo.label") |
OUDSListItemData(label: .textual(.localized("foo.label"))) |
.text("Foo", isBold: true) (on Label) |
.textual("Foo", isBold: true) |
New capability — any textual field can now be styled or localized:
// Before (v3.0) — only `overline` could be styled
OUDSListItemData(label: "Foo", overline: myStyledOverline)
// After (v3.2) — any textual field can be styled or localized
OUDSListItemData(
label: .textual(.rich(myStyledLabel)),
description: .rich(myStyledDescription),
overline: .rich(myStyledOverline),
extraLabel: .localized("extra.label.key"),
helperText: "Plain string literal")Required Action:
- Replace
OUDSListItemData(label: "Foo")(a label alone, or with onlytextSlot/bottomSlot) withOUDSListItemData(label: .textual("Foo")), see the note below. - Replace
hasBoldLabel: truewith.textual("Foo", isBold: true). - Replace
key: LocalizedStringKeywith.textual(.localized(key, tableName:, bundle:)). - Replace
overline: myAttributedStringwithoverline: .rich(myAttributedString)and move theoverline:parameter to its canonical position (afterdescription:in the new init order). - Replace any
Label.text(…)usage with.textual(…).
Note on overload resolution: the new initializers reuse the
label:argument label of the deprecated ones, andLabelas well asAttributedStringare expressible by a string literal. As a consequence, two call forms may select a deprecated initializer and emit a deprecation warning, even if the intent is the new API:
- a bare literal label with no textual field, for example
OUDSListItemData(label: "Foo")or with onlytextSlot/bottomSlot. Writelabel: .textual("Foo")instead;- a custom view label with a literal
overline, for exampleOUDSListItemData(label: myView, accessibilityLabel: "Foo", overline: "Over"). Writeoverline: .raw("Over")instead.As soon as
description,overline,extraLabelorhelperTextis given with a literal next to a literal label (OUDSListItemData(label: "Foo", description: "Bar")) the new initializer is selected without any warning.
Reason for Change: Unify the API so that every textual field of a list item can carry rich text, not only the overline, without multiplying initializer overloads.
The three initializers of OUDSBulletList.Item (String, AttributedString and LocalizedStringKey)
are deprecated and replaced by a single one taking an OUDSTextualContent:
public init(_ text: OUDSTextualContent,
subListType: OUDSBulletList.Type? = nil,
subListTextStyle: OUDSBulletList.TextStyle? = nil,
subListHasBoldText: Bool? = nil,
@OUDSBulletListItemBuilder subItems: () -> [OUDSBulletList.Item] = { [] })Impact: Low — all existing call sites keep working; only deprecation warnings appear.
String literals still work as is (OUDSBulletList.Item("Label") is .raw("Label")), without warning.
| Before (deprecated) | After (v3.2) |
|---|---|
OUDSBulletList.Item("Foo") with a literal |
unchanged |
OUDSBulletList.Item(someString) |
OUDSBulletList.Item(.raw(someString)) |
OUDSBulletList.Item(myAttributedString) |
OUDSBulletList.Item(.rich(myAttributedString)) |
OUDSBulletList.Item(LocalizedStringKey("key"), bundle: .module) |
OUDSBulletList.Item(.localized("key", bundle: .module)) |
Required Action:
- Replace
Item(someString)withItem(.raw(someString))when the value is not a literal. - Replace
Item(myAttributedString)withItem(.rich(myAttributedString)). - Replace
Item(LocalizedStringKey(…), tableName:, bundle:)withItem(.localized(…, tableName:, bundle:)).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads.
The eight initializers of OUDSAlertMessage (label as String or LocalizedStringKey × description as String or
AttributedString × bulletList as [String] or [AttributedString]) are deprecated and replaced by two unified ones:
public init(label: String,
status: OUDSAlertStatus = .positive,
description: OUDSTextualContent? = nil,
bulletList: [OUDSTextualContent] = [],
link: Link? = nil,
onClose: (() -> Void)? = nil)
public init(_ key: LocalizedStringKey,
tableName: String? = nil,
bundle: Bundle = .main,
status: OUDSAlertStatus = .positive,
description: OUDSTextualContent? = nil,
bulletList: [OUDSTextualContent] = [],
link: Link? = nil,
onClose: (() -> Void)? = nil)Impact: Low — all existing call sites keep working; only deprecation warnings appear.
String literals still work as is (description: "Foo", bulletList: ["A", "B"]), without warning.
| Before (deprecated) | After (v3.2) |
|---|---|
description: "Foo" / bulletList: ["A", "B"] with literals |
unchanged |
description: someString |
description: .raw(someString) |
description: myAttributedString |
description: .rich(myAttributedString) |
bulletList: someStrings |
bulletList: someStrings.map { .raw($0) } |
bulletList: myAttributedStrings |
bulletList: myAttributedStrings.map { .rich($0) } |
Required Action:
- Replace
description: myAttributedStringwithdescription: .rich(myAttributedString). - Replace
description: someStringVariablewithdescription: .raw(someStringVariable). - Replace
bulletList: [AttributedString]andbulletList: [String]variables with arrays of.rich(…)/.raw(…); an array literal can also mix raw literals,.localized(…)and.rich(…).
Note on string literals: with the
LocalizedStringKeyinitializer,description: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringis itself expressible by a string literal. Writedescription: .raw("abc")to select the new initializer.
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads.
The four initializers of OUDSSwitchItem (label as String or LocalizedStringKey × errorText as String or AttributedString)
are deprecated and replaced by two unified ones taking errorText: OUDSTextualContent? = nil.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
errorText: someString |
errorText: .raw(someString) |
errorText: "Message" (literal) |
errorText: .raw("Message") |
errorText: myAttributedString |
errorText: .rich(myAttributedString) |
errorText: nil or no errorText |
unchanged |
Note on string literals:
errorText: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringis itself expressible by a string literal. WriteerrorText: .raw("abc")to select the new initializer.
Required Action:
- Replace
errorText: myAttributedStringwitherrorText: .rich(myAttributedString). - Replace
errorText: someStringVariableorerrorText: "Message"witherrorText: .raw(…).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads.
The four initializers of OUDSCheckboxItem (label as String or LocalizedStringKey × errorText as String or AttributedString)
are deprecated and replaced by two unified ones taking errorText: OUDSTextualContent? = nil.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
errorText: someString |
errorText: .raw(someString) |
errorText: "Message" (literal) |
errorText: .raw("Message") |
errorText: myAttributedString |
errorText: .rich(myAttributedString) |
errorText: nil or no errorText |
unchanged |
Note on string literals:
errorText: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringis itself expressible by a string literal. WriteerrorText: .raw("abc")to select the new initializer.
Required Action:
- Replace
errorText: myAttributedStringwitherrorText: .rich(myAttributedString). - Replace
errorText: someStringVariableorerrorText: "Message"witherrorText: .raw(…).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads.
The four initializers of OUDSRadioItem (label as String or LocalizedStringKey × errorText as String or AttributedString)
are deprecated and replaced by two unified ones taking errorText: OUDSTextualContent? = nil.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
errorText: someString |
errorText: .raw(someString) |
errorText: "Message" (literal) |
errorText: .raw("Message") |
errorText: myAttributedString |
errorText: .rich(myAttributedString) |
errorText: nil or no errorText |
unchanged |
Note on string literals:
errorText: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringis itself expressible by a string literal. WriteerrorText: .raw("abc")to select the new initializer.
Required Action:
- Replace
errorText: myAttributedStringwitherrorText: .rich(myAttributedString). - Replace
errorText: someStringVariableorerrorText: "Message"witherrorText: .raw(…).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads.
The two initializers of OUDSCheckboxItemIndeterminate (label as String or LocalizedStringKey) now take errorText: OUDSTextualContent? = nil
instead of errorText: String? = nil. The error message can now also be a localized string or a rich AttributedString, which was not possible before.
The former initializers taking errorText: String? are deprecated.
Impact: Low — all existing call sites keep working; only calls passing a String variable emit a deprecation warning.
String literals, nil or omitted errorText still work as is, without warning.
| Before (deprecated) | After (v3.2) |
|---|---|
errorText: someString |
errorText: .raw(someString) |
errorText: "Message" (literal), nil or omitted |
unchanged |
Required Action:
- Replace
errorText: someStringVariablewitherrorText: .raw(someStringVariable).
Reason for Change: Unify the API around OUDSTextualContent and let the error message be rich or localized like for the other checkbox, radio and switch items.
The three initializers of OUDSPinCodeInput (helperText as String, AttributedString, or LocalizedStringKey with helperText key:, tableName: and bundle:)
are deprecated and replaced by a single one taking helperText: OUDSTextualContent? = nil.
The OUDSPinCodeInput.Status cases .error(message: String) and .richError(message: AttributedString) are deprecated and replaced by
.textualError(message: OUDSTextualContent). In v4, .textualError will be renamed .error.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
helperText: someString or helperText: "Message" |
helperText: .raw(…) |
helperText: myAttributedString |
helperText: .rich(myAttributedString) |
helperText: LocalizedStringKey("key"), tableName: t, bundle: b |
helperText: .localized("key", tableName: t, bundle: b) |
status: .error(message: "Message") |
status: .textualError(message: "Message") |
status: .richError(message: myAttributedString) |
status: .textualError(message: .rich(myAttributedString)) |
helperText: nil or no helperText |
unchanged |
Note on string literals:
helperText: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringandLocalizedStringKeyare themselves expressible by a string literal. WritehelperText: .raw("abc")to select the new initializer.
Required Action:
- Replace
helperText: myAttributedStringwithhelperText: .rich(myAttributedString). - Replace
helperText: someStringVariableorhelperText: "Message"withhelperText: .raw(…). - Replace
helperText: LocalizedStringKey(…), tableName:, bundle:withhelperText: .localized(…, tableName:, bundle:). - Replace
.error(message:)and.richError(message:)with.textualError(message:).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads or status cases.
The four initializers of OUDSTextInput (label as String or LocalizedStringKey × helperText as String or AttributedString)
are deprecated and replaced by two unified ones taking helperText: OUDSTextualContent? = nil.
The OUDSTextInput.Status cases .error(message: String) and .richError(message: AttributedString) are deprecated and replaced by
.textualError(message: OUDSTextualContent). In v4, .textualError will be renamed .error.
This Status is also the one used by OUDSPasswordInput.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
helperText: someString or helperText: "Message" |
helperText: .raw(…) |
helperText: myAttributedString |
helperText: .rich(myAttributedString) |
status: .error(message: "Message") |
status: .textualError(message: "Message") |
status: .richError(message: myAttributedString) |
status: .textualError(message: .rich(myAttributedString)) |
helperText: nil or no helperText |
unchanged |
Note on string literals:
helperText: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringis itself expressible by a string literal. WritehelperText: .raw("abc")to select the new initializer.
Required Action:
- Replace
helperText: myAttributedStringwithhelperText: .rich(myAttributedString). - Replace
helperText: someStringVariableorhelperText: "Message"withhelperText: .raw(…). - Replace
.error(message:)and.richError(message:)with.textualError(message:).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads or status cases.
The four initializers of OUDSPasswordInput (label as String or LocalizedStringKey × helperText as String or AttributedString)
are deprecated and replaced by two unified ones taking helperText: OUDSTextualContent? = nil.
Its status is the OUDSTextInput.Status: see the OUDSTextInput section above for .textualError(message:).
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
helperText: someString or helperText: "Message" |
helperText: .raw(…) |
helperText: myAttributedString |
helperText: .rich(myAttributedString) |
helperText: nil or no helperText |
unchanged |
Note on string literals:
helperText: "abc"(a bare literal) may select a deprecated initializer and emit a deprecation warning, becauseAttributedStringis itself expressible by a string literal. WritehelperText: .raw("abc")to select the new initializer.
Required Action:
- Replace
helperText: myAttributedStringwithhelperText: .rich(myAttributedString). - Replace
helperText: someStringVariableorhelperText: "Message"withhelperText: .raw(…). - Replace
status: .error(message:)and.richError(message:)with.textualError(message:).
Reason for Change: Unify the API around OUDSTextualContent without multiplying initializer overloads.
OUDSTextArea has no initializer to deprecate, but its two enums changed:
OUDSTextArea.HelperText.plain(String)and.rich(AttributedString)are deprecated and replaced by.textual(_: OUDSTextualContent)..charactersMaxCount(_:)is unchanged.OUDSTextArea.Status.error(message: String)and.richError(message: AttributedString)are deprecated and replaced by.textualError(message: OUDSTextualContent). In v4,.textualErrorwill be renamed.error.
Impact: Low — all existing call sites keep working; only deprecation warnings appear.
| Before (deprecated) | After (v3.2) |
|---|---|
helperText: .plain("Message") |
helperText: .textual("Message") |
helperText: .plain(someString) |
helperText: .textual(.raw(someString)) |
helperText: .rich(myAttributedString) |
helperText: .textual(.rich(myAttributedString)) |
status: .error(message: "Message") |
status: .textualError(message: "Message") |
status: .richError(message: myAttributedString) |
status: .textualError(message: .rich(myAttributedString)) |
helperText: .charactersMaxCount(500) |
unchanged |
Required Action:
- Replace
.plain(…)with.textual(…)(a string literal is enough, aStringvariable needs.raw(…)). - Replace
.rich(myAttributedString)with.textual(.rich(myAttributedString)). - Replace
.error(message:)and.richError(message:)with.textualError(message:).
Reason for Change: Unify the API around OUDSTextualContent without multiplying enum cases.
Tokens version 2.6 are integrated in the OUDS code base and contains several breaking changes with renamed or delete tokens, at least at components tokens levels.
- Use version 2.3 or older
The tokens of sizes and spaces for button component have been renamed.
Impact: High
| Old v2 name | New v3 name |
|---|---|
sizeMaxHeightIconOnly |
sizeMaxHeightIconOnlyDefault |
sizeMinHeight |
sizeMinHeightDefault |
sizeMinWidth |
sizeMinWidthDefault |
sizeIcon |
sizeIconDefault |
sizeIconOnly |
sizeIconOnlyDefault |
sizeProgressIndicator |
sizeProgressIndicatorDefault |
spaceColumnGapIconChevron |
spaceColumnGapIconChevronDefault |
spaceColumnGapChevron |
spaceColumnGapChevronDefault |
spaceInsetIconOnly |
spaceInsetIconOnlyDefault |
spacePaddingBlock |
spacePaddingBlockDefault |
spacePaddingInlineChevronEnd |
spacePaddingInlineChevronEndDefault |
spacePaddingInlineChevronStart |
spacePaddingInlineChevronStartDefault |
spacePaddingInlineEndIconStart |
spacePaddingInlineEndIconStartDefault |
spacePaddingInlineIconNone |
spacePaddingInlineIconNoneDefault |
spacePaddingInlineStartIconEnd |
spacePaddingInlineStartIconEndDefault |
For example, before:
theme.button.sizeMinHeightand after:
theme.button.sizeMinHeightDefaultRequired Action:
- Add suffix
Defaultto the components tokens of sizes and spaces forbuttoncomponent
Reason for Change: Renaming of tokens in Figma specification
Some component tokens for tag component have been renamed.
Impact: High
| Old v2 name | New v3 name |
|---|---|
spaceInsetLoaderSmall |
spaceInsetProgressIndicatorSmall |
spaceInsetLoaderDefault |
spaceInsetProgressIndicatorDefault |
For example, before:
theme.tag.spaceInsetLoaderSmalland after:
theme.tag.spaceInsetProgressIndicatorSmallRequired Action:
Loadermust be replaced byProgressIndicator
Reason for Change: Renaming of tokens in Figma specification
The hasLoader: Bool parameter of OUDSTag(label:...) and OUDSTag(_ key:...) has been removed.
Loading tags must now be built exclusively with the dedicated loadingLabel / loadingKey initializers,
which also gained a new optional progress: Double? parameter (nil for indeterminate progress, a value
between 0.0 and 1.0 for determinate progress), mirroring the OUDSButton.Style.loading(progress:) change.
Impact: High
Before (v2.3.0):
OUDSTag(label: "Processing...", hasLoader: true)
OUDSTag(loadingLabel: "Processing...")After (v3.0.0):
// Indeterminate progress
OUDSTag(loadingLabel: "Processing...")
// Determinate progress with percent
OUDSTag(loadingLabel: "Processing...", progress: 0.75)Required Action:
- Replace any use of
OUDSTag(label:hasLoader: true, ...)orOUDSTag(_ key:hasLoader: true, ...)withOUDSTag(loadingLabel:...)orOUDSTag(loadingKey:...) - The
hasLoaderparameter no longer exists onOUDSTag(label:...)/OUDSTag(_ key:...); simply remove it if it wasfalse - Optionally pass a
progressvalue toOUDSTag(loadingLabel:...)/OUDSTag(loadingKey:...)for a determinate progress indicator
Reason for Change: Use the circular progress indicator in determinate or indeterminate variant, and avoid an ambiguous API mixing status and loading tags in a single initializer
The tokens of sizes and spaces for link component have been renamed.
Impact: High
| Old v2 name | New v3 name |
|---|---|
spacePaddingBlock |
spacePaddingBlockDefault |
sizeMinWidthDefault |
sizeMinWidth |
For example, before:
theme.link.spacePaddingBlockand after:
theme.link.spacePaddingBlockDefaultRequired Action:
- Add suffix
Defaultto some of the components tokens of sizes and spaces forlinkcomponent
Reason for Change: Renaming of tokens in Figma specification
The tokens of spaces for accordion component have been renamed.
Impact: High
| Old v2 name | New v3 name |
|---|---|
spacePaddingBlockBottomSlotListItemContainerMobile |
spacePaddingBlockBottomSlotContainerMobile |
spacePaddingBlockBottomSlotListItemContainerTablet |
spacePaddingBlockBottomSlotContainerTablet |
For example, before:
theme.accordion.spacePaddingBlockBottomSlotListItemContainerMobileand after:
theme.accordion.spacePaddingBlockBottomSlotContainerMobileRequired Action:
- Remove
ListItemfrom the token names foraccordioncomponent
Reason for Change: Renaming of tokens in Figma specification
The token of size for alert message component has been renamed.
Impact: High
| Old v2 name | New v3 name |
|---|---|
sizeIcon |
sizeAsset |
For example, before:
theme.alertMessage.sizeIconand after:
theme.alert.sizeAssetRequired Action:
- Replace
sizeIconbysizeAssetforalertMessagecomponent, and change name of token provider
Reason for Change: Renaming of tokens in Figma specification
An old deprecated token has finally been removed from icon component tokens.
Impact: High
Required Action:
- Replace any use of
theme.icon.colorContentDefaultbytheme.colors.contentDefaultif relevant
The tokens provider for control item has been renamed to list item.
This affects both the theme accessor and all public Swift types (classes, protocols).
Impact: High
Required Action:
- Replace any use of
theme.controlItembytheme.listItem - Rename Swift types according to the table below:
| Old type (v2.3.0) | New type (v3.0.0) |
|---|---|
OrangeThemeControlItemComponentTokensProvider |
OrangeThemeListItemComponentTokensProvider |
OrangeCompactThemeControlItemComponentTokensProvider |
OrangeCompactThemeListItemComponentTokensProvider |
SoshThemeControlItemComponentTokensProvider |
SoshThemeListItemComponentTokensProvider |
WireframeThemeControlItemComponentTokensProvider |
WireframeThemeListItemComponentTokensProvider |
AllControlItemComponentTokensProvider |
AllListItemComponentTokensProvider |
ControlItemComponentTokens |
ListItemComponentTokens |
// Before (v2.3.0)
class MyProvider: OrangeThemeControlItemComponentTokensProvider { … }
let provider: AllControlItemComponentTokensProvider = MyProvider()
// After (v3.0.0)
class MyProvider: OrangeThemeListItemComponentTokensProvider { … }
let provider: AllListItemComponentTokensProvider = MyProvider()Reason for Change: "control item" does not exist anymore in Figma but "list item" does
To be aligned with new OUDSImage logic, the Layout for the OUDSChipPickerData has been refactored.
Before (v2.3.0):
.icon(icon: Image("someImage"), accessibilityLabel: "Foo", renderingMode: .original)
.textAndIcon(text: "Foo", icon: Image("someImage"), renderingMode: .original)After (v3.0.0):
.image(image: OUDSImage(asset: Image("someImage"), accessibilityLabel: "Foo", renderingMode: .original))
.textAndImage(text: "Foo", image: OUDSImage(asset: Image("someImage"), renderingMode: .original))Impact: High
Required Action:
- Replace any use of
.icon(icon:accessibilityLabel:renderingMode)by.image(image:) - Replace any use of
.textAndIcon(text:icon)by.textAndImage(text:image:)
Reason for Change: Use new OUDSImage API
To be aligned with new OUDSImage API, the parameter names of alert status cases have been changed.
Before (v2.3.0):
.neutral(icon: someOudsImage)
.accent(icon: someOudsImage)After (v3.0.0):
.neutral(image: someOudsImage)
.accent(image: someOudsImage)Impact: High
Required Action:
- Replace any use of
.neutral(icon:)by.neutral(image:) - Replace any use of
.accent(icon:)by.accent(image:)
Reason for Change: Use new OUDSImage API
To be aligned with new OUDSImage API, the accent and neutral badge icon status cases have been updated.
Before (v2.3.0):
.neutral(icon: Image("someImage"), flipped: false, renderingMode: .original)
.accent(icon: Image("someImage"), flipped: false, renderingMode: .original)After (v3.0.0):
.neutral(image: OUDSImage(asset: Image("someImage"), flipped: false, renderingMode: .original))
.accent(image: OUDSImage(asset: Image("someImage"), flipped: false, renderingMode: .original))Impact: High
Required Action:
- Replace any use of
.neutral(icon:flipped:renderingMode)by.neutral(image:) - Replace any use of
.accent(icon:flipped:renderingMode:)by.accent(image:)
Reason for Change: Use new OUDSImage API
The .forceOUDSLegacyTabBar() view modifier and its underlying OUDSLegacyTabBarModifier type have been renamed to reflect a broader layout scope.
Impact: High
| Old v2 name | New v3 name |
|---|---|
forceOUDSLegacyTabBar |
forceOUDSLegacyLayout |
OUDSLegacyTabBarModifier |
OUDSLegacyLayoutModifier |
Before (v2.3.0):
SomeView()
.forceOUDSLegacyTabBar()
let modifier: OUDSLegacyTabBarModifier = ...After (v3.0.0):
SomeView()
.forceOUDSLegacyLayout()
let modifier: OUDSLegacyLayoutModifier = ...Required Action:
- Replace any call to
.forceOUDSLegacyTabBar()with.forceOUDSLegacyLayout() - Replace any reference to
OUDSLegacyTabBarModifierwithOUDSLegacyLayoutModifier
Reason for Change: The modifier is no longer specific to the tab bar; it applies to the overall layout.
The OUDSLink.Indicator enum case for backward navigation has been renamed from .back to .previous.
Impact: High
Before (v2.3.0):
OUDSLink(text: "Back", indicator: .back, size: .default) { }After (v3.0.0):
OUDSLink(text: "Back", indicator: .previous, size: .default) { }Required Action:
- Replace any use of
indicator: .backwithindicator: .previousinOUDSLinkcalls
Reason for Change: Improved semantic clarity — .previous better describes the navigation direction relative to the current page.
Because the OUDSTextArea component now uses OUDSCircularProgressIndicator, a progress value can be assigned to the indicator.
This new progress parameter even if optional can break pattern matching.
Impact: Low
Before (v2.3.0):
OUDSTextArea.Status.loading()After (v3.0.0):
OUDSTextArea.Status.loading(someProgresValue)The OUDSButton.Style enum case for loading takes an optional progress (nil for indeterminate progress, Double for a percentage of progress).
Impact: High
Before (v2.3.0):
OUDSButton(text: "Back", style: .loading, size: .default) { }After (v3.0.0):
// Indeterminate progress
OUDSButton(text: "Back", style: .loading(), size: .default) { }
// Determinate progress with percent
OUDSButton(text: "Back", style: .loading(progress: 0.75), size: .default) { }Required Action:
- Replace any use of
style: .loadingwithstyle: .loading()inOUDSButtoncalls
Reason for Change: Use the circular progress indicator in determinate or indeterminate variant.
- Backward Compatibility: No
- v2.3.0 Support: None
Work on original images integrations in components brings API updates to group parameters related
to images / icons into one single object type. OUDSIcon is now OUDSImage.
- Use version 2.2 or older
The OUDSIcon type is deprecated. Use instead OUDSImage.
Impact: Low
Before (v2.2.0):
OUDSIcon(asset: Image("ic_heart"), accessibilityLabel: LocalizedStringKey("like_icon"), bundle: Bundle.module)
OUDSIcon(asset: Image("ic_heart"), accessibilityLabel: "Like", renderingMode: .original)After (v2.3.0):
OUDSImage(asset: Image("ic_heart"), accessibilityLabel: LocalizedStringKey("like_icon"), bundle: Bundle.module)
OUDSImage(asset: Image("ic_heart"), accessibilityLabel: "Like", renderingMode: .original)Required Action:
- Rename the
OUDSIconcalls byOUDSImage
Reason for Change: "icon" is too strict in meanings, "image" is more open.
OUDSButton initialisers that accepted a bare Image together with separate icon, flipIcon, renderingMode and accessibilityLabel parameters are deprecated.
Use the new initialisers that accept an OUDSImage value instead; OUDSImage encapsulates the asset, the flip flag, the rendering mode and the accessibility label in one object.
Impact: Low
Before (v2.2.0):
// Text + icon (String label)
OUDSButton(text: "Like", icon: Image("ic_heart"), appearance: .default) {}
// Text + icon (flipped for RTL, original rendering)
OUDSButton(text: "Back", icon: Image("ic_chevron"), flipIcon: true, renderingMode: .original, appearance: .default) {}
// Text + icon (LocalizedStringKey)
OUDSButton(LocalizedStringKey("action_like"), icon: Image("ic_heart"), appearance: .default) {}
// Icon only (String accessibility label)
OUDSButton(icon: Image("ic_heart"), accessibilityLabel: "Like", appearance: .default) {}
// Icon only (LocalizedStringKey accessibility label)
OUDSButton(icon: Image("ic_heart"), accessibilityLabel: LocalizedStringKey("like_icon"), bundle: Bundle.module, appearance: .default) {}After (v2.3.0):
// Text + icon (no accessibility label needed on OUDSImage — decorative in this context)
OUDSButton(text: "Like", image: OUDSImage(asset: Image("ic_heart")), appearance: .default) {}
// Text + icon (flipped for RTL, original rendering)
OUDSButton(text: "Back", image: OUDSImage(asset: Image("ic_chevron"), flipped: true, renderingMode: .original), appearance: .default) {}
// Text + icon (LocalizedStringKey)
OUDSButton(LocalizedStringKey("action_like"), image: OUDSImage(asset: Image("ic_heart")), appearance: .default) {}
// Icon only — accessibilityLabel is now carried by OUDSImage
OUDSButton(image: OUDSImage(asset: Image("ic_heart"), accessibilityLabel: "Like"), appearance: .default) {}
// Icon only — LocalizedStringKey accessibility label
OUDSButton(image: OUDSImage(asset: Image("ic_heart"), accessibilityLabel: LocalizedStringKey("like_icon"), bundle: Bundle.module), appearance: .default) {}Required Action:
- Replace every
icon: Image(…)parameter withimage: OUDSImage(asset: Image(…)) - Move the
flipIcon: Boolvalue toOUDSImage(asset:flipped:)(parameter renamedflipped) - Move the
renderingMode:value toOUDSImage(asset:renderingMode:) - Move the
accessibilityLabel:value (bothStringandLocalizedStringKeyforms) toOUDSImage(asset:accessibilityLabel:)orOUDSImage(asset:accessibilityLabel:tableName:bundle:) - Remove the now-unused
flipIcon,renderingModeandaccessibilityLabelparameters from theOUDSButtoncall site
Reason for Change: Grouping image-related parameters (icon, flipIcon, renderingMode, accessibilityLabel) into one OUDSImage object makes the call site cleaner, reduces the number of parameters on OUDSButton, and aligns with the same pattern used by other components (OUDSLink, OUDSSuggestionChip, OUDSFilterChip, …).
Deprecated OUDSCheckboxItem, OUDSCheckboxItemIndeterminate and OUDSCheckboxPickerData initialisers with icon parameter
Initialisers of OUDSCheckboxItem, OUDSCheckboxItemIndeterminate and OUDSCheckboxPickerData that accepted a bare Image together with separate flipIcon and renderingMode parameters are deprecated.
Use the new initialisers that accept an OUDSImage? value instead; OUDSImage encapsulates the asset, the flip flag and the rendering mode in one object.
Impact: Low
Parameter mapping (applies to all three types):
| Old parameter | New location |
|---|---|
icon: Image(…) |
image: OUDSImage(asset: Image(…)) |
flipIcon: true |
OUDSImage(asset:, flipped: true) — omit if false (default) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSCheckboxItem("Label", isOn: $isOn, icon: Image(decorative: "ic_heart"), isReversed: true)
OUDSCheckboxItem("Label", isOn: $isOn, icon: Image(decorative: "il_brand"), renderingMode: .original)
OUDSCheckboxItem("Label", isOn: $isOn, icon: Image(systemName: "figure.handball"),
flipIcon: layoutDirection == .rightToLeft)
OUDSCheckboxItem(LocalizedStringKey("agree_terms"), bundle: Bundle.module, isOn: $isOn,
icon: Image(decorative: "ic_heart"), renderingMode: .original)After (v2.3.0):
OUDSCheckboxItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "ic_heart")), isReversed: true)
OUDSCheckboxItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "il_brand"), renderingMode: .original))
OUDSCheckboxItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(systemName: "figure.handball"),
flipped: layoutDirection == .rightToLeft))
OUDSCheckboxItem(LocalizedStringKey("agree_terms"), bundle: Bundle.module, isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "ic_heart"), renderingMode: .original))Before (v2.2.0):
OUDSCheckboxItemIndeterminate("Label", selection: $state,
icon: Image(decorative: "ic_heart"), isReversed: true)
OUDSCheckboxItemIndeterminate("Label", selection: $state,
icon: Image(decorative: "il_brand"), renderingMode: .original)After (v2.3.0):
OUDSCheckboxItemIndeterminate("Label", selection: $state,
image: OUDSImage(asset: Image(decorative: "ic_heart")), isReversed: true)
OUDSCheckboxItemIndeterminate("Label", selection: $state,
image: OUDSImage(asset: Image(decorative: "il_brand"), renderingMode: .original))
// New in v2.3.0: LocalizedStringKey variant now available
OUDSCheckboxItemIndeterminate(LocalizedStringKey("select_all"), bundle: Bundle.module, selection: $state,
image: OUDSImage(asset: Image(decorative: "ic_heart")))Before (v2.2.0):
OUDSCheckboxPickerData(tag: "a", label: "Option A", icon: Image(systemName: "flame"))
OUDSCheckboxPickerData(tag: "b", label: "Option B",
icon: Image(decorative: "il_brand"), renderingMode: .original)After (v2.3.0):
OUDSCheckboxPickerData(tag: "a", label: "Option A",
image: OUDSImage(asset: Image(systemName: "flame")))
OUDSCheckboxPickerData(tag: "b", label: "Option B",
image: OUDSImage(asset: Image(decorative: "il_brand"), renderingMode: .original))Required Action:
- Replace every
icon: Image(…)parameter withimage: OUDSImage(asset: Image(…)) - Move
flipIcon: Bool→OUDSImage(asset:, flipped:)(omit iffalse) - Move
renderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Remove the now-unused
flipIconandrenderingModeparameters from the call site
Reason for Change: Grouping image-related parameters into one OUDSImage object reduces the number of parameters, makes the call site cleaner, and aligns OUDSCheckboxItem with the same pattern applied to OUDSButton and other components.
Initialisers of OUDSRadioItem and OUDSRadioPickerData that accepted a bare Image together with separate flipIcon and renderingMode parameters are deprecated.
Use the new initialisers that accept an OUDSImage? value instead.
Impact: Low
Parameter mapping (applies to both types):
| Old parameter | New location |
|---|---|
icon: Image(…) |
image: OUDSImage(asset: Image(…)) |
flipIcon: true |
OUDSImage(asset:, flipped: true) — omit if false (default) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSRadioItem("Label", isOn: $isOn, icon: Image(decorative: "ic_heart"), isReversed: true)
OUDSRadioItem("Label", isOn: $isOn, icon: Image(decorative: "il_brand"), renderingMode: .original)
OUDSRadioItem("Label", isOn: $isOn, icon: Image(systemName: "chevron.right"),
flipIcon: layoutDirection == .rightToLeft)
OUDSRadioItem(LocalizedStringKey("option_label"), bundle: Bundle.module, isOn: $isOn,
icon: Image(decorative: "ic_heart"), renderingMode: .original)After (v2.3.0):
OUDSRadioItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "ic_heart")), isReversed: true)
OUDSRadioItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "il_brand"), renderingMode: .original))
OUDSRadioItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(systemName: "chevron.right"),
flipped: layoutDirection == .rightToLeft))
OUDSRadioItem(LocalizedStringKey("option_label"), bundle: Bundle.module, isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "ic_heart"), renderingMode: .original))Before (v2.2.0):
OUDSRadioPickerData(tag: "a", label: "Option A", icon: Image(systemName: "flame"))
OUDSRadioPickerData(tag: "b", label: "Option B",
icon: Image(decorative: "il_brand"))After (v2.3.0):
OUDSRadioPickerData(tag: "a", label: "Option A",
image: OUDSImage(asset: Image(systemName: "flame")))
OUDSRadioPickerData(tag: "b", label: "Option B",
image: OUDSImage(asset: Image(decorative: "il_brand")))Required Action:
- Replace every
icon: Image(…)parameter withimage: OUDSImage(asset: Image(…)) - Move
flipIcon: Bool→OUDSImage(asset:, flipped:)(omit iffalse) - Move
renderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Remove the now-unused
flipIconandrenderingModeparameters from the call site
Reason for Change: Grouping image-related parameters into one OUDSImage object reduces the number of parameters, makes the call site cleaner, and aligns OUDSRadioItem with the same pattern applied to OUDSButton, OUDSCheckboxItem and other components.
Initialisers of OUDSSwitchItem that accepted a bare Image together with separate flipIcon and renderingMode parameters are deprecated.
Use the new initialisers that accept an OUDSImage? value instead.
Impact: Low
Parameter mapping:
| Old parameter | New location |
|---|---|
icon: Image(…) |
image: OUDSImage(asset: Image(…)) |
flipIcon: true |
OUDSImage(asset:, flipped: true) — omit if false (default) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSSwitchItem("Label", isOn: $isOn, icon: Image(decorative: "ic_heart"), isReversed: true)
OUDSSwitchItem("Label", isOn: $isOn, icon: Image(decorative: "il_brand"), renderingMode: .original)
OUDSSwitchItem("Label", isOn: $isOn,
icon: Image(systemName: "figure.handball"),
flipIcon: layoutDirection == .rightToLeft)
OUDSSwitchItem(LocalizedStringKey("wifi_setting"), bundle: Bundle.module, isOn: $isOn,
icon: Image(decorative: "ic_wifi"), renderingMode: .original)After (v2.3.0):
OUDSSwitchItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "ic_heart")), isReversed: true)
OUDSSwitchItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "il_brand"), renderingMode: .original))
OUDSSwitchItem("Label", isOn: $isOn,
image: OUDSImage(asset: Image(systemName: "figure.handball"),
flipped: layoutDirection == .rightToLeft))
OUDSSwitchItem(LocalizedStringKey("wifi_setting"), bundle: Bundle.module, isOn: $isOn,
image: OUDSImage(asset: Image(decorative: "ic_wifi"), renderingMode: .original))Required Action:
- Replace every
icon: Image(…)parameter withimage: OUDSImage(asset: Image(…)) - Move
flipIcon: Bool→OUDSImage(asset:, flipped:)(omit iffalse) - Move
renderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Remove the now-unused
flipIconandrenderingModeparameters from the call site
Reason for Change: Grouping image-related parameters into one OUDSImage object aligns OUDSSwitchItem with the same pattern applied to OUDSButton, OUDSCheckboxItem, OUDSRadioItem and other components.
Initialisers of OUDSFilterChip and OUDSSuggestionChip that accepted a bare Image together with a separate renderingMode parameter are deprecated.
Use the new initialisers that accept an OUDSImage value instead.
Impact: Low
Note: Unlike other components, chips do not support flipIcon — OUDSImage.flipped is not used here.
The accessibilityLabel parameter remains on the chip itself; do not set it on OUDSImage.
Parameter mapping:
| Old parameter | New location |
|---|---|
icon: Image(…) |
image: OUDSImage(asset: Image(…)) (FilterChip) / image: OUDSImage(asset: Image(…)) (SuggestionChip — see note) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Note on parameter label for both chip components:
OUDSFilterChipandOUDSSuggestionChipactive initialisers all useimage: OUDSImageas the parameter label. Both components renameicon:→image:to be consistent with all other OUDS components.
Before (v2.2.0):
OUDSSuggestionChip(icon: Image("ic_heart"), accessibilityLabel: "Heart") {}
OUDSSuggestionChip(icon: Image("ic_brand"), accessibilityLabel: "Brand", renderingMode: .original) {}
OUDSSuggestionChip(icon: Image("ic_heart"), text: "Heart") {}
OUDSSuggestionChip(icon: Image("ic_brand"), text: "Brand", renderingMode: .original) {}
OUDSFilterChip(icon: Image("ic_heart"), accessibilityLabel: "Heart", selected: true) {}
OUDSFilterChip(icon: Image("ic_brand"), accessibilityLabel: "Brand", renderingMode: .original) {}
OUDSFilterChip(icon: Image("ic_heart"), text: "Heart", selected: true) {}
OUDSFilterChip(icon: Image("ic_brand"), text: "Brand", renderingMode: .original) {}After (v2.3.0):
// OUDSSuggestionChip — image: OUDSImage (parameter label renamed from icon: to image: for all variants)
OUDSSuggestionChip(image: OUDSImage(asset: Image("ic_heart")), accessibilityLabel: "Heart") {}
OUDSSuggestionChip(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), accessibilityLabel: "Brand") {}
OUDSSuggestionChip(image: OUDSImage(asset: Image("ic_heart")), text: "Heart") {}
OUDSSuggestionChip(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), text: "Brand") {}
// OUDSFilterChip — image: OUDSImage (parameter label renamed from icon: to image:)
OUDSFilterChip(image: OUDSImage(asset: Image("ic_heart")), accessibilityLabel: "Heart", selected: true) {}
OUDSFilterChip(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), accessibilityLabel: "Brand") {}
OUDSFilterChip(image: OUDSImage(asset: Image("ic_heart")), text: "Heart", selected: true) {}
OUDSFilterChip(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), text: "Brand") {}Required Action:
- Replace
icon: Image(…)withOUDSImage(asset: Image(…)) - Move
renderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Remove the now-unused
renderingModeparameter from the chip call site - Rename the parameter label from
icon:toimage:(applies to bothOUDSFilterChipandOUDSSuggestionChip)
Reason for Change: Grouping image-related parameters into one OUDSImage object aligns the chip components with the same pattern applied to all other OUDS components. Both rename icon: to image: for consistency.
The @frozen enum OUDSChipPickerData.Layout has been enriched with two static factory methods accepting OUDSImage.
The existing cases .icon(icon:accessibilityLabel:renderingMode:) and .textAndIcon(text:icon:renderingMode:) remain available for backward compatibility.
Impact: Low — additive change, no breaking change.
Before (v2.2.0):
OUDSChipPickerData(tag: .x,
layout: .icon(icon: Image("ic_heart"), accessibilityLabel: "Heart"))
OUDSChipPickerData(tag: .y,
layout: .icon(icon: Image("ic_brand"), accessibilityLabel: "Brand",
renderingMode: .original))
OUDSChipPickerData(tag: .z,
layout: .textAndIcon("Label", icon: Image("ic_heart")))
OUDSChipPickerData(tag: .w,
layout: .textAndIcon("Brand", icon: Image("ic_brand"),
renderingMode: .original))After (v2.3.0) — preferred new form using static factories:
OUDSChipPickerData(tag: .x,
layout: .icon(OUDSImage(asset: Image("ic_heart")), accessibilityLabel: "Heart"))
OUDSChipPickerData(tag: .y,
layout: .icon(OUDSImage(asset: Image("ic_brand"), renderingMode: .original),
accessibilityLabel: "Brand"))
OUDSChipPickerData(tag: .z,
layout: .textAndIcon("Label", image: OUDSImage(asset: Image("ic_heart"))))
OUDSChipPickerData(tag: .w,
layout: .textAndIcon("Brand",
image: OUDSImage(asset: Image("ic_brand"),
renderingMode: .original)))Required Action:
- Migrate to the new static factory form to avoid passing
renderingModeseparately - The old case-based form continues to compile and remains valid
- Replace
icon: Image(…)→image: OUDSImage(asset: Image(…)) - Drop the
text:label: the static factory.textAndIcon(_ text: String, image:)has its first argument unlabelled (_). If your call site used the enum case with an explicittext:label (e.g..textAndIcon(text: "Label", icon: ...)), you must remove that label when switching to the factory (e.g..textAndIcon("Label", image: ...))
Reason for Change: @frozen is preserved for ABI stability. Static factories provide a cleaner API aligned with OUDSImage without requiring a breaking enum change.
The static factories OUDSTag.Status.neutral(icon:flipIcon:renderingMode:) and OUDSTag.Status.accent(icon:flipIcon:renderingMode:) are deprecated.
Use the new overloads that accept an OUDSImage value instead with parameter named image instead of icon.
Only the
.neutral(icon:)and.accent(icon:)factories are affected. All other factories (.positive,.negative,.warning,.info,.neutral(bullet:),.accent(bullet:)) are unchanged.
Impact: Low
Parameter mapping:
| Old parameter | New location |
|---|---|
icon: Image(…) |
OUDSImage(asset: Image(…)) |
flipIcon: true |
OUDSImage(asset:, flipped: true) — omit if false (default) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSTag(label: "Label", status: .neutral(icon: Image(decorative: "ic_heart")))
OUDSTag(label: "Label", status: .neutral(icon: Image(decorative: "ic_heart"), flipIcon: true))
OUDSTag(label: "Label", status: .neutral(icon: Image("ic_brand"), renderingMode: .original))
OUDSTag(label: "Label", status: .accent(icon: Image("ic_brand"), renderingMode: .original))After (v2.3.0):
OUDSTag(label: "Label", status: .neutral(image: OUDSImage(asset: Image(decorative: "ic_heart"))))
OUDSTag(label: "Label", status: .neutral(image: OUDSImage(asset: Image(decorative: "ic_heart"), flipped: true)))
OUDSTag(label: "Label", status: .neutral(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original)))
OUDSTag(label: "Label", status: .accent(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original)))Required Action:
- Replace
icon: Image(…)withimage: OUDSImage(asset: Image(…)) - Move
flipIcon: Bool→OUDSImage(asset:, flipped:)(omit iffalse) - Move
renderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Remove the now-unused
flipIconandrenderingModeparameters from the factory call
Reason for Change: Grouping image-related parameters into one OUDSImage object aligns OUDSTag.Status with the same pattern applied to all other OUDS components.
The two OUDSLink initialisers that accepted a bare Image together with a separate renderingMode parameter are deprecated.
Use the new overloads that accept an OUDSImage? value instead.
The navigation initialisers (
init(text:indicator:size:action:)andinit(_:tableName:bundle:indicator:size:action:)) are unchanged.OUDSLinkdoes not supportflipIconfor custom icons — only navigation indicators are automatically flipped for RTL.
Impact: Low
Parameter mapping:
| Old parameter | New location |
|---|---|
icon: Image(…) |
image: OUDSImage(asset: Image(…)) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSLink(text: "Learn more", icon: Image("ic_heart"), size: .default) {}
OUDSLink(text: "Brand", icon: Image("ic_brand"), renderingMode: .original, size: .default) {}
OUDSLink(LocalizedStringKey("learn_more"), bundle: Bundle.module,
icon: Image("ic_heart"), size: .default) {}
OUDSLink(LocalizedStringKey("brand"), bundle: Bundle.module,
icon: Image("ic_brand"), renderingMode: .original, size: .default) {}After (v2.3.0):
OUDSLink(text: "Learn more", image: OUDSImage(asset: Image("ic_heart")), size: .default) {}
OUDSLink(text: "Brand", image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), size: .default) {}
OUDSLink(LocalizedStringKey("learn_more"), bundle: Bundle.module,
image: OUDSImage(asset: Image("ic_heart")), size: .default) {}
OUDSLink(LocalizedStringKey("brand"), bundle: Bundle.module,
image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), size: .default) {}Required Action:
- Replace
icon: Image(…)withimage: OUDSImage(asset: Image(…))— both the parameter label (icon:→image:) and the type (Image→OUDSImage(asset:)) must change together - Move
renderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Remove the now-unused
renderingModeparameter from the call site
⚠ Two-step migration trap
A common mistake is to replace the
Image(…)value withOUDSImage(asset: Image(…))first (e.g. via a global find-and-replace or Xcode fix-it) while leaving theicon:label unchanged. This producesicon: OUDSImage(asset: Image(…))which still compiles — the deprecatedicon: Image?init accepts it becauseOUDSImageis notImage— but it is incorrect. See the section "Renamedimage:andleadingImage:parameters in active initialisers" further below.You must always rename
icon:→image:at the same time as you wrap the value inOUDSImage(asset:).
Reason for Change: Grouping image-related parameters into one OUDSImage object aligns OUDSLink with the same pattern applied to all other OUDS components.
Both OUDSTextInput and its nested TrailingAction struct have been updated to accept OUDSImage instead of separate Image, flipIcon/flipLeadingIcon, and renderingMode parameters.
Impact: Low
Parameter mapping:
| Old parameter | New location |
|---|---|
leadingIcon: Image(…) |
leadingImage: OUDSImage(asset: Image(…)) |
flipLeadingIcon: true |
OUDSImage(asset:, flipped: true) — omit if false (default) |
leadingIconRenderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSTextInput(label: "Email", text: $text, leadingIcon: Image(systemName: "envelope"))
OUDSTextInput(label: "Brand", text: $text, leadingIcon: Image("ic_brand"), leadingIconRenderingMode: .original)
OUDSTextInput(label: "Label", text: $text, leadingIcon: Image("ic"), flipLeadingIcon: true)
OUDSTextInput(label: "Search", text: $text, placeholder: "Type here...", leadingIcon: Image(systemName: "magnifyingglass"))After (v2.3.0):
OUDSTextInput(label: "Email", text: $text, leadingImage: OUDSImage(asset: Image(systemName: "envelope")))
OUDSTextInput(label: "Brand", text: $text, leadingImage: OUDSImage(asset: Image("ic_brand"), renderingMode: .original))
OUDSTextInput(label: "Label", text: $text, leadingImage: OUDSImage(asset: Image("ic"), flipped: true))
OUDSTextInput(label: "Search", text: $text, placeholder: "Type here...", leadingImage: OUDSImage(asset: Image(systemName: "magnifyingglass")))Parameter mapping:
| Old parameter | New location |
|---|---|
icon: Image(…) |
image: OUDSImage(asset: Image(…)) |
flipIcon: true |
OUDSImage(asset:, flipped: true) — omit if false (default) |
renderingMode: .original |
OUDSImage(asset:, renderingMode: .original) — omit if .template (default) |
Before (v2.2.0):
OUDSTextInput.TrailingAction(icon: Image("ic_cross"), actionHint: "Delete") { text = "" }
OUDSTextInput.TrailingAction(icon: Image("ic_brand"), actionHint: "Brand", renderingMode: .original) {}After (v2.3.0):
OUDSTextInput.TrailingAction(image: OUDSImage(asset: Image("ic_cross")), actionHint: "Delete") { text = "" }
OUDSTextInput.TrailingAction(image: OUDSImage(asset: Image("ic_brand"), renderingMode: .original), actionHint: "Brand") {}Required Action:
- Replace
leadingIcon: Image(…)withleadingImage: OUDSImage(asset: Image(…)) - Move
flipLeadingIcon:→OUDSImage(asset:, flipped:)(omit iffalse) - Move
leadingIconRenderingMode:→OUDSImage(asset:, renderingMode:)(omit if.template) - Replace
TrailingAction(icon: Image(…), …)withTrailingAction(image: OUDSImage(asset: Image(…)), …) - Move
flipIcon:andrenderingMode:inside theOUDSImageconstruction
⚠ Parameter order: in the active init,
leadingImage:comes afterplaceholder:,prefix:andsuffix:. The full order is:label:,text:,placeholder:,prefix:,suffix:,leadingImage:,trailingAction:, … A mechanical find-and-replace may insertleadingImage:immediately aftertext:, placing it beforeplaceholder:— this produces a compile error or incorrect argument order. Always check thatplaceholder:(andprefix:/suffix:if present) appears beforeleadingImage:in the call site.
Reason for Change: Grouping image-related parameters into one OUDSImage object aligns OUDSTextInput with the same pattern applied to all other OUDS components.
Following the introduction of OUDSImage-based initialisers in the same release, a secondary naming ambiguity was discovered: because the deprecated initialisers keep icon: Image? = nil and the new active initialisers had icon: OUDSImage? = nil, Swift could not always resolve which overload to call when nil was passed (or the parameter was omitted).
To resolve this, the active initialisers have been updated to use a distinct parameter label:
icon: OUDSImage?→image: OUDSImage?leadingIcon: OUDSImage?→leadingImage: OUDSImage?
The deprecated initialisers (icon: Image?, leadingIcon: Image?) are unchanged.
Impact: Low
Components affected:
| Component | Old parameter (active init) | New parameter (active init) |
|---|---|---|
OUDSCheckboxItem |
icon: OUDSImage? |
image: OUDSImage? |
OUDSCheckboxItemIndeterminate |
icon: OUDSImage? |
image: OUDSImage? |
OUDSCheckboxPickerData |
icon: OUDSImage? |
image: OUDSImage? |
OUDSRadioItem |
icon: OUDSImage? |
image: OUDSImage? |
OUDSRadioPickerData |
image: OUDSImage? |
unchanged (was already image:) — but still subject to residual ambiguity when called without an image argument (see warning below) |
OUDSSwitchItem |
icon: OUDSImage? |
image: OUDSImage? |
OUDSTextInput |
leadingIcon: OUDSImage? |
leadingImage: OUDSImage? |
OUDSLink |
icon: OUDSImage? |
image: OUDSImage? |
Before:
OUDSCheckboxItem("Label", isOn: $isOn, icon: OUDSImage(asset: Image("ic_heart")))
OUDSCheckboxItemIndeterminate("Label", selection: $state, icon: OUDSImage(asset: Image("ic_heart")))
OUDSCheckboxPickerData(tag: "a", label: "Option A", icon: OUDSImage(asset: Image(systemName: "flame")))
OUDSRadioItem("Label", isOn: $isOn, icon: OUDSImage(asset: Image("ic_heart")))
OUDSSwitchItem("Label", isOn: $isOn, icon: OUDSImage(asset: Image("ic_heart")))
OUDSTextInput(label: "Email", text: $text, leadingIcon: OUDSImage(asset: Image(systemName: "envelope")))
OUDSLink(text: "Learn more", icon: OUDSImage(asset: Image("ic_heart")), size: .default) {}After:
OUDSCheckboxItem("Label", isOn: $isOn, image: OUDSImage(asset: Image("ic_heart")))
OUDSCheckboxItemIndeterminate("Label", selection: $state, image: OUDSImage(asset: Image("ic_heart")))
OUDSCheckboxPickerData(tag: "a", label: "Option A", image: OUDSImage(asset: Image(systemName: "flame")))
OUDSRadioItem("Label", isOn: $isOn, image: OUDSImage(asset: Image("ic_heart")))
OUDSSwitchItem("Label", isOn: $isOn, image: OUDSImage(asset: Image("ic_heart")))
OUDSTextInput(label: "Email", text: $text, leadingImage: OUDSImage(asset: Image(systemName: "envelope")))
OUDSLink(text: "Learn more", image: OUDSImage(asset: Image("ic_heart")), size: .default) {}Required Action:
- In any call site using
icon: OUDSImage(…)on the above components, rename the label toimage: - In any call site using
leadingIcon: OUDSImage(…)onOUDSTextInput, rename toleadingImage: - Call sites using the deprecated
icon: Image(…)form are not affected — they continue to compile with a deprecation warning
Reason for Change: Swift cannot resolve nil between icon: Image? = nil (deprecated) and icon: OUDSImage? = nil (active) when the parameter is omitted, causing a compile-time ambiguity. Using distinct labels (image:, leadingImage:) removes the ambiguity without breaking the deprecated API.
⚠ Residual ambiguity warning
Even after this rename, a call site that omits the image parameter entirely may still trigger a Swift compile-time ambiguity, because both the deprecated init (e.g.
icon: Image? = nil) and the active init (e.g.image: OUDSImage? = nil) can be invoked with no image argument.Symptom:
error: ambiguous use of 'init(...)'Fix: Pass the image parameter explicitly as
nilto force Swift to select the active init:// ❌ may be ambiguous while deprecated inits coexist: OUDSCheckboxItem("Label", isOn: $isOn) OUDSRadioItem("Label", isOn: $isOn) OUDSRadioPickerData(tag: "a", label: "Option A") OUDSSwitchItem("Label", isOn: $isOn) OUDSLink(text: "Learn more", size: .default) {} OUDSTextInput(label: "Email", text: $text) // ✅ unambiguous — active init selected: // temporary — remove once deprecated inits are gone in v3 OUDSCheckboxItem("Label", isOn: $isOn, image: nil) OUDSRadioItem("Label", isOn: $isOn, image: nil) OUDSRadioPickerData(tag: "a", label: "Option A", image: nil) OUDSSwitchItem("Label", isOn: $isOn, image: nil) OUDSLink(text: "Learn more", image: nil, size: .default) {} OUDSTextInput(label: "Email", text: $text, leadingImage: nil)This workaround is only needed until the deprecated initialisers are removed in v3.
- Backward Compatibility: Yes — deprecated initialisers still compile with a warning
- v2.2.0 Support: None
The badge component has been refactored so as to improve maintainability and split responsabilities.
Now there are 3 components instead of 1.
- Use version 2.0 or older
The OUDSBadge component is deprecated. Use instead dedicated API.
Impact: Medium
Before (v2.0.0):
// Standard badge (i.e. empty badge)
OUDSBadge(accessibilityLabel: "New feature available", status: .accent, size: .small)
// Count badge
OUDSBadge(count: 9, accessibilityLabel: "9 new messages", status: .negative, size: .large)
// Icon badge
OUDSBadge(status: .info, accessibilityLabel: "Like", size: .medium)After (v2.1.0):
// Standard badge (i.e. empty badge)
OUDSBadgeStandard(accessibilityLabel: "New feature available", status: .accent, size: .small)
// Count badge
OUDSBadgeCount(9, accessibilityLabel: "9 new messages", status: .negative, size: .large)
// Icon badge
OUDSBadgeIcon(status: .info, accessibilityLabel: "Like", size: .medium)Required Action:
- Replace the
OUDSBadgecalls byOUDSBadgeStandard,OUDSBadgeCountorOUDSBadgeIcon
Reason for Change: Now in Figma these components have their own versions, configurations and should be split.
Tokens libraries have been updated, with some raw, semantic and components tokens removed or renamed.
API for action type of toolbar item has been enriched.
- Use version 1.4 or older
Some component tokens (badge, bar) and semantic tokens (colors, elevations, size) have been renamed.
Impact: High
For colors semantic tokens, "Modal" is now "ModalSheet":
| Old name | New name |
|---|---|
repositorySecondaryHigher |
repositorySecondaryHigherHigh |
overlayModalLight |
overlayModalSheetLight |
overlayModalDark |
overlayModalSheetDark |
overlayModal |
overlayModalSheet |
For elevation semantic tokens, "Default" is now "Elevated":
| Old name | New name |
|---|---|
xDefault |
xElevated |
yDefault |
yElevated |
blurDefault |
blurElevated |
spreadDefault |
spreadElevated |
colorDefaultLight |
colorElevatedLight |
colorDefaultDark |
colorElevatedDark |
For size semantic tokens, the word "Type" has been removed from the name:
| Old name | New name |
|---|---|
maxWidthTypeDisplayLargeMobile |
maxWidthDisplayLargeMobile |
maxWidthTypeDisplayLargeTablet |
maxWidthDisplayLargeTablet |
maxWidthTypeDisplayMediumMobile |
maxWidthDisplayMediumMobile |
maxWidthTypeDisplayMediumTablet |
maxWidthDisplayMediumTablet |
maxWidthTypeDisplaySmallMobile |
maxWidthDisplaySmallMobile |
maxWidthTypeDisplaySmallTablet |
maxWidthDisplaySmallTablet |
maxWidthTypeHeadingXlargeMobile |
maxWidthHeadingXlargeMobile |
maxWidthTypeHeadingXlargeTablet |
maxWidthHeadingXlargeTablet |
maxWidthTypeHeadingLargeMobile |
maxWidthHeadingLargeMobile |
maxWidthTypeHeadingLargeTablet |
maxWidthHeadingLargeTablet |
maxWidthTypeHeadingMediumMobile |
maxWidthHeadingMediumMobile |
maxWidthTypeHeadingMediumTablet |
maxWidthHeadingMediumTablet |
maxWidthTypeHeadingSmallMobile |
maxWidthHeadingSmallMobile |
maxWidthTypeHeadingSmallTablet |
maxWidthHeadingSmallTablet |
maxWidthTypeBodyLargeMobile |
maxWidthBodyLargeMobile |
maxWidthTypeBodyLargeTablet |
maxWidthBodyLargeTablet |
maxWidthTypeBodyMediumMobile |
maxWidthBodyMediumMobile |
maxWidthTypeBodyMediumTablet |
maxWidthBodyMediumTablet |
maxWidthTypeBodySmallMobile |
maxWidthBodySmallMobile |
maxWidthTypeBodySmallTablet |
maxWidthBodySmallTablet |
maxWidthTypeLabelXlargeMobile |
maxWidthLabelXlargeMobile |
maxWidthTypeLabelXlargeTablet |
maxWidthLabelXlargeTablet |
maxWidthTypeLabelLargeMobile |
maxWidthabelLargeMobile |
maxWidthTypeLabelLargeTablet |
maxWidthLabelLargeTablet |
maxWidthTypeLabelMediumMobile |
maxWidthLabelMediumMobile |
maxWidthTypeLabelMediumTablet |
maxWidthLabelMediumTablet |
maxWidthTypeLabelSmallMobile |
maxWidthLabelSmallMobile |
maxWidthTypeLabelSmallTablet |
maxWidthLabelSmallTablet |
For badge component tokens:
| Old name | New name |
|---|---|
spaceInset |
spaceInsetMediumLarge |
For bar component tokens, "ActiveIndicator" is now "CurrentIndicator":
| Old name | New name |
|---|---|
colorActiveIndicatorCustomSelectedEnabled |
colorCurrentIndicatorCustomSelectedEnabled |
colorActiveIndicatorCustomSelectedHover |
colorCurrentIndicatorCustomSelectedHover |
colorActiveIndicatorCustomSelectedPressed |
colorCurrentIndicatorCustomSelectedPressed |
colorActiveIndicatorCustomSelectedFocus |
colorCurrentIndicatorCustomSelectedFocus |
opacityActiveIndicatorCustom |
opacityCurrentIndicatorCustom |
borderRadiusActiveIndicatorCustomTop |
borderRadiusCurrentIndicatorCustomTop |
borderRadiusActiveIndicatorCustomBottom |
borderRadiusCurrentIndicatorCustomBottom |
sizeWidthActiveIndicatorCustomTop |
sizeWidthCurrentIndicatorCustomTop |
sizeWidthActiveIndicatorCustomBottom |
sizeWidthCurrentIndicatorCustomBottom |
sizeWidthActiveIndicatorCustomBottom |
sizeWidthCurrentIndicatorCustomBottom |
Required Action:
- Use the new names as explained above
Reason for Change: Tokens libraries have been updated in design side
Some component tokens (control item, checkbox, radio), semantic tokens (color) and raw tokens (effect, colors) have been removed. All Sosh raw tokens have been changed.
Impact: High
Required Action:
- Remove effect raw token
blur160 - Remove color raw token
opacityGrayLight80800 - Remove color semantic tokens
actionAccentLight,actionAccentDarkandactionAccent; use if relevantcolorAccentbar component tokens - Remove radio component token
sizeIndicator; usetheme.controlItem.sizeControlIndicatorinstead (renamedtheme.listItem.sizeControlIndicatorsince v3.0.0) - Remove checkbox component token
sizeIndicator; usetheme.controlItem.sizeControlIndicatorinstead (renamedtheme.listItem.sizeControlIndicatorsince v3.0.0) - Remove following control item component tokens:
sizeMaxHeihtAssetsContainer,sizeLoader,sizeErrorIcon,borderRadiusItemOnly,colorBgHover*,colorBgFocus*,colorBgPressed*,colorBgLoading*,colorContentLoader*,spacePaddingInlineErrorIcon* - Remove use of all raw tokens for Sosh and use new ones
Reason for Change: Tokens libraries have been updated in design side
The tokens provider for charts colors, previously named charts, is now named colorsCharts.
Impact: High
Required Action:
- Rename any use of
theme.chartstotheme.colorsCharts
Reason for Change: Bring more clarity in naming
The OUDSToolBarItem.ActionType enum has been updated for the icon case.
A new parameter named badgeType appeared.
Impact: Low
Required Action:
- If you make pattern matching on this case, add a new slot for this parameter.
Reason for Change: Manage badge for items with icons in toolbars
- Backward Compatibility: No
- v1.4.0 Support: No
Some public View extension methods prefixed with ouds have been renamed to remove the prefix, aligning with the naming style of typography helpers.
The old methods are deprecated and will be removed in a future major version.
The tab bar component has a new initializer with a binding for the selected tab, deprecating the older one.
- Use version 1.3 or older
The following View extension methods have been deprecated in favor of unprefixed versions.
The old methods still compile with a deprecation warning.
Impact: Low
| Deprecated | Replacement |
|---|---|
.oudsForegroundStyle(_:) |
.foregroundStyle(_:) |
.oudsForegroundColor(_:) |
.foregroundColor(_:) |
.oudsBackground(_:) |
.background(_:) |
.oudsAccentColor(_:) |
.accentColor(_:) |
.oudsShadow(_:) |
.shadow(_:) |
.oudsBorder(style:width:radius:color:) |
.border(style:width:radius:color:) |
.oudsColoredSurface(_:) |
.coloredSurface(_:) |
.oudsGridMargin(_:) |
.gridMargin(_:) |
.oudsRequestAccessibleFocus(_:) |
.requestAccessibleFocus(_:) |
.oudsRequestAccessibleFocus(_:for:) |
.requestAccessibleFocus(_:for:) |
.oudsHorizontalDivider(dividerColor:) |
.horizontal(color:) |
.oudsVerticalDivider(color:) |
.vertical(color:) |
Before (v1.3.x):
Text("Hello")
.oudsForegroundColor(theme.colors.contentDefault)
.oudsBackground(theme.colors.bgPrimary)
// Etc.
SomeView()
.oudsBorder(style: theme.borders.styleDefault,
width: theme.borders.widthThin,
radius: theme.borders.radiusMedium,
color: theme.colors.borderDefault)
.oudsShadow(theme.elevations.emphasized)
// Etc.After (v1.4.0):
Text("Hello")
.foregroundColor(theme.colors.contentDefault)
.background(theme.colors.bgPrimary)
SomeView()
.border(style: theme.borders.styleDefault,
width: theme.borders.widthThin,
radius: theme.borders.radiusMedium,
color: theme.colors.borderDefault)
.shadow(theme.elevations.emphasized)Required Action:
- Replace deprecated
ouds-prefixed calls with their unprefixed counterparts
Reason for Change: User feedback indicated the ouds prefix on methods was redundant and verbose given that parameter types are strongly typed OUDS tokens which prevent any ambiguity with native SwiftUI overloads.
The OUDSTabBar(selected:count:content:) initializer that accepted a plain Int for the initially selected tab is now deprecated.
A new OUDSTabBar(selectedTab:count:content:) initializer replaces it, accepting a Binding<Int> that is updated whenever the user taps a tab — keeping the parent view in sync with the tab bar selection without any extra code.
Impact: Low
Before (v1.3.x):
// The initial tab is fixed at 0; user interactions are not propagated back.
OUDSTabBar(selected: 0, count: 3) {
SomeView().tabItem { Label("Home", image: "ic_home") }.tag(0)
OtherView().tabItem { Label("Search", image: "ic_search") }.tag(1)
LastView().tabItem { Label("Profile", image: "ic_profile") }.tag(2)
}After (v1.4.0):
// Declare a @State to hold the selected tab index.
@State private var selectedTab = 0
// Pass it as a Binding: the tab bar updates selectedTab when the user taps a tab,
// and programmatically changing selectedTab switches the displayed tab.
OUDSTabBar(selectedTab: $selectedTab, count: 3) {
SomeView().tabItem { Label("Home", image: "ic_home") }.tag(0)
OtherView().tabItem { Label("Search", image: "ic_search") }.tag(1)
LastView().tabItem { Label("Profile", image: "ic_profile") }.tag(2)
}Required Action:
- Replace
OUDSTabBar(selected:count:content:)calls withOUDSTabBar(selectedTab:count:content:) - Declare a
@State private var selectedTab: Int(or use an existing state/binding) and pass it as$selectedTab - Remove any manual workaround you may have used to track or drive tab selection from outside the component
Reason for Change: The original initializer only accepted a one-time initial value (Int) with no way to observe or control the selected tab from outside the component.
The new initializer uses a Binding<Int> so the selected tab is always in sync with the parent view: user taps update the binding, and external state changes switch the visible tab.
- Backward Compatibility: Yes
- v1.3.0 Support: Until release of next minor version
The design team confirms that any logic related to grids, gutters and spacings are related to the horizontal size class.
Thus existence of oudsVerticalSizeClass, used nowhere, is a non-sense; this property has been removed.
- Use version 1.2 or older
Impact: Low
Before (v1.x):
@Environment(\.oudsVerticalSizeClass) var sizeClass // Or any other name for propertyAfter (v1.3.0):
// Property removedRequired Action:
- Remove us of
oudsVerticalSizeClassenvironment object
Reason for Change: Not used, not relevant, must not be considered even if design side
Note: This property comes back with v1.4.0 as some users still used it
Impact: Low
Before (v1.x):
var someIconForBulletList: OUDSBulletList.UnorderedIcon {
.free(someImage)
}After (v1.3.0):
var someIconForBulletList: OUDSBulletList.UnorderedAsset {
.icon(someImage)
}Required Action:
- Rename any use of
OUDSBulletList.UnorderedIcontoOUDSBulletList.UnorderedAsset - Case
.freemust be replaced by.icon
Reason for Change: "asset" word has a better meaning than "icon", and is aligned with Android OUDS library API
- Backward Compatibility: No
- v1.2.0 Support: Until release of next minor version
The Orange Business Tools theme has been renamed by the design team to Orange Compact Thus the theme name is more accurate and does not have ambiguity anymore with Orange Business company.
- Use version 1.x
Impact: High
Before (v1.x):
import OUDSThemeOrangeBusinessToolsAfter (v1.2.0):
import OUDSThemeOrangeCompactRequired Action:
- If you use individual imports, rename the name of the Swift Package product from
OUDSThemeOrangeCompacttoOUDSThemeOrangeCompact
Reason for Change: Use more accurate name for the theme
Impact: High
Before (v1.x):
OrangeBusinessToolsTheme()After (v1.2.0):
OrangeCompactTheme()Required Action:
- If you instanciated
OrangeCompactThemeobject, use insteadOrangeCompactThemename
Reason for Change: Use more accurate name for the theme
Impact: High
Required Action:
- Wherever you use the name "OrangeBusinessTools" (whatever the case or the style), in documentation, tests or source code, replace instead by "OrangeCompact"
Reason for Change: Use more accurate name for the theme
- Backward Compatibility: No
- v1.1.0 Support: Until release of next minor version
Some "multiple" object tokens have been renamed from plural form to singular form. Component tokens of button for borders have been shortened.
- Use version 1.0.0
Impact: High
Before (v1.0.0):
// Old namings of objects
MultipleElevationCompositeRawTokens
MultipleColorSemanticTokens
MultipleFontCompositeSemanticTokens
MultipleFontLetterSpacingSemanticTokens
MultipleFontLineHeightSemanticTokens
MultipleFontSizeSemanticTokens
MultipleSizeSemanticTokens
MultipleSpaceSemanticTokensAfter (v1.1.0):
// Use new namings without final 's'
MultipleElevationCompositeRawToken
MultipleColorSemanticToken
MultipleFontCompositeSemanticToken
MultipleFontLetterSpacingSemanticToken
MultipleFontLineHeightSemanticToken
MultipleFontSizeSemanticToken
MultipleSizeSemanticToken
MultipleSpaceSemanticTokenRequired Action:
- Step 1: Rename all
MultipleColorSemanticTokensuses toMultipleColorSemanticToken - Step 2: Rename all
MultipleElevationCompositeRawTokensuses toMultipleElevationCompositeRawToken - Step 3: Rename all
MultipleFontCompositeSemanticTokensuses toMultipleFontCompositeSemanticToken - Step 4: Rename all
MultipleFontLetterSpacingSemanticTokensuses toMultipleFontLetterSpacingSemanticToken - Step 5: Rename all
MultipleFontLineHeightSemanticTokensuses toMultipleFontLineHeightSemanticToken - Step 6: Rename all
MultipleFontSizeSemanticTokensuses toMultipleFontSizeSemanticToken - Step 7: Rename all
MultipleSizeSemanticTokensuses toMultipleSizeSemanticToken - Step 8: Rename all
MultipleSpaceSemanticTokensuses toMultipleSpaceSemanticToken
Reason for Change: Bring consistency between objects exposed by the API; plural form is not correct
Impact: High
Before (v1.0.0):
// Old namings of objects
buttonBorderRadiusDefault
buttonBorderRadiusRounded
buttonBorderRadiusSocial
buttonBorderWidthDefault
buttonBorderWidthDefaultInteraction
buttonBorderWidthDefaultInteractionMonoAfter (v1.1.0):
// Use new namings without 'button' prefix
borderRadiusDefault
borderRadiusRounded
borderRadiusSocial
borderWidthDefault
borderWidthDefaultInteraction
borderWidthDefaultInteractionMonoRequired Action:
- Step 1: Rename all
buttonBorderRadiusDefaultuses toborderRadiusDefault - Step 2: Rename all
buttonBorderRadiusRoundeduses toborderRadiusRounded - Step 3: Rename all
buttonBorderRadiusSocialuses toborderRadiusSocial - Step 4: Rename all
buttonBorderWidthDefaultuses toborderWidthDefault - Step 5: Rename all
buttonBorderWidthDefaultInteractionuses tobuttonBorderWidthDefaultInteraction - Step 6: Rename all
buttonBorderWidthDefaultInteractionMonouses toborderWidthDefaultInteractionMono
Reason for Change: Tokens names must be shortened and must not repeat the component name
- Backward Compatibility: No
- v1.0.0 Support: Until release of version v1.1.0
If you encounter issues: