Style Developers: Migrating to 6.0.0



For a style to be fully compatible with Textual 6, some changes are required.
This knowledge base article describes these changes.


Changes have been made to the following template files:

If a style overrides any of these template files, then the changes made to these files must also be applied to those overridden by the style.

Click each file to view the difference between Textual 5 and Textual 6.

Conversation Tracking

To reduce clutter, Textual now has a built-in implementation of the conversation tracking feature.

The following functions no longer need to exist in a style's scripts.js file:


Parts of the file that callout to updateNicknameAssociatedWithNewMessage() can be replaced by ConversationTracking.updateNicknameWithNewMessage(), which takes the same arguments

Parts of the file that callout to userNicknameSingleClickEvent() can be replaced by ConversationTracking.nicknameSingleClickEventCallback(), which takes the same arguments


Textual.newMessagePostedToView = function(line)
    var element = document.getElementById("line-" + line);


Textual.nicknameSingleClicked = function(e)


Some styles, such as those that modify the layout of the DOM, will not be compatible with Textual's implementation of the conversation tracking feature. Those styles must implement their own logic for this feature.

Loading History

When a user clicks into a view for the first time, Textual loads their history from the previous session.
It is recommended that a style fades in the history when it finishes loading, instead of having it appear suddenly.

To achieve this effect, set the opacity of the #historic_messages element to zero (0), which will hide this element by default. Set a transition on opacity changes, then change the opacity of this element when the history finishes loading.

To make this as easy as possible, the class .loaded is automatically added to the #historic_messages element when the history finishes loading.


#historic_messages {
    transition: opacity 0.8s ease-in;
    opacity: 0;
    height: 0;
    margin: 0;
    padding: 0;

#historic_messages.loaded {
    opacity: 0.6;
    height: auto;


The callback Textual.viewFinishedLoadingHistory() is invoked when the history finishes loading. A style can use this callback to perform other transitions.

Custom Scrollbars for Dark Styles

Textual now adds the attribute customscroller=true to the <body> element when the user has macOS setup to always show scrollbars.

It is recommended that a styles with dark background setup a custom scrollbar appearance when this attribute is set so that the user does not see a white scrollbar on a dark background.

To make this task easier for style authors, the following code can be pasted into a style's design.css file.
This code creates a scrollbar which appears similar to the normal OS X scrollbar, but darker.

body[customscroller="true"]::-webkit-scrollbar {
	width: 17px;

body[customscroller="true"]::-webkit-scrollbar:horizontal {
	height: 0;

body[customscroller="true"]::-webkit-scrollbar-track {
	background: #393939;
	box-shadow: inset 1px 0px 0px 0px #4b4b4b;

body[customscroller="true"]::-webkit-scrollbar-thumb {
	background-color: #7c7c7c;
	border: 4px solid transparent;
	border-left: 5px solid transparent;
	border-radius: 20px;
	background-clip: content-box;

body[customscroller="true"]::-webkit-scrollbar-thumb:hover {
	background-color: #b0b0b0;

Overlay Color

Textual 6 allows users to view multiple channels at once. When a user is viewing multiple channels, a transparent view is laid on top of every channel except the frontmost one.

A style can change the color of this view in its styleSettings.plist file by defining a string value for the key named Channel View Overlay Color.

Hexadecimal notation, in RRGGBBAA order, is the only format supported by this setting.


<key>Channel View Overlay Color</key>

In this example, #00000066 produces the color black with 40% alpha.

app Object

The app object now uses callback functions instead of return values.


    function(returnValue) {
Last modified: May 09, 2018
The contents of this webpage are released into the Public Domain for unlimited distribution.