🌐 Languages: English | Русский
Chromatic Tooltips is a client-side mod for Minecraft that transforms tooltips into a fully customizable UI system. All customization is done through resource packs using declarative JSON, without Java code and recompilation.
Chromatic Tooltips allows you to:
- change backgrounds, borders and textures of tooltips
- configure margins, sizes and alignment
- add animations and transformations
- apply styles conditionally: by items, rarity, tags, NBT etc.
The mod is oriented towards both simple visual tweaks and complex UI compositions.
A tooltip style for items with rare rarity:
- semi-transparent background
- golden border
- appearance animation
.minecraft/resourcepacks/my_tooltips/
└── assets/
└── chromatictooltips/
└── tooltip.json
{
"styles": [{
"margin": 2,
"padding": 4,
"offsetMain": 6,
"offsetCross": -18,
"title": {
"defaultColor": "0xFFFFFFFF"
},
"defaultColor": "0x808080",
"decorators": [{
"type": "background",
"color": "0xF0100010",
"corner": false
},{
"type": "border",
"color": ["0x505000ff", "0x5028007F"],
"margin": 1
}]
}, {
"context": "item",
"filter": "rarity:rare",
"margin": 2,
"padding": 4,
"offsetMain": 6,
"offsetCross": -18,
"defaultColor": "0xFFFFFFFF",
"decorators": [
{ "type": "background", "color": "0x80000020" },
{ "type": "border", "color": "0xFFFFD700", "thickness": 1, "corner": true }
],
"transform": {
"duration": 300,
"function": "easeOut",
"keyframes": [
{ "progress": 0, "scale": 0.8 },
{ "progress": 100, "scale": 1.0 }
]
}
}
]
}- the first block with styles will apply to all tooltips
- the second block will apply only to items with
rarity:rare
- Save the file
- Press F3 + T
- Hover cursor over a rare item
{
"styles": [
{
"context": "item | default | <custom>",
"filter": "...",
"offsetMain": "<int>",
"offsetCross": "<int>",
"hr": {
"decorators": [ "<TooltipDecorator>" ],
"transform": "<TooltipTransform>",
"height" "<int>"
},
"<SectionBox>"
}
]
}or style if you don't have multiple tooltips
{
"style": {
"context": "item | default | <custom>",
"filter": "...",
"offsetMain": "<int>",
"offsetCross": "<int>",
"<SectionBox>"
}
}Accepts a string with the following tokens:
modname:itemid - identify: matches any part of the target, so minecraft:lava matches minecraft:lava_bucket
$orename - ore dictionary: matches any part of the target, so $ingot matches ingotIron, ingotGold, etc.
tag.color=red - tag
rarity:common - rarity
0 or 0-12 - damage
! - logical not. exclude items that match the following expression (!minecraft:portal)
r/.../ - standard java regex (r/^m\w{6}ft$/ = minecraft)
, - logical or in token (minecraft:potion 16384-16462,!16386)
| - logical or multi-item search (wrench|hammer)
example: minecraft:potion 16384-16462,!16386 | $oreiron | tag.color=red
SectionBox is the core of the entire system. Any tooltip, section or element is a SectionBox.
{
"margin": "<TooltipSpacing>",
"padding": "<TooltipSpacing>",
"font": "<TooltipFontContext>",
"decorators": [ "<TooltipDecorator>" ],
"transform": "<TooltipTransform>",
"alignInline": "left|center|right",
"alignBlock": "top|center|bottom",
"minWidth": "<int>",
"minHeight": "<int>",
"order": "<int>",
"spacing": "<int>",
"sectionSpacing": "<int>"
}Supported formats:
{
"padding": 4,
"padding": [4, 8, 4, 8],
"padding": { "top": 4, "right": 6, "bottom": 4, "left": 6 },
"padding": { "inline": 4, "block": 6},
"paddingInline": 4,
"paddingTop": 6
}Supported formats:
{
"fontShadow": true,
"fontParagrath": "<int>",
"fontColors": {
"gold": ["0xFFFFD700", "0xFFB8860B"]
}
}Alias
{
"font": {
"shadow": true,
"paragrath": "<int>",
"colors": {
"gold": ["0xFFFFD700", "0xFFB8860B"]
}
}
}| Field | Type | Description | Alias |
|---|---|---|---|
fontShadow |
boolean | Font shadow | font.shadow |
fontParagrath |
int | Height for empty line | font.paragrath |
fontColors |
object | Custom font colors | font.colors |
Supports 32 colors (0–15 basic, 16–31 shadows of basic fonts):
black,dark_blue,dark_green,dark_aqua,dark_red,dark_purplegold,gray,dark_gray,blue,green,aqua,red,light_purple,yellow,white
Single color
"red": "0xFF0000"Muted color is calculated automatically.
Two colors [normal, shadow]
"red": ["0xFF0000", "0x802020"]General structure:
{
"type": "background|border|gradient-horizontal|gradient-vertical|texture|item",
"margin": "<TooltipSpacing>", // see section 4
"alignInline": "left|center|right|start|end",
"alignBlock": "top|center|bottom|start|end",
"width": "<int>",
"height": "<int>",
// if type = RECTANGLE or BORDER
"color": "<color or array>",
// if type = BORDER
"thickness": "<int>",
"corner": "<boolean>",
// if type = TEXTURE
"path": "<string>", // + other TooltipTexture fields
"transform": { ... } // TooltipTransform JSON
}| type | what is created | required fields |
|---|---|---|
"none" |
nothing | — |
"background" |
colored rectangle | "color", "thickness", "corner" |
"border" |
border | "color", "thickness", "corner" |
"texture" |
texture render | all TooltipTexture fields |
"item" |
item render | no special fields |
"gradient-horizontal" |
horizontal gradient | "color" array |
"gradient-vertical" |
vertical gradient | "color" array |
Rectangular background with customizable color.
{
"type": "background",
"color": "0x80202020"
}Border around the tooltip.
{
"type": "border",
"color": "0xFFFFFFFF",
"thickness": 1,
"corner": true
}Gradient background (horizontal or vertical).
{
"type": "gradient-horizontal",
"color": ["0xFFFF0000", "0xFF00FF00"]
}Texture decorator for complex visual effects.
{
"type": "texture",
"path": "chromatictooltips:textures/tooltip_bg.png",
"repeat": true,
"slice": [4, true, 4]
}Possible options:
1) Single color
"color": 16777215→ becomes array of 4 corners: [ lt, rt, rb, lb ]
2) Two colors
"color": [ 10, 20 ]→ [ 10, 10, 20, 20 ]
3) Three colors
"color": [ c1, c2, c3 ]→ [ c1, c2, c3, c1 ]
4) Four colors
"color": [ lt, rt, rb, lb ](as is)
For gradient-horizontal / gradient-vertical
If array is not specified:
"color": "<int>"generates:
[ transparent, 60% opacity, full opacity, 60% opacity, transparent]
gradient direction depends on its type
General structure:
{
"path": "<string>", // path to texture
"color": "<int | color>", // color (ARGB), e.g. 0xFFFFFFFF
"region": {
"x": "<int>",
"y": "<int>",
"width": "<int>",
"height": "<int>"
},
// repeat / slice systems ↓ see below
"repeat": "...",
"slice": "[...]",
// Animation ↓ see below
"animation": { ... }
}Example:
{
"path": "chromatictooltips:textures/bg.png",
"repeat": true,
"slice": [4, true, 4]
}Supported formats:
{
"region": 4,
"region": [4, 8, 4, 8],
"region": { "x": 4, "y": 6, "width": 4, "height": 6 },
"regionX": 4,
"regionWidth": 6
}Supported formats:
{
"repeat": true,
"repeat": { "inline": true },
"repeatInline": true,
}The code supports 4 formats:
"repeat": trueEquivalent to:
{ "limit": 2147483647, "gap": 0, "fit": "floor" }"repeat": 4Equivalent to:
{ "limit": 4, "gap": 0, "fit": "floor" }"repeat": "ceil"Equivalent to:
{ "limit": 2147483647, "gap": 0, "fit": "ceil" }The fit field accepts:
"floor""ceil""clip""stretch"
"repeat": {
"limit": "<int>", // maximum number of repetitions
"gap": "<int>", // distance between blocks
"fit": "floor|ceil|clip|stretch"
}Note: If repeat is not specified — the system uses slice.
Supported formats:
{
"slice": [ 10, 5, 20 ],
"slice": { "inline": [ 10, 5, 20 ] },
"sliceInline": [ 10, 5, 20 ],
}Each slice is a pair of numbers:
[ base, grow ]
- base — fixed size of the section
- grow — "growth factor" (0 or >0), determines if the section can be stretched
Slice can accept values:
"slice": [ 10, 5, 20 ]Equivalent to:
{ "base": 10 }, { "base": 5 }, { "base": 20 }"slice": [ true, false ]Equivalent to:
{ "grow": 1 }, { "grow": 0 }{
"base": "<int>", // fixed size
"grow": "<int|bool>" // >=0 or true/false
}"slice": [
{ "base": 5, "grow": 1 },
{ "grow": true },
{ "base": 10 }
]Note: If slice is empty — fallback is used:
[ [ defaultSize, 1 ] ]
Animation describes a vertical sprite sheet (each frame is by block height).
"animation": {
"frametime": "<int>", // default frame duration
"frames": [ ... ], // list of frames
"framePingPong": "<boolean>" // if frames are not present
}Frames can be:
"frames": [0, 1, 2, 3]Each frame has:
index = valuetime = frametime
"frames": [
{ "index": 0, "time": 2 },
{ "index": 3, "time": 10 }
]If there are no frames:
"framePingPong": trueCreates sequence: 0,1,2,3,2,1
Time is
frametime.
{
"path": "textures/tooltip.png",
"color": 4294967295,
"region": {
"x": 0,
"y": 0,
"width": 32,
"height": 32
},
"repeatInline": {
"limit": 999,
"gap": 1,
"fit": "stretch"
},
"repeatBlock": "ceil",
"slice": {
"inline": [
{ "base": 4, "grow": true },
8,
{ "grow": false }
],
"block": [
6,
{ "base": 10, "grow": 1 }
],
},
"animation": {
"frametime": 2,
"frames": [
0,
{ "index": 1, "time": 4 },
2,
{ "index": 3, "time": 6 }
]
}
}{
"duration": 600,
"function": "easeInOut",
"originInline": "center",
"originBlock": "center",
"keyframes": [
{ "progress": 0, "scale": 0.9 },
{ "progress": 100, "scale": 1.0 }
]
}If the last keyframe doesn't have progress: 100, it's automatically added:
{ "progress": 100, "translateX": 0, "translateY": 0, "scale": 1, "rotate": 0 }Important: If transform has no keyframes → considered NOT animated → ignored by components.
{
"transform": {
"duration": 800,
"iterationCount": -1,
"pingPong": true,
"keyframes": [
{ "progress": 0, "scale": 1.0 },
{ "progress": 100, "scale": 1.05 }
]
}
}"alignInline": "left|center|right"
// or alias
"align": {"inline": "center"}"alignBlock": "top|center|bottom"
// or alias
"align": {"block": "center"}{
"minWidth": 80,
"minHeight": 20
}In the Chromatic Tooltips system, basic sections define the structure and placement of information within tooltips. Each section can contain various components and styles, and can be extended through Enrichers.
-
header Top part of the tooltip. Usually contains the item name or title. Components like
titleare added here, as well as any additional elements that should be displayed at the beginning of the tooltip. -
body Main part of the tooltip. Here detailed information about the item, its properties, description, quantity, hotkeys, Ore Dictionary and other content-related sections are displayed.
-
footer Bottom part of the tooltip. Used to display information about the mod that added the item, as well as other auxiliary data that should be at the end of the tooltip.
-
navigation Additional section for navigation elements. Drawn only if the tooltip doesn't fit on screen.
Each section is configured through JSON styles and can be supplemented or modified using Enrichers and configuration files.
Enrichers are a system of components that add various sections to tooltips. Each enricher defines where and when its section should be displayed.
Each enricher can be configured through the following parameters:
Defines which part of the tooltip the section will be displayed in:
- HEADER — in the tooltip header (top)
- BODY — in the tooltip body (main part)
- FOOTER — in the tooltip footer (bottom)
Defines the conditions under which the section will be shown:
- NONE — section never displays
- ALWAYS — section displays always
- DEFAULT — section displays by default (without pressed keys or if there are no sections for the pressed key)
- SHIFT — section displays only when Shift is pressed
- CTRL — section displays only when Ctrl is pressed
- ALT — section displays only when Alt is pressed
Modes can be configured through configuration files using the key sections.<sectionId>.modes.
List of default sections:
- title
- stacksize
- hotkeys:help-text
- hotkeys
- oreDictionary
- itemInfo
- contextInfo
- modInfo
Place: HEADER Mode: ALWAYS
Applies to the first line of the tooltip, or to the item name. You can use all styles that SectionBox accepts.
Triggers ItemTitleEnricherEvent through which other mods can edit displayName if it's an item.
Place: BODY Mode: SHIFT
Applies to tooltips that belong to an item. You can use all styles that SectionBox accepts. Displayed when Shift is pressed.
Triggers StackSizeEnricherEvent through which other mods can edit stackSize and fluid to handle it as a liquid.
Settings:
stackSizeEnricherEnabled— allows disabling this sectionplayerInventoryStackSizeEnabled— when hovering over an item in the player's inventory, will show not only the quantity under the cursor, but also the total quantity of items of this type in the player's inventory
Place: BODY Mode: DEFAULT (when there are hotkeys to display)
Displays a hint that you need to press Alt to view hotkeys.
Settings:
hotkeysHelpTextEnabled— allows disabling the hint
Place: BODY Mode: ALT
Applies to tooltips that belong to an item. You can use all styles that SectionBox accepts.
Triggers HotkeyEnricherEvent through which other mods can add their hotkeys for display. The tooltip itself has no base hotkeys. Displays list when Alt is pressed.
Settings:
hotkeysEnricherEnabled— allows disabling this section
Place: BODY Mode: CTRL
Displays a list of Ore Dictionary names for the item.
Place: BODY Mode: DEFAULT
Applies to tooltips that belong to an item. You can use all styles that SectionBox accepts. Displays item tooltip.
Triggers ItemInfoEnricherEvent through which other mods can add their lines to this section.
Place: BODY Mode: DEFAULT
Applies to tooltips that belong to an item. You can use all styles that SectionBox accepts. Displays lines that were passed to the tooltip.
Place: FOOTER Mode: ALWAYS
Applies to tooltips that belong to an item. You can use all styles that SectionBox accepts. Displays information about the mod that added the item.
Each enricher can be configured through configuration files, changing its display modes and location:
{
"sections": {
"stacksize": {
"modes": ["SHIFT", "CTRL"],
"place": "BODY"
},
"hotkeys": {
"modes": ["ALT"],
"place": "BODY"
},
"modInfo": {
"modes": ["DEFAULT"],
"place": "FOOTER"
}
}
}Creating a handler that will enrich the tooltip with its own sections:
public class CustomEnricher implements ITooltipEnricher {
@Override
public String sectionId() {
return "custom_section"; // Unique section ID
}
@Override
public EnricherPlace place() {
return EnricherPlace.BODY; // Where to display the section
}
@Override
public EnumSet<EnricherMode> mode() {
return EnumSet.of(EnricherMode.SHIFT); // When to display
}
@Override
public List<ITooltipComponent> build(TooltipContext context) {
// Logic for creating section components
return components;
}
}Registering an enricher:
TooltipHandler.addEnricher(String id, ITooltipEnricher enricher)TooltipHandler.drawHoveringText(List<?> textLines)
TooltipHandler.drawHoveringText(ItemStack stack, List<?> textLines)
TooltipHandler.drawHoveringText(TooltipRequest request)