Skip to content

Themes#

The appearance of the SDK can be customized using the StorytellerTheme class. This class allows you to configure the visual appearance of all Storyteller content in your app.

final theme = StorytellerTheme(
  light: ThemeType(
    colors: ThemeColors(primary: '#1C62EB'),
  ),
);

await Storyteller.setTheme(theme);

Set the theme as early as possible in your application's lifecycle (for example, in your main() function after initializing the SDK).

It is also possible to apply a specific theme to an individual StorytellerListView instance or when opening content. For example:

final rowTheme = StorytellerTheme(
  light: ThemeType(
    colors: ThemeColors(primary: '#FF0000'),
  ),
);

// Apply to a list view
StorytellerStoriesRowView(
  categories: ['news'],
  theme: rowTheme,
);

// Apply when opening a collection
await Storyteller.openCollection(
  'collection-id',
  theme: rowTheme,
);

For more information on setting a theme on an individual list, see StorytellerListViews.

The theme override on a direct collection open applies on iOS. The current Android Flutter bridge ignores that argument; set a global theme with Storyteller.setTheme for this Android path. Per-widget list themes are separate. See Additional Methods for presentation-specific limits.

The Showcase ThemeManager.buildTheme clones the selected preset and adjusts tile typography or singleton layouts on the fly—use it as guidance when composing dynamic StorytellerTheme objects.

Configuring a StorytellerTheme#

A StorytellerTheme consists of the following properties:

  • light - sets the ThemeType to apply for light mode.
  • dark - sets the ThemeType to apply for dark mode.

The native SDK selects the variant from the device appearance. Flutter's ThemeData does not configure these native views. A supplied light variant is not copied into dark; define both variants when your brand colors must apply in both modes. Omitted fields are excluded from the Dart map and resolved from native defaults, inheritance, and applicable tenant themes. Calling setTheme sends a new theme configuration; include all overrides you intend to retain rather than treating it as a patch to a previous theme.

The expanded Cards, player-icon, Clips, and Search mappings on this page are available in Flutter 11.6.4 and later. Flutter 12.1.2 adds Sheets, multi-stop gradients, the modal Clips layout, clips.embeddedVideoSizing, rectangularTile.titleGradient, and the Instructions button textSize and lineHeight. Native properties not exported by these Dart theme classes cannot be set through Flutter, even when they exist in a newer native reference. Android core requires API 24 or later; the iOS core supports iOS 13 or later, while your app or optional ads integration may require a higher deployment target; see Getting Started.

Creating Themes#

The ThemeType object exposes the Flutter theme sections shown below. Table defaults describe resolved native behavior, not Dart constructor values; most Dart properties default to null and are omitted from toMap(). Layout values use native logical units (Android dp/sp and iOS points); Android maps numeric dimensions to integers, so fractional values can be truncated.

Some properties take their default value from others. For example, setting the primary color to #FF0000 will also result in the New Indicator for Rectangular Tiles being colored red. Such properties are indicated in the tables 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 String The default accent color used throughout the UI. In general, this should be the primary brand color. Color strings should be in hex format (e.g., #1C62EB).
success #3BB327 String Used to indicate correct answers in Quizzes.
alert #E21219 String Used to indicate incorrect answers in Quizzes.
white.primary #FFFFFF String Used for white text
white.secondary white.primary at 85% opacity String Used for light text
white.tertiary white.primary at 70% opacity String Used for gray text
black.primary #1A1A1A String Used for black text
black.secondary black.primary at 85% opacity String Used for light black text
black.tertiary black.primary at 70% opacity String Used for gray text

Use #RRGGBB for opaque colors and #AARRGGBB for alpha colors. For example, #80FFFFFF is translucent white on both platforms.

Example:

ThemeColors(
  primary: '#1C62EB',
  success: '#3BB327',
  alert: '#E21219',
  white: ThemeTextColors(
    primary: '#FFFFFF',
    secondary: '#D9FFFFFF',
    tertiary: '#B3FFFFFF',
  ),
  black: ThemeTextColors(
    primary: '#1A1A1A',
    secondary: '#D91A1A1A',
    tertiary: '#B31A1A1A',
  ),
)


