Themes#
The appearance of the SDK can be customized by setting the theme property. This requires a StorytellerTheme configurable object.
let myTheme = StorytellerTheme()
Storyteller.shared.theme = myTheme
This object is used as the global theme for every StorytellerListView included in your application. We, therefore, recommend setting it as early as possible in the application's lifecycle (for example, in the didFinishLaunchingWithOptions callback in the AppDelegate).
It is also possible to apply a specific theme to a specific StorytellerListView instance. For example:
let myRowTheme = StorytellerTheme()
storytellerRowView.theme = myRowTheme
For more information on setting a theme on an individual list, see StorytellerListView.
Configuring a StorytellerTheme#
A StorytellerTheme consists of the following properties:
light- sets theThemeto apply for light mode.dark- sets theThemeto apply for dark mode.
Which property is used depends on the uiStyle property of the StorytellerListView.
Creating Themes#
The Theme object contains all of the properties which can be customized in the SDK.
Some properties take their default value from others. For example, setting the primaryColor to #FF0000 will also result in the New Indicator for Rectangular Tiles being colored red. Such properties are indicated in the table below.
Note that theme properties may be used for other situations in future.
Colors#
The colors property on theme is used to establish a set of base colors for the SDK to use.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
primary |
#1C62EB |
UIColor |
The default accent color used throughout the UI. In general, this should be the primary brand color. |
success |
#3BB327 |
UIColor |
Used to indicate correct answers in Quizzes. |
alert |
#E21219 |
UIColor |
Used to indicate incorrect answers in Quizzes. |
white.primary |
#FFFFFF |
UIColor |
Used for white text |
white.secondary |
white.primary at 85% opacity |
UIColor |
Used for light text |
white.tertiary |
white.primary at 70% opacity |
UIColor |
Used for gray text |
black.primary |
#000000 |
UIColor |
Used for black text |
black.secondary |
black.primary at 85% opacity |
UIColor |
Used for light black text |
black.tertiary |
black.primary at 70% opacity |
UIColor |
Used for gray text |
Font#
Use the font property to set a custom font for use throughout the UI
To set this create an instance of a class which implements the StorytellerFontProvider protocol and provides an instance of UIFont for the various weights. For example:
private var customFont: StorytellerFontProvider {
class CustomFont: StorytellerFontProvider {
override func font(weight: StorytellerFontWeight, size: CGFloat) -> UIFont? {
switch weight {
case .regular, .medium:
return UIFont(name: "MyCustomFont", size: size)
case .semibold, .bold, .heavy, .black:
return UIFont(name: "MyCustomFontBold", size: size)
default:
return UIFont(name: "MyCustomFont", size: size)
}
}
}
return CustomFont()
}
theme.light.font = customFont
Primitives#
The primitives object contains base values which are used throughout the UI.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
cornerRadius |
8 |
CGFloat |
The corner radius used for rectangular tiles, buttons and poll/quiz answers |
Lists#
The lists customizes properties of the various list types available from the SDK.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
backgroundColor |
colors.white.primary |
UIColor |
Required for outline on Live chip and fade to the side of the row on the Web SDK |
enablePlayerOpen |
true |
Bool |
Controls whether the SDK opens the player when a tile is tapped. When set to false, the SDK will not open the player and the app must handle tile taps via StorytellerListViewDelegate.onTileTapped(type: StorytellerTileType) (includes categories: [StorytellerCategoryDetail] for both clips and stories). This setting is not applied for lists on SDK‑owned screens (Storyteller Home, Followable Categories, and Search) where the SDK always opens the player. |
animateTilesOnReorder |
true |
Bool |
When the reloadData() method is called to update lists, a reorder animation is added to visualise the updating process. |
row.tileSpacing |
8 |
CGFloat |
The space between each Tile in a row |
row.startInset |
12 |
CGFloat |
The space before the first Tile in a row |
row.endInset |
12 |
CGFloat |
The space after the last Tile in a row |
grid.tileSpacing |
8 |
CGFloat |
The space between each Tile in a grid, both vertically and horizontally |
grid.columns |
2 |
CGFloat |
The number of columns in a grid. Not applicable to Search and Category screens. |
grid.topInset |
12 |
CGFloat |
The space before the first row in a grid |
grid.bottomInset |
12 |
CGFloat |
The space after the last row in a grid |
title.font |
nil |
StorytellerFontProvider |
Defines the font of the Title in Section |
title.textSize |
22 |
CGFloat |
Size of the Title in Section |
title.lineHeight |
28 |
CGFloat |
The line height of the Title in Section |
title.textCase |
default |
StorytellerTextCasing |
Sets the text case for the Title in Section. Possible values are upper, lower and default |
title.textColor |
nil |
UIColor |
Color of Title in Section |
Gradient#
The Gradient struct allows for the creation of a color gradient, with options to customize both the colors and the positions at which the gradient starts and ends.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
startColor |
nil |
UIColor |
The color where the gradient begins. |
endColor |
nil |
UIColor |
The color where the gradient ends. |
startPosition |
nil |
GradientPosition |
The position indicating where the gradient starts. |
endPosition |
nil |
GradientPosition |
The position indicating where the gradient ends. |
Enum: GradientPosition#
Defines positions for starting and ending points of the gradient.
| Value | Data Type | Description |
|---|---|---|
bottomLeft |
Int |
Bottom left corner of the gradient area. |
bottomCenter |
Int |
Bottom center edge of the gradient area. |
bottomRight |
Int |
Bottom right corner of the gradient area. |
centerLeft |
Int |
Center left edge of the gradient area. |
centerCenter |
Int |
Center of the gradient area. |
centerRight |
Int |
Center right edge of the gradient area. |
topLeft |
Int |
Top left corner of the gradient area. |
topCenter |
Int |
Top center edge of the gradient area. |
topRight |
Int |
Top right corner of the gradient area. |
Tiles#
The tiles property can be used to customize the appearance of the Tiles.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
chip.textSize |
11 |
CGFloat |
Text size for the New Indicator and Live Indicator. |
chip.show |
true |
Bool |
Used to show/hide the new/live chip |
title.textSize |
11 |
CGFloat |
Size of the Title on a Tile |
title.lineHeight |
13 |
CGFloat |
The line height of the Title on a Tile |
title.alignment |
center |
StorytellerAlignment |
The alignment of the Title on a Tile. Possible values are left, center and right |
circularTile.title.unreadTextColor |
inherits colors.black.primary for light, colors.white.primary for dark |
UIColor |
The text color of the Title for a circular tile when the story or the clip is unread |
circularTile.title.readTextColor |
inherits colors.black.tertiary for light, colors.white.tertiary for dark |
UIColor |
The text color of the Tile for a circular tile when the story or the clip is read |
circularTile.unreadIndicatorColor |
inherits colors.primary |
UIColor |
The color of the ring around a circular tile when the story or the clip is unread |
circularTile.readIndicatorColor |
#C5C5C5 |
UIColor |
The color of the ring around a circular tile when the story or the clip is read |
circularTile.unreadIndicatorGradient |
nil |
Gradient? |
The gradient of the ring around a circular tile when the story or the clip is unread. If set, overrides circularTile.unreadIndicatorColor |
circularTile.unreadIndicatorBorderColor |
nil |
UIColor? |
The border color of the ring around a circular tile when the story or the clip is unread |
circularTile.readIndicatorBorderColor |
nil |
UIColor? |
The border color of the ring around a circular tile when the story or the clip is read |
circularTile.unreadBorderWidth |
2 |
CGFloat |
The width of Circular Tile ring border in unread state |
circularTile.readBorderWidth |
2 |
CGFloat |
The width of Circular Tile ring border in read state |
circularTile.liveChip.readImage |
null |
UIImage? |
Image to be used in place of default read Live Indicator. |
circularTile.liveChip.unreadImage |
null |
UIImage? |
Image to be used in place of default unread Live Indicator |
circularTile.liveChip.unreadBackgroundColor |
colors.alert |
UIColor |
Background color of the Live Indicator when the story contains unread pages or the clip has not been viewed. |
circularTile.liveChip.readBackgroundColor |
colors.black.tertiary |
UIColor |
Background color of the Live Indicator when all story pages have been read or the clip has been viewed. |
circularTile.liveChip.unreadBackgroundGradient |
nil |
Gradient? |
The gradient of the ring around a live tile and background of the Live Indicator. If set, overrides circularTile.liveChip.unreadBackgroundColor |
circularTile.liveChip.unreadTextColor |
colors.white.primary |
UIColor |
Text color of the Live Indicator when the story contains unread pages or the clip has not been viewed. |
circularTile.liveChip.readTextColor |
colors.white.primary |
UIColor |
Text color of the Live Indicator when all story pages have been read or the clip has been viewed. |
circularTile.liveChip.unreadBorderColor |
null |
UIColor? |
Border color of the Live Indicator when the story contains unread pages or the clip has not been viewed. |
circularTile.liveChip.readBorderColor |
null |
UIColor? |
Boder color of the Live Indicator when all story pages have been read or the clip has been viewed. |
rectangularTile.padding |
8 |
CGFloat |
The internal padding for a rectangular story or the clip tile |
rectangularTile.title.textColor |
inherits colors.white.primary |
UIColor |
The text color of the Title for a rectangular tile |
rectangularTile.chip.alignment |
right |
StorytellerAlignment |
The alignment of the New Indicator and Live Indicator in Rectangular Tiles. Possible values are left, center or right |
rectangularTile.unreadIndicator.image |
null |
UIImage? |
An image which can be used in place of the default unread indicator for a rectangular tile. If set, overrides rectangularTile.unreadIndicator.gradient |
rectangularTile.unreadIndicator.gradient |
nil |
Gradient? |
The background gradient of the unread indicator for a rectangular tile. If set, overrides rectangularTile.unreadIndicator.backgroundColor |
rectangularTile.unreadIndicator.backgroundColor |
inherits colors.primary |
UIColor |
The background color of the unread indicator for a rectangular tile |
rectangularTile.unreadIndicator.textColor |
inherits colors.white.primary |
UIColor |
The text color of the unread indicator for a rectangular tile |
rectangularTile.unreadIndicator.borderColor |
null |
UIColor? |
Border color of the unread indicator for a rectangular tile |
rectangularTile.liveChip.readImage |
null |
UIImage? |
Image to be used in place of default read Live Indicator. |
rectangularTile.liveChip.unreadImage |
null |
UIImage? |
Image to be used in place of default unread Live Indicator. If set, overrides rectangularTile.liveChip.unreadBackgroundGradient |
rectangularTile.liveChip.unreadBackgroundGradient |
nil |
Gradient? |
Gradient background to be used for the Live Indicator. If set, overrides rectangularTile.liveChip.unreadBackgroundColor |
rectangularTile.liveChip.unreadBackgroundColor |
colors.alert |
UIColor |
Background color of the Live Indicator when the story contains unread pages or the clip has not been viewed. |
rectangularTile.liveChip.readBackgroundColor |
colors.black.tertiary |
UIColor |
Background color of the Live Indicator when all pages have been read or the clip has been viewed |
rectangularTile.liveChip.unreadTextColor |
colors.white.primary |
UIColor |
Text color of the Live Indicator when the story contains unread pages or the clip has not been viewed. |
rectangularTile.liveChip.readTextColor |
colors.white.primary |
UIColor |
Text color of the Live Indicator when all story pages have been read or the clip has been viewed. |
rectangularTile.liveChip.unreadBorderColor |
null |
UIColor? |
Border color of the Live Indicator when the story contains unread pages or the clip has not been viewed. |
rectangularTile.liveChip.readBorderColor |
null |
UIColor? |
Border color of the Live Indicator when all story pages have been read or the clip has been viewed. |


