Styling Control
Override styles with custom config json
Component Targeting
Customize specific components and pages
Advanced Theming
Complex color schemes and typography
UIKit Framework
Still within the UIKit ecosystem
When to Choose Component Styling
Component Styling is ideal when you need: ✅ Custom brand experiences - Basic colors and fonts✅ Granular control - Target specific components or pages
✅ Advanced theming - Complex color schemes and typography
✅ Framework benefits - Want to stay within UIKit’s ecosystem ❌ Simple branding -
Dynamic UI is easier for basic needs❌ Complex layouts -
Fork & Extend offers more freedom❌ Custom components - Need source code access for new components
Configuration Model
Component Styling uses a single
config.json surface for cross-platform overrides. It layers on top of default UIKit tokens (and Dynamic UI if present) using a path pattern: page_id/component_id/element_id with wildcards (*).Path Pattern & Levels
Supported Theme Tokens
Every key below may be set undertheme.light and theme.dark. Any key you omit falls back to the
default shown. Defaults are identical across platforms — they ship in the same config template.
Where each token applies. Thirteen tokens resolve across every UIKit feature:
primary_color, secondary_color, base_color, base_shade1_color through base_shade4_color,
base_inverse_color, alert_color, background_color, background_shade1_color,
highlight_color, and toast_background_color.The rest belong to a revised color set that currently drives chat components only. Setting them
has no effect on other features yet — those continue to resolve through the thirteen above, and
adopt the expanded set in a later release.Core
Brand shades
Variants ofprimary_color and secondary_color used for hover, pressed, disabled and emphasis states.
Neutral greys
A light-to-dark ramp used for borders, dividers, skeletons and muted text. These are mode-independent by default — set them per mode if your dark theme needs a different ramp.Destructive
Escalating scale for destructive actions and error states.Overlays
Semi-transparent fills for scrims, media overlays and pressed states. Values carry an alpha channel (#RRGGBBAA).
Fixed and feature colors
Minimal Config Skeleton
Theme Application & Preferred Mode
Set the app’s theme resolution strategy withpreferred_theme:
Targeting Examples
Page-Level
Page-Level
Override a whole screen. Great for hero / camera / immersive surfaces.
Component-Level
Component-Level
Adjust reusable functional blocks everywhere.
Element-Level
Element-Level
Fine-grain tweak for single control.
Reference: Allowed IDs
- Pages
- Components
- Elements (Partial)
Exclusions
Remove (hide) specific elements by adding their path toexcludes:
Precedence & Conflict Resolution
Custom Config File (iOS)
iOS only. On Android, Flutter, and React Native, the config JSON is loaded differently per platform. On iOS, use
setConfigFile to load a local JSON file from your app bundle at initialisation time.config.json. setConfigFile lets you supply a replacement from your own app bundle — useful for per-environment configs, white-label builds, or shipping your own defaults without modifying UIKit source.
Implementation
Custom Asset Bundle (iOS)
iOS only. On Android, Flutter, and React Native, image overrides are handled through the
config.json element keys (e.g. “close_icon”: “close.png”).config.json, iOS lets you supply a custom Bundle containing your own images. UIKit uses it as a fallback — your assets are loaded only for image names that do not exist in UIKit’s own bundle.
How It Works
1
UIKit bundle checked first
If the image name exists in UIKit’s own bundle, that version is always used.
2
Custom bundle as fallback
Only when the name is not found in UIKit’s bundle does it fall through to your registered custom bundle.
3
Not found anywhere
If the image is absent from both bundles, UIKit renders a placeholder rather than crashing.
Implementation
- Basic Setup
- With Config File
- Dedicated Bundle
Call
setCustomAssetBundle once during app initialisation, after AmityUIKit4Manager.setup(client:).Troubleshooting
Image is not showing
Image is not showing
Verify the asset is included in the bundle you registered:Check that the file name, extension, and capitalisation match exactly what is referenced in
config.json.UIKit is displaying its default icon instead of mine
UIKit is displaying its default icon instead of mine
An asset with the same name in UIKit’s bundle always wins. Rename your asset uniquely and update the matching
config.json icon key to point to the new name.Works in Debug but missing in Release
Works in Debug but missing in Release
Ensure the image file appears under Copy Bundle Resources in Build Phases. Loose PNG/PDF files (not inside an
.xcassets catalog) must be added manually.Best Practices
Token First
Change global tokens before per-element overrides.
Progressive Specificity
Escalate from page → component → element only when needed.
Consistency
Reuse colors; avoid random hex proliferation.
Auditable Changes
Document rationale in PR descriptions.
Dark Mode QA
Visually inspect every high-contrast surface.
Minimal Exclusions
Prefer styling adjustments over removal.
Overriding Navigation Behaviour
Navigation can be customized without forking by overriding the provided Behaviour classes. UIKit isolates navigation & event hooks into behaviour objects per page/component so you can inject custom flows (e.g., presenting a different creation screen, analytics, guards) while keeping styling overrides separate.
Behaviour Architecture
- Each major screen/component exposes a
Behaviour(iOS) /Behavior(Android) class with overridable navigation methods. - A top-level
AmityUIKit4Manager.behaviour(iOS) /AmityUIKit4Manager.behavior(Android) aggregates these instances. - Replace only the concrete behaviour you need; leave others at default.
Override Example
Advanced iOS Navigation (Swipe Back & SwiftUI Hosting)
UIKit v4 pages are predominantly SwiftUI, embedded inUINavigationController via helper controllers:
To preserve the interactive swipe‑to‑go‑back gesture while customizing appearance, UIKit globally overrides navigation gesture delegate methods. You can supply your own gesture behaviour logic via
AmitySwipeToBackGestureBehavior.
Keep gesture logic lightweight—long operations here can block UI responsiveness.
When to Escalate
If navigation changes require altering internal view composition (e.g., embedding a new container architecture), consider moving to Fork & Extend. Simple route substitutions, analytics, permission gates, and gesture tweaks belong here.Next Steps
Dynamic UI
Remote token updates
Advanced Customization
Fork & extend source