Font#

Use the customFont property to set a custom font for use throughout the UI.

Create a ThemeCustomFont with the Flutter asset path for each weight. The light path is optional for source compatibility; all other paths are required.

ThemeCustomFont(
  lightFilePath: 'fonts/MyCustomFont-Light.ttf',
  regularFilePath: 'fonts/MyCustomFont-Regular.ttf',
  mediumFilePath: 'fonts/MyCustomFont-Medium.ttf',
  semiboldFilePath: 'fonts/MyCustomFont-SemiBold.ttf',
  boldFilePath: 'fonts/MyCustomFont-Bold.ttf',
  heavyFilePath: 'fonts/MyCustomFont-Heavy.ttf',
  blackFilePath: 'fonts/MyCustomFont-Black.ttf',
)

Package every referenced font in your app's pubspec.yaml. You can register all weights under one Flutter font family; the native theme still uses the individual asset paths rather than the Flutter family name:

flutter:
  fonts:
    - family: MyCustomFont
      fonts:
        - asset: fonts/MyCustomFont-Light.ttf
          weight: 300
        - asset: fonts/MyCustomFont-Regular.ttf
          weight: 400
        - asset: fonts/MyCustomFont-Medium.ttf
          weight: 500
        - asset: fonts/MyCustomFont-SemiBold.ttf
          weight: 600
        - asset: fonts/MyCustomFont-Bold.ttf
          weight: 700
        - asset: fonts/MyCustomFont-Heavy.ttf
          weight: 800
        - asset: fonts/MyCustomFont-Black.ttf
          weight: 900

On iOS, all six required font files must resolve and register successfully for the custom font provider to apply. If the optional light file is omitted or unavailable, iOS falls back to the regular font for that weight. Theme images also use Flutter asset paths: declare their files under flutter.assets and pass them using ThemeImage(filePath: ...). Native Lottie resources use the separate packaging described under Player.


Primitives#

The primitives object contains base values which are used throughout the UI.

Property Default Value Data Type Description
cornerRadius 8 double The corner radius used for rectangular tiles, buttons and poll/quiz answers

Example:

ThemePrimitives(
  cornerRadius: 12.0,
)


Lists#

The lists property customizes properties of the various list types available from the SDK.

Property Default Value Data Type Description
backgroundColor colors.white.primary (light), colors.black.primary (dark) String Required for outline on Live chip and fade to the side of the row
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 the onTileTapped callback.
animateTilesOnReorder true bool When the reloadData() method is called to update lists, a reorder animation is added to visualize the updating process.
row.tileSpacing 8 double The space between each Tile in a row
row.startInset 12 double The space before the first Tile in a row
row.endInset 12 double The space after the last Tile in a row
grid.tileSpacing 8 double The space between each Tile in a grid, both vertically and horizontally
grid.columns 2 int The number of columns in a grid.
grid.topInset 0 double The space before the first row in a grid
grid.bottomInset 0 double The space after the last row in a grid
title.font null ThemeCustomFont Defines the font of the Title in Section
title.textSize 22 double Size of the Title in Section
title.lineHeight 28 double The line height of the Title in Section
title.textCase default String Sets the text case for the Title in Section. Possible values are upper, lower and default
title.textColor colors.black.primary (light), colors.white.primary (dark) String Color of Title in Section

Example:

ThemeLists(
  backgroundColor: '#FFFFFF',
  enablePlayerOpen: true,
  animateTilesOnReorder: true,
  row: ThemeListRow(
    tileSpacing: 8.0,
    startInset: 12.0,
    endInset: 12.0,
  ),
  grid: ThemeListGrid(
    tileSpacing: 8.0,
    columns: 2,
    topInset: 12.0,
    bottomInset: 12.0,
  ),
  title: ThemeTitle(
    textSize: 22.0,
    lineHeight: 28.0,
    textCase: 'default',
    textColor: '#000000',
  ),
)


Gradient#

