Collabora Online Design System
A living reference of the UI components, tokens, and patterns used in Collabora Online, extracted directly from the CSS source files under browser/css/.
Typography
The UI uses a multi-tier font system. The primary font for all chrome is --cool-font. Dialogs and form controls use --jquery-ui-font.
| Token | Value | Usage |
|---|---|---|
--default-font-size | 0.75rem (12px) | Body, labels, controls |
--medium-font-size | 0.875rem (14px) | Context menus, tooltips |
--header-font-size | 1rem (16px) | Section headers, doc title |
--tooltip-font-size | 0.875rem (14px) | Tooltip text |
--overflow-group-font-size | 8.5pt | Notebookbar group labels |
Color Palette
All colors are defined as CSS custom properties in color-palette.css (light) and color-palette-dark.css (dark). The primary brand color is a vibrant blue used for focus rings, active states, and primary actions.
Primary / Brand
Text
Backgrounds
Borders
Semantic
Document Type Accents
Each document type has an RGB triplet used for selected tab underlines, active toolbar buttons, and progress bars via --doc-type.
Cursors
All cursor types used across Collabora Online, with live previews and links to source. There is no centralised cursor map in the codebase — cursors are applied inline via style.cursor in TypeScript/JavaScript or via CSS classes. The Uses chip counts occurrences in browser/css/ + inline style.cursor assignments in browser/src/. The Source link points at one representative declaration at a pinned upstream SHA.
main when this page was built (SHA 202fadc) so line numbers stay accurate; the pipeline re-pins to the latest commit on every run.
Standard CSS cursors
| Cursor | Preview | Description | Uses | Source |
|---|---|---|---|---|
auto | hover | Browser chooses cursor automatically | 3 | cool.css:233 |
cell | hover | Cell selection in spreadsheets | 1 | spreadsheet.css:2 |
col-resize | hover | Column width resize | 2 | cool.css:266 |
context-menu | hover | Context menu trigger | 1 | jsdialogs.css:747 |
crosshair | hover | Crosshair selector (auto-fill in spreadsheets) | 4 | leaflet.css:169 |
default | hover | Standard arrow (buttons, toolbar, panels) | 20 | jquery-ui-lightness.css:61 |
e-resize | hover | Resize from the east (right) edge | 5 | jquery-ui-lightness.css:613 |
ew-resize | hover | Horizontal resize (east/west) | 1 | leaflet.css:187 |
grab | hover | Hand ready to grab/drag. Used only as SVG fallback in this codebase — see grab.svg below. | 2 | ShapeHandleAnchorSubSection.ts:30 |
grabbing | hover | Hand actively dragging | 1 | leaflet.css:220 |
help | hover | Help/explainer cursor (info tooltips, AI chat sidebar) | 1 | aichat-sidebar.css:212 |
inherit | hover | Inherit cursor from parent element | 1 | cool.css:946 |
move | hover | Move/drag element (four-arrow) | 7 | leaflet.css:165 |
n-resize | hover | Resize from north (top) edge | 1 | jquery-ui-lightness.css:599 |
ne-resize | hover | Resize from north-east corner | 1 | jquery-ui-lightness.css:648 |
nesw-resize | hover | Diagonal resize (NE / SW) | 1 | leaflet.css:183 |
not-allowed | hover | Action not permitted (disabled buttons) | 5 | backstage.css:166 |
ns-resize | hover | Vertical resize (north/south) | 1 | leaflet.css:195 |
nw-resize | hover | Resize from north-west corner | 1 | jquery-ui-lightness.css:641 |
nwse-resize | hover | Diagonal resize (NW / SE) | 1 | leaflet.css:191 |
pointer | hover | Interactive element (buttons, links) | 78 | selectionMarkers.css:29 |
row-resize | hover | Row height resize | 1 | spreadsheet.css:228 |
s-resize | hover | Resize from south (bottom) edge | 2 | jquery-ui-lightness.css:606 |
se-resize | hover | Resize from south-east corner (table fill) | 2 | jquery-ui-lightness.css:627 |
sw-resize | hover | Resize from south-west corner | 1 | jquery-ui-lightness.css:634 |
text | hover | Text input / text selection (I-beam) | 4 | jquery-ui-lightness.css:862 |
w-resize | hover | Resize from west (left) edge | 4 | jquery-ui-lightness.css:620 |
Custom SVG cursors
Three product-specific cursors shipped as SVG assets in browser/images/cursors/.
| Cursor | SVG | Preview | Description | Uses | Source |
|---|---|---|---|---|---|
crop.svg |
hover |
Image cropping tool — shown when dragging a shape's scaling handle in crop mode | 1 | ||
fill.svg |
hover |
Auto-fill brush — paint formatting / spreadsheet fill handle | 2 | ||
grab.svg |
hover |
Custom grab hand — shape anchor and custom shape handles | 2 |
Cursor declarations live across spreadsheet.css (spreadsheet-specific), leaflet.css (map/pan resize), jquery-ui-lightness.css (UI widget resize), and inline in browser/src/canvas/sections/ (shape/canvas handles).
Anatomy
How each custom cursor is constructed: hotspot, fill, stroke, and the surrounding clear region. The three Figma frames below break down the anatomy and the production conventions used across the cursor set.
Infographics
Illustrative SVGs that visualise a choice or state for the user. Distinct from cursors (functional pointer feedback) and toolbar icons (which live in the LibreOffice icon themes). Infographics live next to the surface that uses them — e.g. browser/admin/images/ for the integrator settings panel.
UI mode selector (integrator settings)
Shown in the per-user settings dialog under Customization, where the user picks between the Notebookbar and Compact toolbar layouts. The two illustrations are paired as clickable cards; the active card gets the .selected ring (blue tint + border). Rendered at 300px wide, scaling responsively. See AdminIntegratorSettings.ts:1443 (renderCompactModeToggle) and adminIntegratorSettings.css:669 for the styling.
Notebookbar.svg
Tabbed ribbon-style toolbar (the default). Shows a coloured tab strip with one tab active, plus a grid of icon-sized rectangles standing in for the per-tab tool clusters.
Compact.svg
Classic single-row toolbar with a menubar above (the “Compact” mode). Mirrors the Notebookbar illustration's footprint so the two cards align side-by-side.
Conventions for new infographics: author at the rendered display size (here 900×600 viewBox, displayed at 300×200), keep the Collabora primary blue #0369a2 for emphasis strokes, use the neutral greys (#e6e6e6, #f2f2f2, #f9f9f9) for the chrome, and pair illustrations that share a footprint so they can be compared at a glance.
Icons
The Collabora Online icon theme started life as Colibre, designed by Andreas Kainz. Over the years the set has grown well past its starting point: hundreds of additions and tweaks have landed from many contributors, and the result no longer follows the original Colibre conventions in every detail. The drift is friendly, not adversarial, but it does mean the source-of-truth for "what an icon should look like today" is no longer the historical Colibre rules. But here is the current icon guidelines for Collabora Online:
Components
Primary Button
The main call-to-action button, used for the default action in dialog boxes (e.g., "OK", "Apply"). Class: .button-primary
| Property | Value |
|---|---|
| Height | 32px |
| Min Width | 62px |
| Padding | 0 16px |
| Border Radius | var(--border-radius) = 4px |
| Border | 1px solid #0063b1 |
| Background | #0b87e7 (--color-primary) |
| Text Color | #fff |
| Font Size | 0.75rem (12px) |
| Margin | 5px |
Secondary Button
Used for cancel, close, and non-primary dialog actions. Also the default style for all generic <button> elements in dialogs. Class: .button-secondary
| Property | Value |
|---|---|
| Height | 32px |
| Min Width | 62px |
| Padding | 0 16px |
| Border Radius | 4px |
| Border | 1px solid #cecece (--color-border-dark) |
| Background | #e8e8e8 (--color-background-dark) |
| Text Color | #333333 |
| Margin | 5px |
Icon Toolbar Button
Used in the toolbar and notebookbar for icon-only actions (Bold, Italic, Underline, etc.). The selected state is tinted with the document-type accent color. Class: .unotoolbutton
| Property | Value |
|---|---|
| Size (button) | 28px × 28px (--btn-size) |
| Icon Size | 24px × 24px (--btn-img-size) |
| Padding | 2px (--btn-padding) |
| Border Radius | 4px |
| Border (default) | 1px solid transparent |
| Border (hover) | 1px solid #b6b6b6 (--color-btn-border) |
| Background (hover) | #f1f1f1 (--color-background-tabs-group) |
| Selected Background | rgba(var(--doc-type), 0.1) |
| Selected Border | 1px solid rgb(var(--doc-type)) |
| Disabled Opacity | 0.65 |
| Margin (in toolbar) | auto 2px |
Menu Button
A button with a dropdown arrow, used for selection controls in dialogs and sidebars. Class: .jsdialog.menubutton
| Property | Value |
|---|---|
| Padding | 8px 10px |
| Border Radius | 4px |
| Border | 1px solid #cecece (--color-border-dark) |
| Background | #e8e8e8 (--color-background-dark) |
| Font Size | calc(0.75rem * 1.2) (~14.4px) |
| Font Family | --jquery-ui-font |
| Arrow | CSS triangle: 4px border, 5px top |
Text Input
Standard single-line text field used in dialogs. Class: .jsdialog.ui-edit
| Property | Value |
|---|---|
| Height | 32px |
| Line Height | 28px |
| Border Radius | 4px |
| Border | 1px solid #cecece (--color-border-dark) |
| Background | #e8e8e8 (--color-background-dark) |
| Padding Inline | 4px |
| Focus border | #0b87e7 (--color-primary) |
Spinfield
Numeric input with step controls, used for measurements and quantities. Class: .spinfieldcontainer .spinfield
| Property | Value |
|---|---|
| Height | 28px |
| Min Width | 70px |
| Border Radius | 4px |
| Border | 1px solid #cecece |
| Background | #e8e8e8 |
| Padding | 4px 0 4px 4px |
| Container margin-end | 5px |
Checkbox
Custom-styled checkbox with SVG icons in the actual app. Class: .jsdialog.checkbutton
| Property | Value |
|---|---|
| Checkbox Size | 20px × 20px |
| Checkbox Margin | 1px 8px |
| Border Radius | 3px |
| Label Font Size | 0.75rem (12px) |
| Label Line Height | 28px |
Radio Button
Mutually exclusive option selector. Class: .radiobutton.jsdialog
| Property | Value |
|---|---|
| Radio Size | 18px × 18px |
| Radio Margin | 1px 8px |
| Dot Size (checked) | 8px |
| Border Radius | 50% |
Select / Listbox
Native select dropdown used in dialogs and sidebar. Class: .ui-listbox-container .ui-listbox
| Property | Value |
|---|---|
| Height (dialog) | 32px |
| Height (toolbar) | 24px (1.5rem) |
| Min Width | 70px (toolbar) / 100px (dialog) |
| Border Radius | 4px |
| Border | 1px solid #cecece |
| Background | #e8e8e8 |
| Padding | 0 14px 0 4px |
Combobox
Editable input combined with a dropdown list. Class: .ui-combobox
| Property | Value |
|---|---|
| Height (dialog) | 32px |
| Border Radius | 4px |
| Border | 1px solid #b6b6b6 (--color-border) |
| Input Background | #fff (--color-background-lighter) |
| Button width | 28px |
Tabs
Two tab variants exist, both underline-style with a doc-type accent. Dialog tabs colour the selected label in the doc-type colour and underline it. Notebookbar tabs keep the label colour and mark the selected tab with an inset bottom border in the doc-type colour.
| Property | Dialog Tab | Notebookbar Tab |
|---|---|---|
| Height | 34px (--header-height) | 34px (full nav height) |
| Border Radius | 0 (none) | 0 (none) |
| Padding | 0 1em | 0 clamp(4px, 1vw, 1em) |
| Selected text colour | rgba(var(--doc-type), 1) | unchanged label colour |
| Selected indicator | underline 2px solid rgba(var(--doc-type), 1), offset 6px | inset 0 -2px rgb(var(--doc-type)) |
| Margin | 0 12px 0 0 | 0 |
TreeView
Scrollable list of entries with optional icons, used in dialogs for file browsers, style lists, etc. Class: .ui-treeview
| Property | Value |
|---|---|
| Border | 1px solid #b6b6b6 |
| Border Radius | 4px |
| Min Size | 150px × 100px |
| Max Height (dialog) | 150px |
| Line Height | 24px |
| Icon Size | 16px (--btn-img-size-s) |
| Selected Background | #0b87e7 (--color-primary) |
| Hover Background | #c0bfbc (--color-background-darker) |
Context Menu
Right-click popup menu. Class: .context-menu-list
| Property | Value |
|---|---|
| Border | 1px solid #cecece |
| Border Radius | 4px |
| Box Shadow | 0 0 3px rgba(77,77,77,0.5) |
| Item Font Size | 0.875rem (14px) |
| Item Padding | 5px 22px |
| Separator | 1px solid #f1f1f1 |
Tooltip
Hover tooltip for toolbar buttons and controls. Class: .cooltip-text
| Property | Value |
|---|---|
| Padding | 7px 9px |
| Border Radius | 6px |
| Box Shadow | 0 0 4px rgba(77,77,77,0.5) |
| Font Size | 0.875rem (14px) |
| Background | #fff |
| Z-index | 2147483647 (max) |
Progress Bar
Thin progress indicator tinted with the document-type accent. Class: .ui-progressbar
Writer (blue) — 65%
Calc (green) — 40%
Impress (orange) — 80%
| Property | Value |
|---|---|
| Height | 5px |
| Track Color | rgba(var(--doc-type), 0.2) |
| Bar Color | rgb(var(--doc-type)) |
| Border Radius | 3px |
Color Picker
Grid of color swatches for font/background color selection. Class: .ui-color-picker
| Property | Value |
|---|---|
| Swatch Size | 16px × 16px |
| Grid Gap | 4px |
| Padding | 4px |
| Hover Outline | 2px solid #0b87e7, offset 1px |
Badge
Small status indicator used in the status bar. Class: .ui-badge
| Property | Value |
|---|---|
| Padding | 5px |
| Border Radius | 4px |
| Background | #c0bfbc (--color-background-darker) |
| Font Size | 0.75rem (12px) |
Separator
Visual dividers for toolbars and dialogs.
Horizontal separator:
| Property | Vertical | Horizontal |
|---|---|---|
| Size | 1px × 14px | 100% × 1px |
| Color | #c0bfbc | #f1f1f1 |
| Margin | 0 3px | 0 |
Snackbar
Toast-like notification bar shown at the bottom of the screen. Class: .snackbar
| Property | Value |
|---|---|
| Background | #323232 |
| Text Color | #fff |
| Padding | 12px 16px |
| Border Radius | 4px |
| Action Color | #83beec (--color-primary-lighter) |
Status bar
The bar pinned at the bottom of the document viewport. Hosts document-wide indicators (page number, zoom, word count, language, sheet selector in Calc, slide indicator in Impress) and the user presence list for collaborative editing. See the Figma reference for the canonical layout.
Dialogs
Collabora Online uses a single dialog framework (jsdialog, see Control.JSDialog.js + jsdialogs.css) but the framework hosts three behaviourally distinct kinds of surface, classified by two dimensions — whether the backdrop is dimmed (lightbox / nonlightbox) and whether background interaction is blocked (modal / nonmodal / non-dialog). See the classification thread on the forum for the original rubric.
| Kind | Backdrop | Background interaction | Movable | Outside click | CSS marker |
|---|---|---|---|---|---|
| Modal | Lightbox (dimmed) | Blocked | No | Closes only if .cancellable (info dialogs) | .jsdialog-window.modalpopup + .jsdialog-overlay |
| Nonmodal | Nonlightbox | Allowed | Yes (drag titlebar) | Does not close | .jsdialog-window:not(.modalpopup) |
| Popover | Nonlightbox | Allowed | No (anchored) | Closes | popupParent: '_POPOVER_' on the JSDialog instance |
Anatomy
Every dialog (regardless of kind) shares the same three regions: a title bar with the title and a close affordance, a body with the content, and a button area at the foot. Popovers are the exception — they have no title bar or button area and are just a body anchored to the trigger.
Body content with the inputs, labels and options the dialog needs to ask the user about.
- Title bar. Short noun phrase naming the dialog. On nonmodal dialogs the title bar is also the drag handle.
- Close affordance. The × on the right; Esc is the keyboard equivalent. For destructive dialogs prefer an explicit Cancel button.
- Body. A single column. Group related fields with a separator or a fieldset, not visual frames.
- Secondary actions (left). Help, Reset, advanced toggles. Never put a destructive action here.
- Primary action (right). The default action sits rightmost (Western convention; mirrored in RTL). Cancel sits just left of the primary action.
Modal (lightbox)
A dimmed backdrop blocks the document underneath. The dialog is centred and cannot be moved. Use when: the user must commit to a decision before they can keep working (settings, confirmations, blocking errors). Outside-click closes only when the dialog has the cancellable flag (typical for purely informational dialogs).
You have unsaved changes in Untitled 1. Do you want to save them before closing?
| Example | Dialog id / class | Source |
|---|---|---|
| About dialog | #modal-dialog-about-dialog-box |
jsdialogs.css:159 |
| Online Help | #modal-dialog-online-help-content-box |
jsdialogs.css:160 |
| Keyboard Shortcuts | #modal-dialog-keyboard-shortcuts-content-box |
jsdialogs.css:161 |
| Busy indicator | busypopup (type: modalpopup) |
Control.UIManager.ts:488 |
| LibreOffice native dialogs (Format Cells, Insert Special Character, …) | .lokdialog_container.modalpopup |
jsdialogs.css:26 |
Nonmodal (draggable)
No backdrop — the document underneath stays interactive. The dialog can be dragged by its title bar and stays open until the user dismisses it. Use when: the dialog is a tool the user keeps glancing at while editing (Find & Replace, Accept/Reject Changes, Sort criteria). Outside clicks do not close it.
3 pending changes by Caolán. Drag this dialog out of the way while you review the document.
| Example | Dialog id / class | Source |
|---|---|---|
| Accept / Reject Changes | AcceptRejectChangesDialog |
jsdialogs.css:62 |
| Sort Key Window (Sort — Calc) | SortKeyWindow |
jsdialogs.css:199 |
Note: the nonmodal surface is the rarest of the three — most older floating tool palettes (Find & Replace, advanced filters) still come from the LibreOffice native dialog path and so behave nonmodally without explicitly opting in. New work tends to land as either modal jsdialog or popover.
Popover (non-dialog)
Not really a dialog — an anchored panel for inline pickers and dropdowns. Has no title bar, no button area; just content. Opted-in via the JSDialog property popupParent: '_POPOVER_' (and clickToClose: '_POPOVER_'). Use when: the user is making a small bounded choice tied to a specific control (font color, autocomplete suggestion, autofilter values). Outside click dismisses.
| Example | Dialog id / class | Source |
|---|---|---|
| Auto-complete popup | AutoCompletePopup |
AutoCompletePopup.ts:56 |
| Content-control dropdown (Writer) | contentControlModalpopup |
ContentControlDropdownSubSection.ts:94 |
| Formula usage popup (Calc) | extends AutoCompletePopup |
Control.FormulaUsagePopup.ts:35 |