Player#
The player property is used to customize properties relating to the Story and Clips Player.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
showStoryIcon |
false |
Bool |
Shows the round story icon before the Story Title in the Player |
showTimestamp |
true |
Bool |
Shows the timestamp after the Story Title in the Player, indicating how long ago a story was published |
showShareButton |
true |
Bool |
Shows the share button in the Player. Setting this to false entirely disables sharing in Storyteller |
showLikeButton |
true |
Bool |
Shows the like button in the Clips Player. Setting this to false entirely disables liking in Storyteller |
showShareCount |
true |
Bool |
Shows the share count label in the Clips Player. Does not affect share button visibility |
showLikeCount |
true |
Bool |
Shows the like count label in the Clips Player. Does not affect like button visibility |
liveChip.image |
null |
UIImage? |
Image used in place of Live Chip before Live Story or Clip Titles. If set, it overrides liveChip.backgroundGradient |
liveChip.textColor |
null |
UIColor? |
Text color used for badge label for Live Story or Clip |
liveChip.backgroundGradient |
null |
Gradient? |
Background gradient of the badge for Live Story or Clip. If set, it overrides liveChip.backgroundColor |
liveChip.backgroundColor |
theme.colors.alert |
UIColor? |
Background color of the badge for Live Story or Clip |
liveChip.borderColor |
null |
UIColor |
Border color of the badge for Live Story or Clip |
icons.share |
null |
UIImage? |
An image to be used in place of the default share icon |
icons.refresh |
null |
UIImage? |
Refresh button image to be used in place of refresh share icon, used in the error state |
icons.like.initial |
null |
UIImage? |
An image to be used in place of the default like icon when the clip is not liked |
icons.like.liked |
null |
UIImage? |
An image to be used in place of the default like icon when the clip is liked |