The ThemeGradient class 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 required String The color where the gradient begins (hex format).
endColor required String The color where the gradient ends (hex format).
startPosition required int The position indicating where the gradient starts (0-8).
endPosition required int The position indicating where the gradient ends (0-8).
stops null List<ThemeGradientStop> Ordered color stops for a gradient with more than two colors. If set, overrides startColor and endColor. See Multi-stop gradients.

Gradient Positions#

Gradient positions are represented as integers from 0-8:

Value Position
0 Bottom left corner
1 Bottom center edge
2 Bottom right corner
3 Center left edge
4 Center
5 Center right edge
6 Top left corner
7 Top center edge
8 Top right corner

Example:

ThemeGradient(
  startColor: '#FF0000',
  endColor: '#0000FF',
  startPosition: 6, // Top left
  endPosition: 2,   // Bottom right
)

Multi-stop gradients#

ThemeGradient.withStops creates a gradient from two or more ThemeGradientStop values. It sets startColor and endColor from the first and last stops.

Property Default Value Data Type Description
color required String Stop color as #RRGGBB or #AARRGGBB
location required double Position along the gradient, from 0 to 1

The constructors throw an ArgumentError for fewer than two stops, a location outside 0 to 1, or locations that decrease. If the native SDK can't use a stop list, for example because a stop color is invalid, it draws the two-color gradient from startColor and endColor instead.

