Repository navigation
Branding
This page is generated from docs/BRANDING.md. To change it, edit that file in the repository: edits made here are replaced.
Block Viewer’s interface is clean, modular and slightly glassy: deep surface neutrals, a signal-lime accent, readable text, crisp icons. Every screen must read as Block — not as another viewer’s purple gradient skin.
The colours come from crates/block-viewer/src/theme.rs (Theme::default).
In the code, always use the resolved Palette (p.violet, p.ink…),
never a hard-coded colour: a skin can change them, and so can the user,
from Preferences › Appearance › Skin › Interface colours
(interface_colors.rs): they pick the accent (violet role → signal), the
windows' background (panel) and the text (ink), and the other accent,
surface and text roles follow from those three. Field names like violet /
indigo are historical role ids; hex values are Block brand tokens.
| Role id | Hex | Block token / use |
|---|---|---|
| violet | #D4FF3F |
signal — main accent: selection, active button, focus |
| indigo | #5BE3E8 |
data — secondary accent, brand gradients |
| teal | #5BE3E8 |
active / online, links in chat and profiles |
| navy | #0B0C0E |
surface-0 — deep background (login, loading) |
| violet_light | #E2FF7A |
signal on dark (accent text, hover) |
| violet_pale | #F0FFB0 |
soft signal details |
| indigo_light | #8EF0F4 |
light data variant |
| Name | Hex | Use |
|---|---|---|
| panel | #1B1D21 |
window background (opacity panel_alpha = 235) |
| bar | #131417 |
top and bottom bars |
| field | #0B0C0E |
input fields, sunken areas |
| raised | #25282D |
buttons, hovered surfaces |
| ink | #ECEEF0 |
main text |
| muted | #9AA0A8 |
secondary text, labels |
| muted_dim | #6B717A |
tertiary text, disabled |
| on_accent | #0B0C0E |
text/icons on a signal face (lime needs dark ink) |
| Name | Hex | Use |
|---|---|---|
| success | #4ADE80 |
success, validated |
| warn | #FB923C |
warning |
| danger | #F87171 |
error, destructive action |
| amber | #FCD34D |
soft highlight (favourites, ratings) |
| rose | #F472B6 |
rare: categories, playful accents |
The build axes take three of these colours, wherever an axis is shown (edit
gizmo, X / Y / Z boxes of "Transform", value readout): X danger,
Y success, Z indigo_light (build::draw::axis_color). Hovering and
dragging a handle switch to violet_light, like any selection.
-
The look comes from the theme. A window writes no colour, no radius
and no stroke: it takes the roles of the
Palette, the radii of the theme and the shared widgets ofui/widgets.rs. What a window draws with its own values is content, not dressing: colours of a map and of its legend, maturity rating colours, inside of a colour swatch, image shown as it is (widgets::PICTURE_TINT). A test checks it (ui/theme_guard.rs, run bycheck.ps1); a content line is declared there with a comment// theme-guard: content — the reason. -
Discreet glass. A shared GPU blur appears in the windows, the
dialogs, the top and bottom bars and everything laid over the world
(notifications, volume, emoji, media controls, local chat bubbles, pie
menu), under a dark tint. A soft shadow and a thin border separate the
surface from the world; the fields stay calm and readable. A skin with
panel_alpha = 255keeps opaque surfaces without this blur. The high contrast palette of Preferences › Accessibility (high_contrast.rs) is opaque too, and gives buttons, fields, windows, islands and dividers a light border: a new border goes throughwidgets::border_strokeso that it follows. Outside a window, a surface is drawn withwidgets::overlay. An already positioned scene label useswidgets::paint_world_label, with a lighter tint and shaded scene blur to keep its text readable. With no world behind, as on the login screen, usewidgets::overlay_frame. Never write a background, border or radius by hand. The bars keep thebarcolour as their tint (widgets::finish_bar_glass); the minimap keeps the Legacy Viewer's opacity with the border and the shadow of the windows. Menus, submenus, right-click menus and drop-down lists get this glass from a single place (menu::glaze, at the end of the frame, in the world): a new menu has nothing to do to get it. Gradients are reserved for brand elements (login background, grid wash, fill of the progress bar). -
Preferences › Block. The page of what Block does differently from
the Legacy Viewer carries the brand in two places only: its entry in the
category list (edge mark and name in the brand gradient, from
successthroughteal,indigo_lightandviolet_lighttorose) and the head of the page (signal/data wash over thenavysky, a hairline of the same gradient along its bottom edge). The settings below keep the cards and controls of the other pages; the choices between Block's look and the Legacy Viewer's are awidgets::segmentedtrack, Block's segment lit in the accent and the Legacy Viewer's inraised. It is not a precedent for the other pages (human's choice, 2026-10-14). -
Login screen. It is the viewer's showcase. The window blur only
knows the 3D scene, which is absent here: each card (
login::card) therefore redraws under its tint the sky it covers, out of focus (block_bg::frosted: no stars, soft brand blooms, modular grid softened, ridges feathered), with signal and data glows that spill around it. Its top edge catches the light; the login card carries the hairline with the brand gradient. The news sits next to the login card, on its row and at its height (the list scrolls), the version above it. The bottom buttons and the version number share the same line. -
Progress bars.
widgets::progress: a flat track (that of the sliders) filled with the brand gradient, which slides to its value instead of jumping; the percentage written below slides with it. The loading and teleport banners slide in the same way. An instantaneous level (microphone) goes throughwidgets::level, which only smooths the jitter between two measurements. Neveregui::ProgressBar. - Microphone button and panel. The microphone stays in the centre of its button, like the neighbouring icons; the arrow that follows it points to the panel it opens above the bar. The panel (window glass) gives the state of the voice, the two ways of talking as cards (the current one lit like an active button of the bar and ticked, the key to hold drawn as a key), then the microphone and the audio output one under the other, and the access to the preferences.
-
Loading and teleport. A "cinema banner" without a panel
(
ui/loading.rs): the last view, blurred, fills the whole screen, the name of the region is written large at the bottom left with what is known about it (maturity rating, arrival point, residents present) and the current step; at the bottom right, the tile of the region on the world map with the arrival point, and the progress in figures; the progress itself is a luminous hairline with the brand gradient along the whole bottom edge. The brand (wolf and name) stays discreet at the top left. -
Discreet rounding. Flat design, almost square corners. Buttons:
radius 5; windows, cards and pills of the toolbar: radius 3, with corners
close to those of the build tools, including when collapsed.
The radii come from the theme, never from a number in the code:
ui.visuals().window_corner_radiusfor cards, pills, list highlights and image or colour frames,ui.visuals().widgets.inactive.corner_radiusfor buttons,widgets::inner_radius(one pixel less than the windows) for a small mark inside a control or a row: knob of a switch, key, status square, maturity rating letter. Left as they are: the deliberate right angles (radius 0), the circles (status dots, notification dot) and the thin bars (track of a progress bar or of a level, marker on a rail), whose 2 px ends come from a single constant,widgets::TRACK_RADIUS. -
Name plate. The tag above an avatar (
ui/nameplate.rs) is the only exception to the almost square corners: a glass plate with fully rounded ends. It is not a precedent: nothing else in the interface is rounder, but for the residents' pictures (below). -
Residents' pictures. The profile pictures of the residents are round:
on the name plates, and in the Conversations window (bubbles, head of a
conversation, list), drawn by
widgets::avatar_disc, with their status dot on the edge (ui/presence.rs). Only these pictures and the name plates are round; groups, places and objects keep square tiles. The bubbles of the conversations themselves keep the buttons' radius, and the user's own bubbles carry the accent gradient (violet to indigo), the one gradient outside the brand elements, chosen by the human (2026-10-14).-
Glass: the tint of the plate (halfway between
navyandbar, at 52%) over the window blur, a light one-pixel border (inkat 14%), a soft shadow below. The blur goes to the 16 nearest plates; the others, and the distant pills, only have the tint, denser. An opaque skin (panel_alpha = 255) has no blur. -
Three levels depending on the distance to the camera: up to 15 m, the
full plate (profile picture in a circle, status dot, display name in
semi-bold, user name in
muted, group title inteal, round badges floating on the top right edge); up to 40 m, a compact pill (name and badges on one line); beyond, the name alone. A plate only changes level 1.5 m beyond a threshold and slides from one level to the other in 0.18 s. In a crowd, only the eight nearest plates are full, the next ones are compact pills. A line hidden by the preferences is absent: never an empty line. -
Status: dot at the bottom right of the picture,
success(present),amber(away),danger(do not disturb); none for a blocked resident. -
Badges:
successmicrophone (in the voice channel), three animated dots (typing),successheart (friend),ambertriangle (avatar too complex, shown as a silhouette),dangerno-entry sign (blocked). -
Voice: in the voice channel, the outline of the plate takes the
successcolour, at every level; while the person is speaking, a tight halo around the plate follows the level of their voice (fast rise, slower fall, no halo in silence). -
Name colour. Every display name in
ink, ours too; a blocked resident's in italics on a plate at 62%. Preferences › Colors › "Color the names by relation" (off by default) colours the names of the plates and of the classic name tags alike, with the colours of that page (me, friends, blocked, Linden Lab, from the palette by default). - Size: the display name keeps the size of the classic name tags (13 points) on the full plate; everything else follows from it through the proportions of the mock-up.
-
Glass: the tint of the plate (halfway between
-
Solid buttons. All buttons and drop-down lists are solid faces
without a visible border: the theme (
theme.rs) gives their border the colour of the face, only input fields and checkboxes keep an outline. A button therefore sets neither a background nor a radius itself, except for the main action (violet) or a destructive one (danger). An action with an icon useswidgets::action_button. The bottom toolbar has no separator lines: the spacing and the pill of the hovered or active button are enough. -
Switches and checkboxes. The switch (
widgets::switch) is almost square: track with the theme radius, square knob that slides. It is used for a standalone setting (alone with its label:widgets::switch_labeled); lists of flags (rights, data of a report, cells of a table) keep checkboxes, drawn bywidgets::checkbox(flat square, violet and ticked when it is active), never byui.checkbox. -
Radio buttons. A choice among several goes through
widgets::radio(radio_valuefor a value), never throughui.radio: the row of the checkbox (same size, same label, same hover), but round so that it is not taken for a checkbox: thin ring at rest, violet around a dot when the choice is made. It is the only round control of the interface; the other circles are marks (status dots, notification dot). -
Collapsible sections.
widgets::collapsing: a full-width row with a Tabler chevron and the title of the section, lit as a pill on hover, without a line; neveregui::CollapsingHeader. -
Colours. A colour is chosen with
widgets::color_button: the swatch opens a small glass panel (saturation / value field, hue bar, new colour above the old one, R G B and hexadecimal fields, eyedropper), never egui'scolor_edit_button_*. The colour palette of the build tools stays a separate window. -
Scroll bars. Thin and solid, in a strip of their own at the right of
what scrolls, faint at rest: the theme sets them for every scroll area
(
widgets::reserved_scroll_style). Never egui's floating bar, which covers the switches, buttons and values of the right edge; a window does not set its own scroll style. - Shared hierarchy. Window title and controls at the top, stable navigation, content grouped by function and accessible actions. The inventory keeps a large list and a single status line at the bottom, without a details sheet for the selection. Lists scroll within their area and do not make the window grow. The build tools use a compact inspector with a rail of sections.
- Light navigation. The tabs and navigation controls of the inventory are underlined in grey at rest, in violet when activated, without an outline. Hover stays discreet. The secondary actions of dialogs keep their dark surface. The command bar directly follows the title; the clear cross is built into the filter, without moving the controls.
- A single accent colour per area. Violet signals what is active or important; the rest is neutral.
-
Contrast and readability.
inktext onpanel; secondary text inmuted. Never dark violet text on a dark background (useviolet_light). On a solid violet face, text and icons inon_accent(neither hard-coded white, norink, which a skin can darken); on adangeroramberface, which are light, the text stays innavy. Signed height sliders usewidgets::height_slider: a visible neutral track, zero marker, violet fill from zero and a solid rectangular handle in the theme's radius. Secondary controls can be grey while retaining their interaction; the hover-height manual controls switch automatic mode off when edited. The surrounding shared floater keeps its glass. -
Very subtle but visible separators. A thin line of a neutral barely
lighter than the background, so that one can see where each element starts
and ends without weighing things down. Between two areas of a window:
widgets::divider(horizontal in a column, vertical in a row); between two groups of entries of a menu:menu::separator; a line placed by hand (edge of a rail, boundary between two panes) takeswidgets::divider_stroke. Neverui.separator(), and no line between buttons or the elements of a toolbar. -
Typography. Inter (regular, semi-bold) by default; Noto Sans,
Roboto and OpenDyslexic (an accessibility choice for readers with
dyslexia), each with its own semi-bold or bold face, as the other
embedded choices of Preferences › Fonts. No other font without a reason. Every text
follows the chosen font: semi-bold through
fonts::semibold, monospace only for code-like text (script editor, UUIDs, keys, colour codes, URLs, paths, versions), and an arrow or a caret is a Tabler icon, never a character (widgets::disclosure_caret,sort_caret). The characters they lack (display names and messages in Georgian, Japanese, Arabic, mathematical letters…) are drawn with the system fonts, which are never chosen for a text of the interface itself. - Text size. Preferences › Fonts and the skin's font scale apply to all font faces, including explicit rich text, painter fonts and monospace. Keep font sizes in unscaled points; shaping supplies the scaled advances and row heights. Size custom text containers from their laid-out text.
-
Regular spacing. Reuse the existing widgets (
ui/widgets.rs: flat buttons, switches, help badges, warning triangle…) rather than recreating them. -
Interface texts are short and clear, in English and French through
block_i18n::tr!(see TRANSLATING.md); English is the fallback. A tooltip explains every option whose effect is not obvious. -
Snapping windows. A window moved near another one, a bar or an edge
follows the pointer without a jump. Moving without Alt creates no snap
or attachment. With Alt held, what will happen on release is shown
by a guide: a 2 px line in
violet_lightalong the edges that are going to touch (over the length they share) or to align, and the very light outline of the place where the window will land, with the window radius. No guide, no snapping. Snapped windows touch, edge to edge, with each other as with the bars and the edges, with no gap, like those of the first-launch layout (layout::GAP, at 0). During the gesture, a small pill on the window glass recalls Alt's role: the keycap (widgets::keycap) followed by "snap and attach" for a free move, "detach this window" for a grouped move, or "do not snap" for a snapped resize. Alt detaches a moved window from its group and enables attachment to a new target; resizing keeps automatic snapping, disabled by Alt. The pill usesmutedtext, placed near the window, away from the guide and the pointer, after a short delay. No button and no permanent decoration for snapped windows.
Files in assets/branding/:
| File | Use |
|---|---|
block-logo.svg / .png (720 px) |
full logo in colour, transparent background: README, window icon, login and loading screens, About, system notifications (LOGO_PNG of app.rs), the Linux desktop icon (block-viewer.svg of the archive) |
block-logo-white.svg / .png (4096 px) |
white silhouette: the Block menu button of the toolbars (tinted with the palette), monochrome uses on a dark background |
block-logo-black.svg / .png (4096 px) |
black silhouette: monochrome uses on a light background |
block-logo-purple.png / block-logo-teal.png (4096 px) |
silhouette in violet or in turquoise |
block-logo-bg.png (4096 px) |
full logo on a navy background (the only file with an opaque background): square icons that need one (website's Apple touch icon) |
block.icns |
Block app mark (block/02-app-icon/, 16 to 1024 px): icon of Block Viewer.app on macOS (package-macos.ps1 builds it with iconutil when available) |
block/02-app-icon/ |
source PNGs and block.ico for the app icon (diagonal lime / charcoal mark) |
block.ico |
same mark as a Windows icon (16 to 256 px): icon of block-viewer.exe (embedded by its build.rs), "Block Tools" and "Block PR" shortcuts; prefer block/02-app-icon/block.ico when regenerating |
The logo is a howling wolf's head in profile, facing up and to the right,
its mane made of streaming ribbons, in a circle. Its colours: violet #8B5CF6
and indigo #4F46E5 for the head, turquoise #5EEAD4 and a deeper
turquoise #56CAA9 for the ribbons. Do not distort it, recolour it or add
an effect to it; the one-colour versions above are the only recolourings.
The buttons of the README header and its "Soon" pill are small SVG files in
docs/readme/, drawn like the viewer's own: flat face, radius of
4, a Tabler icon and Inter SemiBold.
| File | Use |
|---|---|
button-download.svg |
main action (violet face, on_accent text): latest release |
button-discord.svg / button-website.svg
|
flat buttons (raised face, ink text): the Discord and website links of the login screen (links.rs) |
pill-soon.svg |
marks a planned feature in a list (teal face, navy text), 18 px high |
The text is live text, not outlines. Its textLength is the width of the
label in Inter SemiBold at the file's font size, so that the layout holds
with the fallback fonts of a machine without Inter. For another button, copy
a file, change the icon paths, the label and that width, then the width of
the svg and of its rect (18 + 20 + 9 + text + 18).
Deeper protocol, offline-validation, and contributor-depth sections are omitted here so this page stays readable.
Generated from the repository; the guides are edited there.
For testers
- Reporting bugs
- Installing on Linux
- Experimental VR scene viewing
- Experimental Windows VR
- Installing on macOS
- Updates
- Asset imports
- LiveMesh
- Motorcycle hand contacts
- IK Edit and bone contacts
- Create native animations
- Local photo poser
- Dev Toolbox
Contributing
Technical
In the repository