Buttons#
The buttons property applies customizations to buttons which appear throughout the UI.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
backgroundColor |
inherits colors.white.primary |
UIColor |
The background color of buttons throughout the UI |
textColor |
inherits colors.black.primary |
UIColor |
The text color of buttons throughout the SDK |
textCase |
default |
StorytellerTextCasing |
Sets the text case for buttons throughout the UI. Possible values are upper, lower and default |
cornerRadius |
inherits primitives.cornerRadius |
CGFloat |
The corner radius for all buttons throughout the UI |
Instructions#
Use the instructions property to customize the appearance of the instructions screen.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
show |
true |
Bool |
Determines whether the Instructions Screen is shown the first time a user opens the Story Player. Set to false to completely disable the instructions screen. |
headingColor |
inherits colors.black.primary for light, colors.white.primary for dark |
UIColor |
The color of the heading text on the Instructions Screen |
headingTextCase |
default |
StorytellerTextCasing |
Determines the text case of the heading on the Instructions Screen. Possible values are upper, lower and default |
headingFont |
null |
StorytellerFontProvider |
Defines the font of the heading text on the Instructions Screen |
subHeadingColor |
inherits colors.black.secondary for light, colors.white.secondary for dark |
UIColor |
The color of the subheading text on the Instructions Screen |
backgroundColor |
inherits colors.white.primary for light, colors.black.primary for dark |
UIColor |
The color of the background of the Instructions Screen |
icons |
null |
InstructionsIcons |
A set of custom icons to be used for each instruction on the Instructions Screen |
button.backgroundColor |
inherits colors.black.primary for light, colors.white.primary for dark |
UIColor |
The background color of the button used on the Instructions Screen |
button.textColor |
inherits colors.white.primary for light, colors.black.primary for dark |
UIColor |
The text color of the button used on the Instructions Screen |
The icons property can be used to provide a completely custom set of icons. The icons should be 48x48 PNGs. An example of using this property is shown below:
private var customIcons: InstructionsIcons {
InstructionsIcons(
forward: UIImage(named: "icon-forward-custom"),
pause: UIImage(named: "icon-pause-custom"),
back: UIImage(named: "icon-back-custom"),
move: UIImage(named: "icon-move-custom")
)
}
theme.instructions.icons = customIcons