Flutter colors put alpha first (#AARRGGBB), while the Storyteller CMS puts it last (#RRGGBBAA). Reorder the digits when you copy a transparent color from the CMS.

Example:

ThemeGradient.withStops(
  stops: [
    ThemeGradientStop(color: '#00000000', location: 0),
    ThemeGradientStop(color: '#66000000', location: 0.6),
    ThemeGradientStop(color: '#CC000000', location: 1),
  ],
  startPosition: 7, // Top center
  endPosition: 1,   // Bottom center
)


Tiles#

The tiles property can be used to customize the appearance of the Tiles.

Property Default Value Data Type Description
chip.textSize 11 double Text size for the New Indicator and Live Indicator.
chip.show true bool Used to show/hide the new/live chip
title.textSize 11 double Size of the Title on a Tile
title.lineHeight 13 double The line height of the Title on a Tile
title.alignment center String 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 String 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 String The text color of the Tile for a circular tile when the story or the clip is read
circularTile.unreadIndicatorColor inherits colors.primary String The color of the ring around a circular tile when the story or the clip is unread
circularTile.readIndicatorColor #C1C1C1 (Android), #C5C5C5 (iOS) String The color of the ring around a circular tile when the story or the clip is read
circularTile.unreadIndicatorGradient null ThemeGradient The gradient of the ring around a circular tile when the story or the clip is unread. If set, overrides circularTile.unreadIndicatorColor
circularTile.unreadIndicatorBorderColor null String The border color of the ring around a circular tile when the story or the clip is unread
circularTile.readIndicatorBorderColor null String The border color of the ring around a circular tile when the story or the clip is read
circularTile.unreadBorderWidth 2 double The width of Circular Tile ring border in unread state
circularTile.readBorderWidth 1 double The width of Circular Tile ring border in read state
circularTile.liveChip.readImage null ThemeImage Image to be used in place of default read Live Indicator.
circularTile.liveChip.unreadImage null ThemeImage Image to be used in place of default unread Live Indicator
circularTile.liveChip.unreadBackgroundColor colors.alert String 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 String Background color of the Live Indicator when all story pages have been read or the clip has been viewed.
circularTile.liveChip.unreadBackgroundGradient null ThemeGradient 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 String 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 String Text color of the Live Indicator when all story pages have been read or the clip has been viewed.
circularTile.liveChip.unreadBorderColor null String Border color of the Live Indicator when the story contains unread pages or the clip has not been viewed.
circularTile.liveChip.readBorderColor null String Border color of the Live Indicator when all story pages have been read or the clip has been viewed.
rectangularTile.padding 8 double The internal padding for a rectangular story or the clip tile
rectangularTile.title.textColor inherits colors.white.primary String The text color of the Title for a rectangular tile
rectangularTile.titleGradient native default ThemeGradient Readability gradient behind the Title of a rectangular tile. If set, replaces the native title scrim
rectangularTile.chip.alignment right String The alignment of the New Indicator and Live Indicator in Rectangular Tiles. Possible values are left, center or right
rectangularTile.unreadIndicator.image null ThemeImage 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 null ThemeGradient iOS-only gradient for the rectangular unread indicator; Android ignores this Dart field. If set on iOS, overrides rectangularTile.unreadIndicator.backgroundColor
rectangularTile.unreadIndicator.backgroundColor inherits colors.primary String The background color of the unread indicator for a rectangular tile
rectangularTile.unreadIndicator.textColor inherits colors.white.primary String The text color of the unread indicator for a rectangular tile
rectangularTile.unreadIndicator.borderColor null String Border color of the unread indicator for a rectangular tile
rectangularTile.liveChip.readImage null ThemeImage Image to be used in place of default read Live Indicator.
rectangularTile.liveChip.unreadImage null ThemeImage Image to be used in place of default unread Live Indicator. If set, overrides rectangularTile.liveChip.unreadBackgroundGradient
rectangularTile.liveChip.unreadBackgroundGradient null ThemeGradient Gradient background to be used for the Live Indicator. If set, overrides rectangularTile.liveChip.unreadBackgroundColor
rectangularTile.liveChip.unreadBackgroundColor colors.alert String 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 String Background color of the Live Indicator when all pages have been read or the clip has been viewed
rectangularTile.liveChip.unreadTextColor colors.white.primary String 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 String Text color of the Live Indicator when all story pages have been read or the clip has been viewed.
rectangularTile.liveChip.unreadBorderColor null String Border color of the Live Indicator when the story contains unread pages or the clip has not been viewed.
rectangularTile.liveChip.readBorderColor null String Border color of the Live Indicator when all story pages have been read or the clip has been viewed.

Diagram illustrating rowTheme rectangular options

Diagram illustrating rowTheme circular options

Example:

ThemeTiles(
  chip: ThemeTileChip(
    textSize: 11.0,
    show: true,
  ),
  title: ThemeTileTitle(
    textSize: 11.0,
    lineHeight: 13.0,
    alignment: 'center',
  ),
  circularTile: ThemeCircularTile(
    unreadIndicatorColor: '#1C62EB',
    readIndicatorColor: '#C5C5C5',
    unreadBorderWidth: 2.0,
    readBorderWidth: 2.0,
  ),
  rectangularTile: ThemeRectangularTile(
    padding: 8.0,
    title: ThemeRectangularTileTitle(
      textColor: '#FFFFFF',
    ),
  ),
)


Cards#

The cards property customizes controls rendered inside native Cards collections.

Property Default Value Data Type Description
audio.mutedIcon native icon ThemeImage Audio-control image shown while a video Card is muted
audio.unmutedIcon native icon ThemeImage Audio-control image shown while a video Card is unmuted
audio.unavailableIcon native icon ThemeImage Android-only image shown when a video Card has no audio; iOS ignores this optional field
ThemeCards(
  audio: ThemeCardsAudio(
    mutedIcon: ThemeImage(filePath: 'assets/icons/card_muted.png'),
    unmutedIcon: ThemeImage(filePath: 'assets/icons/card_unmuted.png'),
    unavailableIcon: ThemeImage(
      filePath: 'assets/icons/card_audio_unavailable.png',
    ),
  ),
)

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
showMoreButton native default bool Android-only visibility control for the Clips more button; iOS ignores it
enableFollowableCategorySwipeFromRightEdge native default bool Enables or disables the right-edge swipe that opens a followable category
liveChip.image null ThemeImage Image used in place of Live Chip before Live Story or Clip Titles. If set, it overrides liveChip.backgroundGradient
liveChip.textColor inherits colors.white.primary String Text color used for badge label for Live Story or Clip
liveChip.backgroundGradient null ThemeGradient Background gradient of the badge for Live Story or Clip. If set, it overrides liveChip.backgroundColor
liveChip.backgroundColor theme.colors.alert String Background color of the badge for Live Story or Clip
liveChip.borderColor null String Border color of the badge for Live Story or Clip
icons.share null ThemeImage An image to be used in place of the default share icon
icons.refresh null ThemeImage Refresh button image to be used in place of refresh share icon, used in the error state
icons.back null ThemeImage Back button image used by the native player
icons.close null ThemeImage Android-only close button image; iOS ignores it
icons.more null ThemeImage Android-only more button image; iOS ignores it
icons.likeInitial null ThemeImage An image to be used in place of the default like icon when the clip is not liked
icons.likeLiked null ThemeImage An image to be used in place of the default like icon when the clip is liked
icons.likeAnimation.liked null ThemeLottieAnimationResource Lottie animation used when a clip changes to liked
icons.likeAnimation.unliked null ThemeLottieAnimationResource Lottie animation used when a clip changes to unliked
icons.mute.muted null ThemeImage Mute button image for the muted state
icons.mute.unmuted null ThemeImage Mute button image for the unmuted state
icons.captions.enabled null ThemeImage Captions button image for the enabled state
icons.captions.disabled null ThemeImage Captions button image for the disabled state
clips.showButtonBackgrounds native default bool Controls native action-button backgrounds in the Clips Player
clips.actionIconSize native default double Requested Clips action-icon size; the native SDK applies its supported size rules
clips.eyebrow.* native defaults ThemePlayerClipsEyebrow Font, text size, line height, and color for the Clips eyebrow
clips.title.* native defaults ThemePlayerClipsTitle Font, weight, text size, line height, and color for the Clips title
clips.feedSwitcher.selected.* native defaults ThemePlayerClipsFeedSwitcherState Weight, text size, and line height for the selected Following-feed label
clips.feedSwitcher.unselected.* native defaults ThemePlayerClipsFeedSwitcherState Weight, text size, and line height for an unselected Following-feed label
clips.categoryNavigation.* native defaults ThemePlayerClipsCategoryNavigation Weight, text size, and line height for category-navigation labels
clips.topGradient native default ThemeGradient Readability gradient at the top of the Clips Player
clips.bottomGradient native default ThemeGradient Readability gradient at the bottom of the Clips Player
clips.embeddedVideoSizing Storyteller CMS setting String Video sizing in Embedded Clips: legacy keeps the existing layout; widthConstrained fits the video to the available width, keeps its aspect ratio, and centers any vertical overflow. If set, overrides the CMS setting. Modal Clips are not affected
clips.modal.* null ThemePlayerClipsModal Layout overrides for full-screen Clips; see Modal Clips layout. When unset, the existing modal layout is kept
clips.progressBar.position native default String bottom or aboveAction; native layout remains authoritative
clips.progressBar.playedColor native default String Played-track color
clips.progressBar.remainingColor native default String Remaining-track color
clips.progressBar.active.* native defaults ThemePlayerClipsProgressBarActive Played, remaining, current-time, and total-time colors while scrubbing
clips.spacing.* native defaults ThemePlayerClipsSpacing Insets and gaps: backButtonStartInset, contentInsetHorizontal, contentInsetBottom, actionSpacing, eyebrowToTitleSpacing, titleToActionSpacing, titleToCategoriesSpacing, categoriesToMoreSpacing, metadataToProgressBarSpacing, and progressBarToActionSpacing

On Android, add each Lottie JSON file to android/app/src/main/res/raw and provide its filename without .json in androidRawResourceName (or name as a fallback). On iOS, add the JSON file to the app target's Copy Bundle Resources phase and provide its bundled resource name in name. Use iosBundlePath when the resource belongs to a bundle other than the main app bundle.

Diagram illustrating playerTheme options

Example:

ThemePlayer(
  showStoryIcon: false,
  showTimestamp: true,
  showShareButton: true,
  showLikeButton: true,
  enableFollowableCategorySwipeFromRightEdge: true,
  icons: ThemePlayerIcons(
    share: ThemeImage(filePath: 'assets/icons/share.png'),
    back: ThemeImage(filePath: 'assets/icons/back.png'),
    likeInitial: ThemeImage(filePath: 'assets/icons/like.png'),
    likeLiked: ThemeImage(filePath: 'assets/icons/like_filled.png'),
    mute: ThemePlayerMuteIcons(
      muted: ThemeImage(filePath: 'assets/icons/muted.png'),
      unmuted: ThemeImage(filePath: 'assets/icons/unmuted.png'),
    ),
    captions: ThemePlayerCaptionsIcons(
      enabled: ThemeImage(filePath: 'assets/icons/captions_on.png'),
      disabled: ThemeImage(filePath: 'assets/icons/captions_off.png'),
    ),
    likeAnimation: ThemePlayerLikeAnimation(
      liked: ThemeLottieAnimationResource(
        name: 'like_lottie',
        androidRawResourceName: 'like_lottie',
      ),
      unliked: ThemeLottieAnimationResource(
        name: 'unlike_lottie',
        androidRawResourceName: 'unlike_lottie',
      ),
    ),
  ),
  clips: ThemePlayerClips(
    showButtonBackgrounds: true,
    actionIconSize: 34,
    title: ThemePlayerClipsTitle(
      fontWeight: 'bold',
      textSize: 18,
      lineHeight: 22,
      textColor: '#FFFFFF',
    ),
    progressBar: ThemePlayerClipsProgressBar(
      position: 'aboveAction',
      playedColor: '#1C62EB',
      remainingColor: '#80FFFFFF',
    ),
    spacing: ThemePlayerClipsSpacing(
      contentInsetHorizontal: 16,
      contentInsetBottom: 20,
      actionSpacing: 12,
    ),
  ),
)

ThemePlayerClips.modal takes a ThemePlayerClipsModal, which overrides the layout of full-screen (modal) Clips. It doesn't affect Embedded Clips. Leave it unset to keep the existing modal layout. On Android, any valid value that differs from the default switches to the configurable modal layout; defaults and values Android rejects don't. Set modal only when you want to change it.

Property Default Value Data Type Description
drawBehindStatusBar false bool Extends the video behind the status bar; controls stay in the safe area
feedSwitcherItemSpacing native default double Total horizontal gap between the For You and Following labels
titleToCategoriesSpacing native default double Gap between the title or description and the category labels
categoriesToMoreSpacing native default double Gap between the category labels and the more/less control
metadataToProgressBarSpacing native default double Gap between the metadata and the resting progress track
progressBarToActionSpacing native default double Minimum gap between the progress track and the primary action
progressBarPosition native default String bottom or aboveAction. aboveAction falls back to bottom when the Clip has no call to action
topGradientHeight native default double Height of the top readability gradient, including any status-bar area behind the video
bottomGradientHeight native default double Height of the bottom readability gradient
progressBarHeight native default double Height of the resting progress track
progressBarActiveHeight native default double Height of the progress track while scrubbing; the drag target stays at least 48 high
progressBarInsetHorizontal native default double Horizontal inset of the progress track from the video edges
navigationIconSize native default double Size of the Back and Search icons; their tap targets stay at least 48
navigationInsetHorizontal native default double Horizontal inset of the Back and Search buttons from the safe edges
navigationInsetTop native default double Additional top inset for navigation below the status bar
navigationHeight native default double Height of the navigation row. Android uses at least 48
searchIcon null ThemeImage Replaces the built-in Search icon

Spacing, inset and gradient-height values must be zero or more, and sizes must be greater than zero. Android ignores values outside these ranges.


Buttons#

The buttons property applies customizations to buttons which appear throughout the UI.

Property Default Value Data Type Description
backgroundColor inherits colors.white.primary String The background color of buttons throughout the UI
textColor inherits colors.black.primary String The text color of buttons throughout the SDK
textCase default String Sets the text case for buttons throughout the UI. Possible values are upper, lower and default
cornerRadius inherits primitives.cornerRadius double The corner radius for all buttons throughout the UI

Example:

ThemeButtons(
  backgroundColor: '#000000',
  textColor: '#FFFFFF',
  textCase: 'upper',
  cornerRadius: 8.0,
)


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 String The color of the heading text on the Instructions Screen
headingTextCase default String Determines the text case of the heading on the Instructions Screen. Possible values are upper, lower and default
headingFont inherits global custom font ThemeCustomFont Defines the font of the heading text on the Instructions Screen
subHeadingColor inherits colors.black.secondary for light, colors.white.secondary for dark String The color of the subheading text on the Instructions Screen
backgroundColor inherits colors.white.primary for light, colors.black.primary for dark String The color of the background of the Instructions Screen
icons null ThemeInstructionIcons Custom instruction images on Android and iOS
button.backgroundColor inherits colors.black.primary for light, colors.white.primary for dark String The background color of the button used on the Instructions Screen
button.textColor inherits colors.white.primary for light, colors.black.primary for dark String The text color of the button used on the Instructions Screen
button.textSize 16 double Android-only text size of the button label on the Clips Instructions Screen; iOS ignores it
button.lineHeight 21 double Android-only line height of the button label on the Clips Instructions Screen; iOS ignores it

The icons property replaces the instruction images on Android and iOS. The icons should be 48x48 PNGs or appropriate asset images. An example of using this property is shown below:

ThemeInstructionIcons(
  forward: ThemeImage(filePath: 'assets/icons/forward.png'),
  pause: ThemeImage(filePath: 'assets/icons/pause.png'),
  back: ThemeImage(filePath: 'assets/icons/back.png'),
  move: ThemeImage(filePath: 'assets/icons/move.png'),
)

Diagram illustrating instructionsTheme options

Example:

ThemeInstructions(
  show: true,
  headingColor: '#000000',
  headingTextCase: 'default',
  subHeadingColor: '#666666',
  backgroundColor: '#FFFFFF',
  button: ThemeInstructionButton(
    backgroundColor: '#000000',
    textColor: '#FFFFFF',
  ),
)


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 String The text color used for Poll Answers
poll.percentBarColor #CDD0DC String The background color of the percentage bar in Poll Answers
poll.selectedAnswerBorderColor inherits colors.primary String The border color applied to the selected Poll Answer
poll.answeredMessageTextColor inherits colors.white.primary String The color of the vote count shown to users after they select a Poll Answer
poll.selectedAnswerBorderImage null ThemeImage A border image which can be used for the selected Poll Answer. If set, the native selected-answer border uses the supplied image.
poll.showImageAnswerGradientOverlay true bool Controls whether image poll answers show the native gradient overlay
triviaQuiz.correctColor inherits colors.success String The color used to show correct answers in Trivia Quizzes
triviaQuiz.incorrectColor inherits colors.alert String The color used to show incorrect answers in Trivia Quizzes

Diagram illustrating pollTheme options

Diagram illustrating quizTheme options

Example:

ThemeEngagementUnits(
  poll: ThemePoll(
    answerTextColor: '#000000',
    percentBarColor: '#CDD0DC',
    selectedAnswerBorderColor: '#1C62EB',
    showImageAnswerGradientOverlay: true,
  ),
  triviaQuiz: ThemeTriviaQuiz(
    correctColor: '#3BB327',
    incorrectColor: '#E21219',
  ),
)


The search property applies customizations to the Search component.

Property Default Value Data Type Description
backIcon default back icon ThemeImage Image to be used as a back icon in the Search UI
backgroundColor native default String Search screen background color
heading.font inherits global custom font ThemeCustomFont Defines the styling of the Filters title in the Filter View
heading.textSize 22 double Size of the Filter View title
heading.lineHeight 28 double The line height of the Filter View title
heading.textCase default String Sets the text case for Filter View title. Possible values are upper, lower and default
heading.textColor appearance foreground (Android), lists.title.textColor (iOS) String Color of Filter View title
input.* native defaults ThemeSearchInput Input background, text, placeholder, icon, corner radius, text size, and line height
filterButton.* native defaults ThemeSearchFilterButton Filter-button background, icon color, and corner radius
suggestions.* native defaults ThemeSearchSuggestions Suggestion text/icon colors, icon background, text size, and line height
noResults.iconColor native default String No-results icon color
noResults.title.* native defaults ThemeSearchTextStyle No-results title color, size, line height, and case
noResults.message.* native defaults ThemeSearchTextStyle No-results message color, size, line height, and case
filters.backgroundColor native default String Filter-sheet background color
filters.handleColor native default String Filter-sheet drag-handle color
filters.sectionHeading.* native defaults ThemeSearchTextStyle Filter-section heading color, size, line height, and case
filters.option.* native defaults ThemeSearchFilterOption Normal/selected option colors and borders, corner radius, text size, and line height
filters.applyButton.* native defaults ThemeButtons Apply-button background, text color, text case, and corner radius

Example:

ThemeSearch(
  backgroundColor: '#F7F9FC',
  backIcon: ThemeImage(filePath: 'assets/icons/back.png'),
  input: ThemeSearchInput(
    backgroundColor: '#FFFFFF',
    textColor: '#172033',
    placeholderTextColor: '#667085',
    iconColor: '#1C62EB',
    cornerRadius: 12,
  ),
  filterButton: ThemeSearchFilterButton(
    backgroundColor: '#E8EEFF',
    iconColor: '#1C62EB',
    cornerRadius: 12,
  ),
  heading: ThemeTitle(
    textSize: 22.0,
    lineHeight: 28.0,
    textCase: 'default',
    textColor: '#000000',
  ),
  filters: ThemeSearchFilters(
    backgroundColor: '#FFFFFF',
    handleColor: '#98A2B3',
    option: ThemeSearchFilterOption(
      selectedBackgroundColor: '#1C62EB',
      selectedTextColor: '#FFFFFF',
      cornerRadius: 8,
    ),
    applyButton: ThemeButtons(
      backgroundColor: '#1C62EB',
      textColor: '#FFFFFF',
    ),
  ),
)

Search filter availability (Sort, Date, and Content Type) is controlled by the tenant's native Search settings. Local Flutter themes change appearance, not which filters are enabled. The Following-feed selection mechanism, modal Clips bottom anchoring, followable-category profile content, and remote theme precedence are also resolved by native/tenant configuration. Omitted Flutter theme fields continue to inherit those native values.


Home#

The home property can be used to customize properties related to the Storyteller Home component.

Property Default Value Data Type Description
headerTitle.font null ThemeCustomFont Defines the font for the heading
headerTitle.textSize 22 double Size of the title in section
headerTitle.lineHeight 25 (Android), 28 (iOS) double The line height of the title in section
headerTitle.textCase default String Sets the text case for the title. Possible values are upper, lower and default
headerTitle.textColor null String Color of heading text in Storyteller Home
circularTitle.textSize inherits lists.title.textSize (Android), 11 (iOS) double Size of the circular title in section
circularTitle.lineHeight inherits lists.title.lineHeight (Android), 13 (iOS) double The line height of the circular title in section
singletonTitle.textSize 22 double Size of the singleton title in section
singletonTitle.lineHeight 28 double The line height of the singleton title in section
gridTitle.textSize 16 double Size of the grid title in section
gridTitle.lineHeight 22 double The line height of the grid title in section

Example:

ThemeHome(
  headerTitle: ThemeTitle(
    textSize: 22.0,
    lineHeight: 28.0,
    textCase: 'default',
    textColor: '#000000',
  ),
  circularTitle: ThemeHomeTitle(
    textSize: 11.0,
    lineHeight: 13.0,
  ),
)

Sheets#

The sheets property can be used to customize the sheets that Storyteller presents.

Property Default Value Data Type Description
cornerRadius native default for each sheet double Top corner radius of Storyteller sheets

Checking a Theme Change#

Start with an obvious accent color, supply both light and dark variants, and open a published Story/Clip from the placement you styled. Test both device appearances and the relevant list/player/Search screen: a Clips-only property does not restyle Stories, and a per-list theme can override the global theme for that placement. Set the global theme before mounting content.

If a value appears unchanged, check its applicable surface and platform, the placement's own theme, and any tenant or collection remote overrides. Native/tenant settings can override supported host values. Confirm that icon and font assets are packaged and paths match their case; missing iOS font weights prevent the provider from applying. Reopening content is a useful check after changing appearance or resources; rebuilding is required after changing native resource packaging. Continue with Storyteller List Views, Search, or Troubleshooting for the surface you are integrating.