One value type — AIAutocompleteAppearance — holds every visual token: fonts, colors, radii, spacing, animation. Defaults follow the stock design and adapt to light/dark automatically.
Applying an appearance
Build a value, override what you need, and apply it — the environment modifier in SwiftUI, the appearance property in UIKit.
import AIAutocompleteUIKitvar brand = AIAutocompleteAppearance()brand.font = .systemFont(ofSize: 18)brand.inputCornerRadius = 12brand.pillBorderStyle = .dashedbrand.pillBorderColor = .systemIndigobrand.columns = 2// SwiftUI — applies to every AIAutocomplete / AIAutocompleteDropdown below itAIAutocomplete(configuration: config).aiAutocompleteAppearance(brand)// UIKit — assign to the view; restyles in placeautocompleteView.appearance = brand
Light and dark mode
Every default color is a dynamic UIColor that resolves against the system appearance — light and dark both look right with no work. Custom colors can do the same: pass a UIColor closure keyed on userInterfaceStyle, or an asset-catalog color.
var appearance = AIAutocompleteAppearance()appearance.inputBackgroundColor = UIColor { traits intraits.userInterfaceStyle == .dark ? .black : .white}
Typography
| Prop | Type | Default | Description |
|---|---|---|---|
font | UIFont | 16pt system, Dynamic Type | Base font for input text and completed params; pills and options fall back to it. Scales with Dynamic Type. |
pillFont | UIFont? | nil (falls back to font) | Pill chip font. |
optionFont | UIFont? | 14pt system, Dynamic Type | Dropdown option font. |
optionSelectedFontWeight | UIFont.Weight | .semibold | Font weight of the highlighted / selected option's text; the regular face is restored on deselect. Applied through the descriptor, so a custom optionFont keeps its family. |
maxInputLines | Int? | 5 | Lines the input grows to before scrolling internally. nil grows without bound. |
lineSpacing | CGFloat | 9 | Extra spacing between wrapped input lines, in points. |
maximumContentSizeCategory | UIContentSizeCategory | .accessibilityExtraLarge | Dynamic Type cap for option text — scales up to this category and no further. |
Colors
All UIColor. Defaults are dynamic light/dark pairs mirroring the web SDK's stock palette.
| Prop | Type | Description |
|---|---|---|
textColor | UIColor | Free-typed text and completed params in the input. |
placeholderColor | UIColor | Placeholder text and unfilled placeholder pills. |
caretColor | UIColor | The text caret. |
pillBackgroundColor / pillTextColor | UIColor | Pill fill and label text. The stock fill is transparent and the stock border style is .none, so pills read as plain labels. |
pillBorderColor | UIColor | Outline color of unfilled pills. |
completedParamBackgroundColor / completedParamActiveBackgroundColor | UIColor | Completed-param chip fill — resting, and while the param is re-edited. Used when completedParamEmphasis contains .highlight. |
completedParamTextColor | UIColor? | Completed-param chip text color. Defaults to the solid fill's inverse ink (white on light, black on dark); nil follows textColor instead. |
completedParamShimmerColor | UIColor? | Band tint of the promotion glint swept across a just-completed param. nil (the default) follows the chip fill, so the glint reads on the chip's ink and stays invisible over the fill. |
inputBackgroundColor / inputBorderColor | UIColor | Input surface fill and border. |
dropdownBackgroundColor / dropdownBorderColor | UIColor | Dropdown surface fill and border (solid mode). |
optionTextColor / optionSelectedTextColor | UIColor | Option text, normal and highlighted. |
optionHighlightBackgroundColor | UIColor | Highlighted option's background fill. |
shimmerColor | UIColor | Loading shimmer / skeleton base. |
submitButtonBackgroundColor / submitButtonForegroundColor | UIColor | Built-in submit button fill and glyph. Ignored with a custom button. |
Pills and completed params
Unfilled suggestion pills render as hollow small-caps chips — no fill, with a solid outline on the pill being filled (queued pills wait borderless; outline them all via showsInactivePillBorders). Once a param is filled it renders as a solid high-contrast capsule — black on light, white on dark, with inverse ink — that lifts toward the surface while it's being re-edited. Every look is tokenized: restyle the outline, pick a different emphasis, or turn the chips off entirely.
var appearance = AIAutocompleteAppearance()// Unfilled pills: a solid outline on the ACTIVE pill by default —// restyle it, outline every pill, or drop outlines entirelyappearance.pillBorderStyle = .dashed // or .solid (default) / .noneappearance.pillBorderColor = .systemIndigoappearance.showsInactivePillBorders = true // outline the queued pills too// Completed params: a solid black/white capsule by default (.highlight)appearance.completedParamEmphasis = [.highlight, .bold] // fill + semiboldappearance.completedParamEmphasis = .bold // semibold onlyappearance.completedParamEmphasis = [] // plain text
| Prop | Type | Default | Description |
|---|---|---|---|
pillBorderStyle | .none | .dashed | .solid | .solid | Pill outline: .none (plain label text), .dashed, or .solid — inline and in the dropdown pill bar. |
pillBorderWidth | CGFloat | 1 | Width of the pill outline. |
showsInactivePillBorders | Bool | false | false reserves the pill outline for the active param alone, so the queue reads as one outlined slot being filled. Inert when pillBorderStyle is .none. |
completedParamEmphasis | CompletedParamEmphasis | .highlight | .highlight draws the chip fill (with horizontal room reserved around each param), .bold sets semibold text. Combine both, or pass [] for plain text. |
Layout
| Prop | Type | Default | Description |
|---|---|---|---|
inputCornerRadius | CGFloat | 12 | Input surface radius. |
dropdownCornerRadius | CGFloat | 12 | Dropdown card radius. |
pillCornerRadius | CGFloat | 6 | Pill chip radius, clamped to half the chip height — a rounded rectangle by default. |
optionCornerRadius | CGFloat | 4 | Highlighted option fill (and streak) radius. |
inputBorderWidth / dropdownBorderWidth | CGFloat | 0.8 / 0.2 | Hairline borders around the input and dropdown. |
inputInsets | UIEdgeInsets | 10pt all sides | Padding between the input surface's edge and its content. |
dropdownGap | CGFloat | 6 | Vertical gap between input and dropdown. |
dropdownMaxHeight | CGFloat? | nil | Optional hard cap on the option grid's height, in points. Applied together with maxVisibleOptionRows and the keyboard bound — the smallest wins. |
maxVisibleOptionRows | Int? | 5 | Option rows shown before the grid scrolls. Expressed in rows, so the cap tracks the option font and Dynamic Type. nil removes the cap. |
optionLeadingInset | CGFloat | 5 | Extra leading inset for option text. The default lines options up with the input's text; 0 lines them up with the dropdown pill bar instead. |
optionVerticalPadding | CGFloat | 9.75 | Vertical padding around each option's text — the text-to-text gap between adjacent options is twice this. Options wrap to as many lines as they need; each row is exactly tall enough for its option. |
completedParamHorizontalPadding / completedParamVerticalPadding | CGFloat | 7 / 2.5 | Chip capsule padding around the param's text, per side. Vertical expands into the line gap — keep it at or below half of lineSpacing, or wrapped chips overlap the line above. |
dropdownShadow | Shadow? | .default | Drop shadow cast by the dropdown card — the stock .default is a soft shadow (offset y 8pt, blur radius 6pt). nil draws no shadow. Solid mode only; glass supplies its own depth. |
columns | Int | 1 | Columns in the option grid. |
submitButtonSize / submitButtonSpacing | CGFloat | 28 / 12 | Built-in submit button diameter and its gap from the text. |
Animation, haptics, surfaces
| Prop | Type | Default | Description |
|---|---|---|---|
animations | Bool | true | Master switch for the selection streak and shimmer. The system Reduce Motion setting always wins. |
haptics | Bool | true | Light haptic tick on param promotion. Independent of animations. |
dropdownSurface | .solid | .glass | .solid | Solid fill, or system glass. |
showBrandFooter | Bool | false | Whether the AI Autocomplete brand row renders at the dropdown's far edge. Hiding it also releases the scroll band reserved beneath it. |