Engagement Units#
The engagementUnits property can be used to customize properties relating to Polls and Quizzes.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
poll.answerTextColor |
inherits colors.black.primary |
UIColor |
The text color used for Poll Answers |
poll.percentBarColor |
#CDD0DC |
UIColor |
The background color of the percentage bar in Poll Answers |
poll.selectedAnswerBorderColor |
inherits colors.primary |
UIColor |
The border color applied to the selected Poll Answer |
poll.answeredMessageTextColor |
inherits colors.white.tertiary |
UIColor |
The color of the vote count shown to users after they select a Poll Answer |
poll.selectedAnswerBorderImage |
null |
UIImage? |
A border image which can be used for the selected Poll Answer. If this is set, selectedAnswerBorderColor is used. |
poll.showPercentBarBackground |
false |
Bool |
Adds a striped background under the percentage bar in Poll Answers |
triviaQuiz.correctColor |
inherits colors.success |
UIColor |
The color used to show correct answers in Trivia Quizzes |
triviaQuiz.incorrectColor |
inherits colors.alert |
UIColor |
The color used to show incorrect answers in Trivia Quizzes |


Search#
The search property applies customizations to the Search component.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
search.backIcon |
chevron.backward system image |
UIImage? |
Image to be used as a back icon in the Search UI |
search.heading.font |
inherits lists.title.font |
StorytellerFontProvider |
The only font that can vary from theme.font, defines the styling of the Filters title in the Filter View |
search.heading.textSize |
inherits lists.title.textSize |
CGFloat |
Size of the Filter View title |
search.heading.lineHeight |
inherits lists.title.lineHeight |
CGFloat |
The line height of the Filter View title |
search.heading.textCase |
inherits lists.title.textCase |
StorytellerTextCasing |
Sets the text case for Filter View title. Possible values are upper, lower and default |
search.heading.textColor |
inherits lists.title.textColor |
UIColor |
Color of Filter View title |
Example#
// Subclassing font providers
class CustomFontProvider: StorytellerFontProvider, @unchecked Sendable {
override func font(weight: StorytellerFontWeight, size: CGFloat) -> UIFont? {
switch weight {
case .regular, .medium:
return UIFont(name: "Custom Font Regular", size: size)
case .semibold, .bold, .heavy, .black:
return UIFont(name: "Custom Font Bold", size: size)
}
}
}
// Setting instruction icons
let icons = StorytellerInstructionIcons(
forward: UIImage(named: "custom-icon-forward-white"),
pause: UIImage(named: "custom-icon-pause-white"),
back: UIImage(named: "custom-icon-forward-white"),
move: UIImage(named: "custom-icon-move-white")
)
// Creating the theme struct
var theme = StorytellerTheme()
// Customizing theme by direct property access
theme.light.colors.primary = UIColor.blue
theme.light.instructions.headingColor = UIColor.black
theme.light.instructions.icons = icons
theme.light.customFont = CustomFontProvider()
// Copying common theme properties over to the dark side
theme.dark = theme.light
// Applying dark mode specific values
theme.dark.instructions.headingColor = UIColor.white
Home#
The home property can be used to customize properties related to the Storyteller Home component.
| Property | Default Value | Data Type | Description |
|---|---|---|---|
home.headerTitle.font |
nil |
StorytellerFontProvider |
The only font that can vary from theme.font, defines the font for the heading |
home.headerTitle.textSize |
22 |
CGFloat |
Size of the title in section |
home.headerTitle.lineHeight |
28 |
CGFloat |
The line height of the title on in section |
home.headerTitle.textCase |
default |
StorytellerTextCasing |
Sets the text case for buttons throughout the UI. Possible values are upper, lower and default |
home.headerTitle.textColor |
nil |
UIColor |
Color of heading text in Storyteller Home |
home.circularTitle.textSize |
11 |
CGFloat |
Size of the circular title in section |
home.circularTitle.lineHeight |
13 |
CGFloat |
The line height of the circular title on in section |
home.singletonTitle.textSize |
22 |
CGFloat |
Size of the singleton title in section |
home.singletonTitle.lineHeight |
28 |
CGFloat |
The line height of the singleton title in section |
home.gridTitle.textSize |
16 |
CGFloat |
Size of the grid title in section |
home.gridTitle.lineHeight |
22 |
CGFloat |
The line height of the grid title on in section |