g2-kit 99 samples · 57 components
Charts, controls and HUD pieces for Even Realities G2 Hub plugins, drawn on the phone into 4-bit image tiles. Previews are 2× and use the brightness curve measured in evenhub-simulator 0.9.5; real-glasses brightness is not yet verified. Unofficial; not affiliated with Even Realities.
Live demos run in your browser with a mock host: on-screen gesture buttons, or ↓ ↑ Enter D H
Quickstart →Bar chart + KPI above a native list: the README snippet.Dashboard →Four panels; swipe moves focus, tap opens one chart across all four tiles.Pickers →Carousel typing, a time picker with edit mode, a keyboard prompt.Keyboard →Every keyboard option: letters, symbols layer / beside / below, rows or columns, action keys.Text components →Spinner and progress as firmware text, and a slider per text box: no image sends.Tic-tac-toe →The game kit with one gesture axis.Calibration card →16 levels, theme levels, patterns and fonts, for tuning a device.
Charts
BarChart · 288×144 · P0 · ink 32%
props
import { BarChart } from 'g2-kit/charts'
g2.draw('left', BarChart, {
"title": "Steps / day",
"data": [
{
"label": "M",
"value": 6200
},
{
"label": "T",
"value": 8400
},
{
"label": "W",
"value": 4100
},
{
"label": "T",
"value": 9900
},
{
"label": "F",
"value": 7300
},
{
"label": "S",
"value": 12100
},
{
"label": "S",
"value": 3000
}
],
"highlight": 5,
"peak": true,
"format": "compact"
})
BarChart · 288×144 · P0 · ink 15%
props
import { BarChart } from 'g2-kit/charts'
g2.draw('left', BarChart, {
"title": "Net flow",
"data": [
3,
-2,
5,
-4,
1,
6
],
"categories": [
"Q1",
"Q2",
"Q3",
"Q4",
"Q5",
"Q6"
]
})
BarChart · 288×144 · P0 · ink 20%
props
import { BarChart } from 'g2-kit/charts'
g2.draw('left', BarChart, {
"title": "Languages",
"orientation": "horizontal",
"data": [
{
"label": "TypeScript",
"value": 48
},
{
"label": "Rust",
"value": 21
},
{
"label": "Go",
"value": 14
},
{
"label": "Python",
"value": 9
}
],
"highlight": 0,
"format": {
"suffix": "%"
}
})
BarChart · 288×144 · P0 · ink 16%
props
import { BarChart } from 'g2-kit/charts'
g2.draw('left', BarChart, {
"title": "Load by hour",
"data": [
50,
63,
75,
84,
89,
90,
86,
79,
68,
56,
42,
30,
20,
13,
10,
12,
17,
27,
39,
52,
65,
76,
85,
89
],
"categories": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23"
],
"fill": "hatch",
"highlight": 14
})
LineChart · 288×144 · P0 · ink 11%
props
import { LineChart } from 'g2-kit/charts'
g2.draw('left', LineChart, {
"title": "Revenue",
"series": [
{
"name": "This year",
"values": [
12,
15,
14,
18,
22,
19,
25,
28,
26,
31,
29,
34
]
},
{
"name": "Last year",
"values": [
10,
11,
13,
12,
14,
16,
15,
17,
19,
18,
20,
22
]
}
],
"xLabels": [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
],
"annotateMinMax": true,
"area": "dots",
"format": {
"suffix": "k"
}
})
LineChart · 288×144 · P0 · ink 4%
props
import { LineChart } from 'g2-kit/charts'
g2.draw('left', LineChart, {
"title": "Heart rate",
"series": [
70,
74,
78,
81,
85,
88,
90,
85,
86,
87,
87,
86,
85,
84,
75,
73,
71,
69,
67,
66,
65,
57,
57,
57,
58,
60,
62,
64,
61,
64,
68,
72,
76,
80,
83,
80,
83,
85,
88,
89
],
"xLabels": [
"6am",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"now"
]
})
LineChart · 288×144 · P0 · ink 6%
props
import { LineChart } from 'g2-kit/charts'
g2.draw('left', LineChart, {
"series": [
{
"values": [
5,
7,
6,
9,
8,
11,
10
]
},
{
"values": [
3,
4,
null,
6,
7,
6,
8
]
},
{
"values": [
1,
2,
2,
3,
5,
4,
6
]
}
],
"labels": "normal",
"xLabels": [
"M",
"T",
"W",
"T",
"F",
"S",
"S"
]
})
Sparkline · 128×28 · P0 · ink 14%
props
import { Sparkline } from 'g2-kit/charts'
g2.draw('left', Sparkline, {
"values": [
12,
15,
14,
18,
22,
19,
25,
28,
26,
31,
29,
34
],
"band": [
15,
25
]
})
Sparkline · 96×16 · P0 · ink 14%
props
import { Sparkline } from 'g2-kit/charts'
g2.draw('left', Sparkline, {
"values": [
10,
11,
13,
12,
14,
16,
15,
17,
19,
18,
20,
22
],
"extremes": true
})
Kpi · 288×144 · P0 · ink 8%
props
import { Kpi } from 'g2-kit/charts'
g2.draw('left', Kpi, {
"label": "Active users",
"value": 12840,
"format": "compact",
"delta": 0.042,
"deltaFormat": "percent",
"footnote": "vs last week",
"spark": [
12,
15,
14,
18,
22,
19,
25,
28,
26,
31,
29,
34
]
})
Kpi · 144×144 · P0 · ink 7%
props
import { Kpi } from 'g2-kit/charts'
g2.draw('left', Kpi, {
"label": "Temp",
"value": "21.5",
"unit": "°C",
"delta": -1.2,
"style": "segment"
})
Kpi · 288×96 · P0 · ink 7%
props
import { Kpi } from 'g2-kit/charts'
g2.draw('left', Kpi, {
"label": "Latency",
"value": 182,
"unit": "ms",
"delta": 34,
"good": "down",
"align": "center"
})
Gauge · 288×144 · P0 · ink 16%
props
import { Gauge } from 'g2-kit/charts'
g2.draw('left', Gauge, {
"value": 63,
"label": "Battery",
"unit": "%",
"thresholds": [
20,
50
]
})
Gauge · 144×144 · P0 · ink 14%
props
import { Gauge } from 'g2-kit/charts'
g2.draw('left', Gauge, {
"value": 72,
"label": "CPU",
"unit": "%",
"thresholds": [
80
]
})
Gauge · 144×144 · P0 · ink 16%
props
import { Gauge } from 'g2-kit/charts'
g2.draw('left', Gauge, {
"value": 30,
"style": "needle",
"label": "Speed",
"max": 50
})
BarChart · 288×144 · P0 · ink 1%
props
import { BarChart } from 'g2-kit/charts'
g2.draw('left', BarChart, {
"title": "Sales",
"data": [],
"message": "No sales yet"
})
LineChart · 288×144 · P0 · ink 3%
props
import { LineChart } from 'g2-kit/charts'
g2.draw('left', LineChart, {
"title": "Weather",
"series": [],
"state": "error",
"message": "Offline: showing nothing"
})
MultiBarChart · 288×144 · P1 · ink 36%
props
import { MultiBarChart } from 'g2-kit/charts'
g2.draw('left', MultiBarChart, {
"title": "Sleep vs goal",
"series": [
{
"name": "Sleep",
"values": [
6.5,
7.2,
5.9,
8.1,
7
]
},
{
"name": "Goal",
"values": [
8,
8,
8,
8,
8
]
}
],
"categories": [
"M",
"T",
"W",
"T",
"F"
],
"valueLabels": false
})
MultiBarChart · 288×144 · P1 · ink 31%
props
import { MultiBarChart } from 'g2-kit/charts'
g2.draw('left', MultiBarChart, {
"title": "Time by app (h)",
"mode": "stacked",
"series": [
{
"name": "Work",
"values": [
5,
6,
4,
7,
5,
1,
0
]
},
{
"name": "Chat",
"values": [
1,
2,
1,
1,
2,
1,
1
]
},
{
"name": "Media",
"values": [
1,
1,
2,
1,
2,
4,
3
]
}
],
"categories": [
"M",
"T",
"W",
"T",
"F",
"S",
"S"
]
})
PieChart · 288×144 · P1 · ink 19%
props
import { PieChart } from 'g2-kit/charts'
g2.draw('left', PieChart, {
"slices": [
{
"label": "Rent",
"value": 1200
},
{
"label": "Food",
"value": 450
},
{
"label": "Travel",
"value": 220
},
{
"label": "Other",
"value": 330
}
]
})
PieChart · 288×144 · P1 · ink 16%
props
import { PieChart } from 'g2-kit/charts'
g2.draw('left', PieChart, {
"slices": [
{
"label": "Yes",
"value": 62
},
{
"label": "No",
"value": 28
},
{
"label": "?",
"value": 10
}
],
"donut": 0,
"labelMode": "outside"
})
ProgressRings · 288×144 · P1 · ink 21%
props
import { ProgressRings } from 'g2-kit/charts'
g2.draw('left', ProgressRings, {
"rings": [
{
"label": "Move",
"value": 420,
"max": 500
},
{
"label": "Exercise",
"value": 0.8
},
{
"label": "Stand",
"value": 0.5
}
]
})
Heatmap · 288×144 · P1 · ink 26%
props
import { Heatmap } from 'g2-kit/charts'
g2.draw('left', Heatmap, {
"title": "Commits by hour",
"values": [
[
0,
0,
0,
0,
0,
0,
0,
9,
7,
6,
4,
2,
1,
0,
0,
0,
1,
2,
4,
5,
7,
8,
9,
10
],
[
0,
0,
0,
0,
0,
0,
0,
4,
2,
1,
0,
0,
0,
1,
2,
4,
5,
7,
8,
9,
10,
10,
9,
8
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
4,
5,
7,
8,
9,
10,
10,
9,
8,
7,
5,
4
],
[
0,
0,
0,
0,
0,
0,
0,
1,
2,
4,
5,
7,
8,
9,
10,
10,
9,
8,
7,
5,
4,
2,
1,
0
],
[
0,
0,
0,
0,
0,
0,
0,
5,
7,
8,
9,
10,
10,
9,
8,
7,
5,
4,
2,
1,
0,
0,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
3,
3,
3,
3,
3,
2,
2,
1,
1,
0,
0,
0,
0,
0,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
0,
3,
3,
2,
2,
1,
1,
0,
0,
0,
0,
0,
1,
1,
2,
2,
3,
3
]
],
"rowLabels": [
"M",
"T",
"W",
"T",
"F",
"S",
"S"
],
"colLabels": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23"
],
"encoding": "both",
"highlight": [
2,
15
]
})
CalendarHeatmap · 288×144 · P1 · ink 21%
props
import { CalendarHeatmap } from 'g2-kit/charts'
g2.draw('left', CalendarHeatmap, {
"title": "Workouts",
"days": [
0,
0,
2,
0,
0,
1,
0,
0,
5,
0,
1,
0,
0,
5,
0,
0,
4,
0,
0,
3,
0,
4,
0,
0,
3,
0,
0,
2,
0,
0,
1,
0,
2,
0,
0,
1,
0,
0,
5,
0,
0,
4,
0,
5,
0,
0,
4,
0,
0,
3,
0,
0,
2,
0,
3,
0,
0,
2,
0,
0,
1,
0,
0,
5,
0,
1,
0,
0,
5,
0,
0,
4,
0,
0,
3,
0,
4,
0,
0,
3,
0,
0,
2,
0,
0,
1,
0,
2,
0,
0,
1,
0,
0,
5,
0,
0,
4,
0,
5,
0,
0,
4,
0,
0,
3,
0,
0,
2,
0,
3,
0,
0,
2,
0,
0,
1,
0,
0,
5,
0,
1,
0,
0,
5,
0,
0,
4,
0,
0,
3,
0,
4,
0,
0,
3,
0,
0,
2,
0,
0
],
"end": "2026-09-29T00:00:00.000Z"
})
Funnel · 288×144 · P1 · ink 16%
props
import { Funnel } from 'g2-kit/charts'
g2.draw('left', Funnel, {
"stages": [
{
"label": "Visits",
"value": 12000
},
{
"label": "Sign-ups",
"value": 3100
},
{
"label": "Trials",
"value": 1400
},
{
"label": "Paid",
"value": 420
}
],
"format": "compact"
})
BulletChart · 288×36 · P1 · ink 21%
props
import { BulletChart } from 'g2-kit/charts'
g2.draw('left', BulletChart, {
"label": "Revenue",
"value": 270,
"target": 250,
"ranges": [
150,
225,
300
],
"format": {
"suffix": "k"
}
})
Timeline · 288×96 · P1 · ink 10%
props
import { Timeline } from 'g2-kit/charts'
g2.draw('left', Timeline, {
"start": 8,
"end": 18,
"now": 13.5,
"events": [
{
"at": 9,
"end": 10.5,
"label": "Standup",
"lane": 0
},
{
"at": 11,
"end": 12,
"label": "Review",
"lane": 1
},
{
"at": 14,
"end": 16,
"label": "Focus",
"lane": 0
},
{
"at": 12.5,
"label": "Lunch",
"lane": 1,
"marker": "dot"
}
],
"ticks": [
[
8,
"8:00"
],
[
12,
"12:00"
],
[
18,
"18:00"
]
]
})
WaffleChart · 288×144 · P2 · ink 26%
props
import { WaffleChart } from 'g2-kit/charts'
g2.draw('left', WaffleChart, {
"parts": [
{
"label": "Done",
"value": 62
},
{
"label": "Doing",
"value": 23
},
{
"label": "Todo",
"value": 15
}
]
})
ScatterChart · 288×144 · P2 · ink 5%
props
import { ScatterChart } from 'g2-kit/charts'
g2.draw('left', ScatterChart, {
"title": "Sleep vs steps",
"series": [
{
"points": [
[
4,
5.5
],
[
6,
6.2
],
[
7,
6.8
],
[
9,
7.1
],
[
10,
7.6
],
[
12,
7.4
],
[
13,
8.1
],
[
8,
6.1
],
[
5,
6.4
]
]
},
{
"points": [
[
3,
7.5
],
[
5,
7.2
],
[
6,
6.8
],
[
9,
6
],
[
11,
5.9
]
]
}
],
"trend": true,
"xLabel": "k steps"
})
Histogram · 288×144 · P2 · ink 26%
props
import { Histogram } from 'g2-kit/charts'
g2.draw('left', Histogram, {
"title": "Commute (min)",
"values": [
22,
25,
31,
28,
24,
35,
41,
27,
26,
29,
33,
30,
23,
38,
45,
27,
29,
31,
26,
28
],
"mark": 33
})
BoxPlot · 288×144 · P2 · ink 4%
props
import { BoxPlot } from 'g2-kit/charts'
g2.draw('left', BoxPlot, {
"title": "Response (ms)",
"boxes": [
{
"label": "API",
"min": 120,
"q1": 145,
"median": 160,
"q3": 195,
"max": 260
},
{
"label": "CDN",
"min": 60,
"q1": 71.25,
"median": 77.5,
"q3": 91.25,
"max": 130
},
{
"label": "DB",
"min": 200,
"q1": 270,
"median": 320,
"q3": 400,
"max": 600
}
]
})
CandlestickChart · 288×144 · P2 · ink 4%
props
import { CandlestickChart } from 'g2-kit/charts'
g2.draw('left', CandlestickChart, {
"title": "ACME",
"candles": [
{
"open": 10,
"high": 12,
"low": 9,
"close": 11.5,
"label": "Mon"
},
{
"open": 11.5,
"high": 13,
"low": 11,
"close": 12.4
},
{
"open": 12.4,
"high": 12.8,
"low": 10.5,
"close": 10.9
},
{
"open": 10.9,
"high": 11.6,
"low": 10.2,
"close": 11.2
},
{
"open": 11.2,
"high": 14,
"low": 11,
"close": 13.6,
"label": "Fri"
}
]
})Legends & encodings
Legend · 288×144 · P1 · ink 3%
props
import { Legend } from 'g2-kit/charts'
g2.draw('left', Legend, {
"items": [
{
"label": "Solid / dot",
"dash": "solid",
"marker": "dot"
},
{
"label": "Dashed / square",
"dash": "dashed",
"marker": "square"
},
{
"label": "Dotted / triangle",
"dash": "dotted",
"marker": "triangle"
},
{
"label": "Hatch fill",
"paint": {
"pattern": "hatch",
"level": 15
}
},
{
"label": "Dots fill",
"paint": {
"pattern": "dots",
"level": 15
}
},
{
"label": "Cross-hatch fill",
"paint": {
"pattern": "crossHatch",
"level": 15
}
}
]
})
Legend · 288×144 · P1 · ink 3%
props
import { Legend } from 'g2-kit/charts'
g2.draw('left', Legend, {
"items": [
{
"label": "Right spot",
"mark": "filled",
"glyph": "A"
},
{
"label": "Wrong spot",
"mark": "ring",
"glyph": "B"
},
{
"label": "Not in word",
"mark": "strike",
"glyph": "C"
}
],
"large": true,
"valign": "middle"
})Input controls
Carousel · 288×64 · P0 · ink 5%
props
import { Carousel } from 'g2-kit/widgets'
g2.draw('left', Carousel, {
"items": [
"DEL",
"ENTER",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
],
"index": 5
})
Carousel · 288×64 · P0 · ink 6%
props
import { Carousel } from 'g2-kit/widgets'
g2.draw('left', Carousel, {
"items": [
"Coffee",
"Tea",
"Water",
"Juice",
"Soda"
],
"index": 1,
"wrap": false
})
Carousel · 288×64 · P0 · ink 5%
props
import { Carousel } from 'g2-kit/widgets'
g2.draw('left', Carousel, {
"items": [
{
"icon": "home"
},
{
"icon": "music"
},
{
"icon": "clock"
},
{
"icon": "gear"
},
{
"icon": "mail"
},
{
"icon": "search"
}
],
"index": 2
})
Carousel · 144×144 · P0 · ink 7%
props
import { Carousel } from 'g2-kit/widgets'
g2.draw('left', Carousel, {
"items": [
"5 min",
"10 min",
"15 min",
"25 min",
"45 min"
],
"index": 3,
"orientation": "vertical",
"wrap": false
})
Button · 120×36 · P0 · ink 20%
props
import { Button } from 'g2-kit/widgets'
g2.draw('left', Button, {
"label": "Refresh",
"icon": "refresh",
"state": "focused"
})
ButtonRow · 288×44 · P0 · ink 34%
props
import { ButtonRow } from 'g2-kit/widgets'
g2.draw('left', ButtonRow, {
"buttons": [
{
"label": "Normal"
},
{
"label": "Focus"
},
{
"label": "Press"
},
{
"label": "On",
"active": true
},
{
"label": "Off",
"disabled": true
}
],
"focus": 1,
"pressed": 2
})
ButtonRow · 288×44 · P0 · ink 10%
props
import { ButtonRow } from 'g2-kit/widgets'
g2.draw('left', ButtonRow, {
"buttons": [
{
"icon": "play",
"label": "Play"
},
{
"icon": "pause"
},
{
"icon": "refresh",
"label": "Again"
}
],
"focus": 0,
"variant": "pill"
})
Toggle · 160×36 · P0 · ink 26%
props
import { Toggle } from 'g2-kit/widgets'
g2.draw('left', Toggle, {
"on": true,
"label": "Wi-Fi",
"focused": true
})
Toggle · 160×36 · P0 · ink 10%
props
import { Toggle } from 'g2-kit/widgets'
g2.draw('left', Toggle, {
"on": false,
"label": "Alerts"
})
SegmentedControl · 288×36 · P1 · ink 34%
props
import { SegmentedControl } from 'g2-kit/widgets'
g2.draw('left', SegmentedControl, {
"options": [
"Day",
"Week",
"Month"
],
"selected": 1,
"focused": true
})
Slider · 288×56 · P1 · ink 14%
props
import { Slider } from 'g2-kit/widgets'
g2.draw('left', Slider, {
"label": "Brightness",
"value": 60,
"step": 10,
"focused": true
})
Slider · 288×56 · P1 · ink 11%
props
import { Slider } from 'g2-kit/widgets'
g2.draw('left', Slider, {
"label": "Volume",
"value": 35,
"step": 5,
"editing": true
})
Slider · 72×144 · P1 · ink 6%
props
import { Slider } from 'g2-kit/widgets'
g2.draw('left', Slider, {
"label": "Temp",
"value": 21,
"min": 16,
"max": 28,
"orientation": "vertical"
})
Roller · 288×120 · P1 · ink 6%
props
import { Roller } from 'g2-kit/widgets'
g2.draw('left', Roller, {
"columns": [
{
"values": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
],
"index": 4
},
{
"values": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
],
"index": 0
},
{
"values": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
],
"index": 7
},
{
"values": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
],
"index": 1
}
],
"focus": 2,
"editing": true,
"label": "Enter PIN"
})
TimePicker · 288×120 · P1 · ink 4%
props
import { TimePicker } from 'g2-kit/widgets'
g2.draw('left', TimePicker, {
"hours": 7,
"minutes": 30,
"focus": 1,
"label": "Alarm",
"minuteStep": 5
})
DatePicker · 288×120 · P1 · ink 9%
props
import { DatePicker } from 'g2-kit/widgets'
g2.draw('left', DatePicker, {
"year": 2026,
"month": 9,
"day": 29,
"focus": 0,
"editing": true
})
Checklist · 288×144 · P1 · ink 4%
props
import { Checklist } from 'g2-kit/widgets'
g2.draw('left', Checklist, {
"items": [
{
"label": "Milk",
"done": true
},
{
"label": "Eggs",
"done": true
},
{
"label": "Coffee beans"
},
{
"label": "Bread"
},
{
"label": "Tomatoes"
},
{
"label": "Olive oil"
},
{
"label": "Basil"
}
],
"focus": 2
})
StatusKeyboard · 288×120 · P1 · ink 17%
props
import { StatusKeyboard } from 'g2-kit/widgets'
g2.draw('left', StatusKeyboard, {
"marks": {
"A": "filled",
"R": "filled",
"E": "ring",
"S": "strike",
"T": "strike",
"O": "ring",
"L": "strike",
"I": "strike"
},
"focus": "N"
})
GridKeyboard · 288×144 · P1 · ink 16%
props
import { GridKeyboard } from 'g2-kit/widgets'
g2.draw('left', GridKeyboard, {
"row": 1,
"col": 3,
"text": "HELLO WOR"
})
GridKeyboard · 288×144 · P1 · ink 13%
props
import { GridKeyboard } from 'g2-kit/widgets'
g2.draw('left', GridKeyboard, {
"rows": [
[
".,?",
"ABC",
"DEF"
],
[
"GHI",
"JKL",
"MNO"
],
[
"PQRS",
"TUV",
"WXYZ"
],
[
"SPACE",
"DEL",
"OK"
]
],
"row": 2,
"col": -1
})
TextKeyboardFrames · 576×144 · P1 · ink 4%Drawn once; the letters and focus are firmware text on top.
props
import { TextKeyboardFrames } from 'g2-kit/widgets'
g2.draw('left', TextKeyboardFrames, {
"grid": {
"layout": {
"keyboardLayout": {}
},
"cols": 28,
"lines": 4,
"views": [
[
{
"key": 0,
"line": 0,
"start": 4,
"len": 1
},
{
"key": 1,
"line": 0,
"start": 6,
"len": 1
},
{
"key": 2,
"line": 0,
"start": 8,
"len": 1
},
{
"key": 3,
"line": 0,
"start": 10,
"len": 1
},
{
"key": 4,
"line": 0,
"start": 12,
"len": 1
},
{
"key": 5,
"line": 0,
"start": 14,
"len": 1
},
{
"key": 6,
"line": 0,
"start": 16,
"len": 1
},
{
"key": 7,
"line": 0,
"start": 18,
"len": 1
},
{
"key": 8,
"line": 0,
"start": 20,
"len": 1
},
{
"key": 9,
"line": 0,
"start": 22,
"len": 1
},
{
"key": 10,
"line": 1,
"start": 5,
"len": 1
},
{
"key": 11,
"line": 1,
"start": 7,
"len": 1
},
{
"key": 12,
"line": 1,
"start": 9,
"len": 1
},
{
"key": 13,
"line": 1,
"start": 11,
"len": 1
},
{
"key": 14,
"line": 1,
"start": 13,
"len": 1
},
{
"key": 15,
"line": 1,
"start": 15,
"len": 1
},
{
"key": 16,
"line": 1,
"start": 17,
"len": 1
},
{
"key": 17,
"line": 1,
"start": 19,
"len": 1
},
{
"key": 18,
"line": 1,
"start": 21,
"len": 1
},
{
"key": 19,
"line": 2,
"start": 7,
"len": 1
},
{
"key": 20,
"line": 2,
"start": 9,
"len": 1
},
{
"key": 21,
"line": 2,
"start": 11,
"len": 1
},
{
"key": 22,
"line": 2,
"start": 13,
"len": 1
},
{
"key": 23,
"line": 2,
"start": 15,
"len": 1
},
{
"key": 24,
"line": 2,
"start": 17,
"len": 1
},
{
"key": 25,
"line": 2,
"start": 19,
"len": 1
},
{
"key": 26,
"line": 3,
"start": 6,
"len": 1
},
{
"key": 27,
"line": 3,
"start": 8,
"len": 4
},
{
"key": 28,
"line": 3,
"start": 13,
"len": 3
},
{
"key": 29,
"line": 3,
"start": 17,
"len": 1
},
{
"key": 30,
"line": 3,
"start": 19,
"len": 2
}
],
[
{
"key": 0,
"line": 0,
"start": 4,
"len": 1
},
{
"key": 1,
"line": 0,
"start": 6,
"len": 1
},
{
"key": 2,
"line": 0,
"start": 8,
"len": 1
},
{
"key": 3,
"line": 0,
"start": 10,
"len": 1
},
{
"key": 4,
"line": 0,
"start": 12,
"len": 1
},
{
"key": 5,
"line": 0,
"start": 14,
"len": 1
},
{
"key": 6,
"line": 0,
"start": 16,
"len": 1
},
{
"key": 7,
"line": 0,
"start": 18,
"len": 1
},
{
"key": 8,
"line": 0,
"start": 20,
"len": 1
},
{
"key": 9,
"line": 0,
"start": 22,
"len": 1
},
{
"key": 10,
"line": 1,
"start": 4,
"len": 1
},
{
"key": 11,
"line": 1,
"start": 6,
"len": 1
},
{
"key": 12,
"line": 1,
"start": 8,
"len": 1
},
{
"key": 13,
"line": 1,
"start": 10,
"len": 1
},
{
"key": 14,
"line": 1,
"start": 12,
"len": 1
},
{
"key": 15,
"line": 1,
"start": 14,
"len": 1
},
{
"key": 16,
"line": 1,
"start": 16,
"len": 1
},
{
"key": 17,
"line": 1,
"start": 18,
"len": 1
},
{
"key": 18,
"line": 1,
"start": 20,
"len": 1
},
{
"key": 19,
"line": 1,
"start": 22,
"len": 1
},
{
"key": 20,
"line": 2,
"start": 4,
"len": 1
},
{
"key": 21,
"line": 2,
"start": 6,
"len": 1
},
{
"key": 22,
"line": 2,
"start": 8,
"len": 1
},
{
"key": 23,
"line": 2,
"start": 10,
"len": 1
},
{
"key": 24,
"line": 2,
"start": 12,
"len": 1
},
{
"key": 25,
"line": 2,
"start": 14,
"len": 1
},
{
"key": 26,
"line": 2,
"start": 16,
"len": 1
},
{
"key": 27,
"line": 2,
"start": 18,
"len": 1
},
{
"key": 28,
"line": 2,
"start": 20,
"len": 1
},
{
"key": 29,
"line": 2,
"start": 22,
"len": 1
},
{
"key": 30,
"line": 3,
"start": 6,
"len": 1
},
{
"key": 31,
"line": 3,
"start": 8,
"len": 3
},
{
"key": 32,
"line": 3,
"start": 12,
"len": 3
},
{
"key": 33,
"line": 3,
"start": 16,
"len": 1
},
{
"key": 34,
"line": 3,
"start": 18,
"len": 2
}
]
]
},
"origin": {
"x": 8,
"y": 30
}
})
Keyboard · 288×144 · P1 · ink 15%
props
import { Keyboard } from 'g2-kit/widgets'
g2.draw('left', Keyboard, {
"layout": {
"keyboardLayout": {}
},
"group": 1
})
Keyboard · 288×144 · P1 · ink 14%
props
import { Keyboard } from 'g2-kit/widgets'
g2.draw('left', Keyboard, {
"layout": {
"keyboardLayout": {}
},
"group": 0,
"key": 4,
"shift": "once"
})
Keyboard · 288×144 · P1 · ink 16%
props
import { Keyboard } from 'g2-kit/widgets'
g2.draw('left', Keyboard, {
"layout": {
"keyboardLayout": {}
},
"view": 1,
"group": 3,
"key": 1
})
Keyboard · 288×144 · P1 · ink 15%
props
import { Keyboard } from 'g2-kit/widgets'
g2.draw('left', Keyboard, {
"layout": {
"keyboardLayout": {
"letters": "abc",
"scan": "columns",
"punctuation": ".,",
"actions": [
"caps",
"symbols",
"space",
"delete",
"submit"
],
"labels": {
"submit": "Send"
}
}
},
"group": 2,
"shift": "lock"
})
Keyboard · 576×144 · P1 · ink 11%
props
import { Keyboard } from 'g2-kit/widgets'
g2.draw('left', Keyboard, {
"layout": {
"keyboardLayout": {
"panels": "side"
}
},
"group": 2,
"key": 3
})
Keyboard · 288×288 · P1 · ink 15%
props
import { Keyboard } from 'g2-kit/widgets'
g2.draw('left', Keyboard, {
"layout": {
"keyboardLayout": {
"panels": "stack",
"digits": "row",
"actions": [
"shift",
"space",
"delete",
"cancel",
"submit"
]
}
},
"group": 5,
"text": "Hello, world"
})
Rating · 160×32 · P2 · ink 21%
props
import { Rating } from 'g2-kit/widgets'
g2.draw('left', Rating, {
"value": 3.5,
"focused": true
})Text, feedback & chrome
ProgressBar · 260×40 · P0 · ink 24%
props
import { ProgressBar } from 'g2-kit/widgets'
g2.draw('left', ProgressBar, {
"value": 0.62,
"label": "Download"
})
ProgressBar · 260×40 · P0 · ink 25%
props
import { ProgressBar } from 'g2-kit/widgets'
g2.draw('left', ProgressBar, {
"value": 7,
"max": 10,
"segments": 10,
"label": "Reps",
"valueText": "7/10"
})
BigText · 288×144 · P0 · ink 14%
props
import { BigText } from 'g2-kit/widgets'
g2.draw('left', BigText, {
"text": "Turn left in 200 m"
})
BigText · 144×96 · P0 · ink 10%
props
import { BigText } from 'g2-kit/widgets'
g2.draw('left', BigText, {
"text": "GO!"
})
Toast · 288×48 · P1 · ink 16%
props
import { Toast } from 'g2-kit/widgets'
g2.draw('left', Toast, {
"text": "Synced 3 new items",
"remaining": 0.6
})
Toast · 288×48 · P1 · ink 11%
props
import { Toast } from 'g2-kit/widgets'
g2.draw('left', Toast, {
"text": "Saved",
"kind": "success"
})
Toast · 288×48 · P1 · ink 9%
props
import { Toast } from 'g2-kit/widgets'
g2.draw('left', Toast, {
"text": "Battery low: 15%",
"kind": "warning"
})
Toast · 288×48 · P1 · ink 95%
props
import { Toast } from 'g2-kit/widgets'
g2.draw('left', Toast, {
"text": "Upload failed. Retrying…",
"kind": "error"
})
Modal · 288×144 · P1 · ink 10%
props
import { Modal } from 'g2-kit/widgets'
g2.draw('left', Modal, {
"title": "Delete note?",
"body": "This removes it from all devices. It cannot be undone.",
"buttons": [
"Cancel",
"Delete"
],
"focus": 0,
"icon": "trash"
})
Tabs · 288×24 · P1 · ink 15%
props
import { Tabs } from 'g2-kit/widgets'
g2.draw('left', Tabs, {
"tabs": [
"Today",
"Week",
"Month",
"Year"
],
"active": 1
})
Tabs · 144×24 · P1 · ink 50%
props
import { Tabs } from 'g2-kit/widgets'
g2.draw('left', Tabs, {
"tabs": [
"Map",
"List"
],
"active": 0,
"variant": "boxed"
})
PaginationDots · 96×16 · P1 · ink 13%
props
import { PaginationDots } from 'g2-kit/widgets'
g2.draw('left', PaginationDots, {
"count": 5,
"active": 2
})
ScrollIndicator · 6×144 · P1 · ink 18%
props
import { ScrollIndicator } from 'g2-kit/widgets'
g2.draw('left', ScrollIndicator, {
"total": 40,
"visible": 8,
"offset": 12
})
StatusBar · 288×20 · P1 · ink 16%
props
import { StatusBar } from 'g2-kit/widgets'
g2.draw('left', StatusBar, {
"time": "09:41",
"battery": 0.72,
"signal": 3,
"slots": [
{
"icon": "bell",
"text": "2"
},
{
"icon": "music"
}
],
"title": "Home"
})
HudFrame · 288×144 · P1 · ink 1%
props
import { HudFrame } from 'g2-kit/widgets'
g2.draw('left', HudFrame, {
"title": "Target",
"style": "brackets"
})
HudFrame · 288×144 · P1 · ink 10%
props
import { HudFrame } from 'g2-kit/widgets'
g2.draw('left', HudFrame, {
"title": "System",
"style": "notched",
"titleStyle": "bar"
})
Ticker · 288×24 · P1 · ink 10%Each frame is one image send (~350 ms on glasses).
props
import { Ticker } from 'g2-kit/widgets'
g2.draw('left', Ticker, {
"text": "AAPL 232.1 +1.2% MSFT 511.9 -0.4% NVDA 184.2 +2.9%",
"offset": 40
})
Table · 288×144 · P2 · ink 19%
props
import { Table } from 'g2-kit/widgets'
g2.draw('left', Table, {
"columns": [
{
"label": "Stop",
"weight": 2
},
{
"label": "Line"
},
{
"label": "Min",
"align": "right"
}
],
"rows": [
[
"Central Station",
"U2",
3
],
[
"Market Square",
"14",
7
],
[
"Harbour",
"S1",
12
],
[
"Old Town Hall",
"4",
15
],
[
"University",
"U2",
21
],
[
"Airport",
"S8",
34
]
],
"focus": 1,
"font": "body"
})
Card · 144×96 · P2 · ink 15%
props
import { Card } from 'g2-kit/widgets'
g2.draw('left', Card, {
"title": "Heart rate",
"value": "72",
"icon": "heart",
"footnote": "resting",
"focused": true
})
Badge · 96×16 · P2 · ink 30%
props
import { Badge } from 'g2-kit/widgets'
g2.draw('left', Badge, {
"text": "LIVE",
"variant": "solid",
"icon": "record"
})
Spinner · 144×32 · P2 · ink 7%Each frame is one send; advance slowly.
props
import { Spinner } from 'g2-kit/widgets'
g2.draw('left', Spinner, {
"frame": 1,
"label": "Syncing"
})Glanceable data faces
AnalogClock · 144×144 · P1 · ink 6%
props
import { AnalogClock } from 'g2-kit/widgets'
g2.draw('left', AnalogClock, {
"hours": 10,
"minutes": 8,
"seconds": 36
})
AnalogClock · 144×144 · P1 · ink 8%
props
import { AnalogClock } from 'g2-kit/widgets'
g2.draw('left', AnalogClock, {
"hours": 3,
"minutes": 45,
"ticks": "numbers",
"label": "Tokyo"
})
TimerRing · 144×144 · P1 · ink 22%
props
import { TimerRing } from 'g2-kit/widgets'
g2.draw('left', TimerRing, {
"remaining": 1062,
"total": 1500,
"label": "Focus"
})
CompassStrip · 288×48 · P1 · ink 4%
props
import { CompassStrip } from 'g2-kit/widgets'
g2.draw('left', CompassStrip, {
"heading": 62,
"markers": [
{
"bearing": 95
},
{
"bearing": 250
}
]
})
TurnArrow · 288×96 · P1 · ink 7%
props
import { TurnArrow } from 'g2-kit/widgets'
g2.draw('left', TurnArrow, {
"direction": "right",
"distance": "200 m",
"street": "Main Street"
})
TurnArrow · 288×96 · P1 · ink 6%
props
import { TurnArrow } from 'g2-kit/widgets'
g2.draw('left', TurnArrow, {
"direction": "slightLeft",
"distance": "1.2 km",
"street": "A7 north"
})
TurnArrow · 288×96 · P1 · ink 8%
props
import { TurnArrow } from 'g2-kit/widgets'
g2.draw('left', TurnArrow, {
"direction": "uturn",
"distance": "50 m"
})
WeatherGlyph · 288×96 · P2 · ink 11%
props
import { WeatherGlyph } from 'g2-kit/widgets'
g2.draw('left', WeatherGlyph, {
"condition": "partly",
"temp": "18°",
"label": "Berlin",
"hiLo": "H 21° L 12°"
})
WeatherGlyph · 144×72 · P2 · ink 19%
props
import { WeatherGlyph } from 'g2-kit/widgets'
g2.draw('left', WeatherGlyph, {
"condition": "rain",
"temp": "9°"
})Game kit
GridBoard · 144×144 · P1 · ink 23%
props
import { GridBoard } from 'g2-kit/widgets'
g2.draw('left', GridBoard, {
"cells": [
[
{
"glyph": "C",
"mark": "strike"
},
{
"glyph": "R",
"mark": "ring"
},
{
"glyph": "A",
"mark": "filled"
},
{
"glyph": "N",
"mark": "strike"
},
{
"glyph": "E",
"mark": "ring"
}
],
[
{
"glyph": "B",
"mark": "strike"
},
{
"glyph": "E",
"mark": "filled"
},
{
"glyph": "A",
"mark": "filled"
},
{
"glyph": "R",
"mark": "filled"
},
{
"glyph": "D",
"mark": "strike"
}
],
[
{
"glyph": "S",
"mark": "focus"
},
{
"glyph": "P"
},
null,
null,
null
],
[
null,
null,
null,
null,
null
]
]
})
GridBoard · 144×144 · P1 · ink 12%
props
import { GridBoard } from 'g2-kit/widgets'
g2.draw('left', GridBoard, {
"cells": [
[
{
"glyph": "X"
},
{
"glyph": "O"
},
null
],
[
null,
{
"glyph": "X"
},
null
],
[
{
"glyph": "O"
},
null,
null
]
],
"focus": [
2,
2
]
})
GridBoard · 144×144 · P1 · ink 25%
props
import { GridBoard } from 'g2-kit/widgets'
g2.draw('left', GridBoard, {
"cells": [
[
{
"glyph": "2"
},
null,
{
"glyph": "4"
},
null
],
[
{
"glyph": "8",
"mark": "ring"
},
{
"glyph": "16",
"mark": "ring"
},
null,
null
],
[
{
"glyph": "128",
"mark": "filled"
},
{
"glyph": "32",
"mark": "ring"
},
{
"glyph": "4"
},
null
],
[
{
"glyph": "512",
"mark": "filled"
},
{
"glyph": "64",
"mark": "ring"
},
{
"glyph": "2"
},
{
"glyph": "2"
}
]
],
"gap": 3
})
ScoreHud · 288×24 · P1 · ink 11%
props
import { ScoreHud } from 'g2-kit/widgets'
g2.draw('left', ScoreHud, {
"score": 1280,
"best": 4096,
"streak": 3,
"lives": {
"current": 2,
"max": 3
}
})
ScoreHud · 144×96 · P1 · ink 6%
props
import { ScoreHud } from 'g2-kit/widgets'
g2.draw('left', ScoreHud, {
"score": 42,
"best": 97,
"lives": {
"current": 3,
"max": 5
},
"layout": "stack"
})
Dice · 288×64 · P2 · ink 32%
props
import { Dice } from 'g2-kit/widgets'
g2.draw('left', Dice, {
"values": [
3,
6,
1,
5,
2
],
"held": [
false,
true,
false,
true,
false
],
"focus": 2
})
HealthBar · 160×16 · P2 · ink 28%
props
import { HealthBar } from 'g2-kit/widgets'
g2.draw('left', HealthBar, {
"value": 64,
"max": 100,
"icon": "heart"
})Filled vs outline theme surface: 'outline': ink 24% → 14% over these 17 samples
Every lit pixel sits between the wearer and the world. With createTheme({ surface: 'outline' }) (or outlineTheme),
components draw frames and light textures where they would paint solid blocks. Ink is the share of lit pixels; the budget is 25%.
filled · ink 32%
outline · ink 16%BarChart
filled · ink 15%
outline · ink 7%BarChart
filled · ink 20%
outline · ink 14%BarChart
filled · ink 36%
outline · ink 20%MultiBarChart
filled · ink 31%
outline · ink 12%MultiBarChart
filled · ink 34%
outline · ink 24%ButtonRow
filled · ink 26%
outline · ink 15%Toggle
filled · ink 24%
outline · ink 14%ProgressBar
filled · ink 25%
outline · ink 15%ProgressBar
filled · ink 34%
outline · ink 22%SegmentedControl
filled · ink 14%
outline · ink 13%Keyboard
filled · ink 16%
outline · ink 14%Keyboard
filled · ink 15%
outline · ink 14%Keyboard
filled · ink 11%
outline · ink 10%Keyboard
filled · ink 95%
outline · ink 17%Toast
filled · ink 50%
outline · ink 21%Tabs
filled · ink 26%
outline · ink 12%HistogramText components strings for firmware text containers: no image send (~60 ms vs ~260 ms per update on G2)
Shown in a monospace font here; the glasses use their own proportional firmware font. Put them in any text container with g2.textArea(name).draw(key, Component, props).
Q W E R T Y U I O P A S D[F]G H J K L Z X C V B N M ▲ ?123 ___ ◀ OK
TextKeyboardFullwidth text on the G2 grid over TextKeyboardFrames; a focus move is one text update.[q w e r t y u i o p] a s d f g h j k l z x c v b n m △ ?123 ___ ◀ OK
TextKeyboardSyncing ↗
TextSpinnerFrames ↑ ↗ → ↘ ↓ ↙ ← ↖; one text update per frame.Loading ▶
TextSpinnerSyncing /
TextSpinnerDownload ━━━━━━━━──────────── 40%
TextProgress█████▏────── 43%
TextProgressReps ━━━━━━━─── 7/10
TextProgressDownload [########------------] 40%
TextProgress▷ Brightness ━━━━━━━●──── 60
TextSlider▶ Volume ━━━━●─────── 35
TextSlider▶ Volume ━━━━◆────── 40
TextSlidereditStyle: knob keeps the line still while editing.▶ Temp ◀ ━━━━━●────── ▶ 21°C
TextSlider▷ Resume ▶ New game ▷ Settings ▷ Quit
TextMenuThe "fake buttons" pattern: a menu with no image.▷ ○ Bread ▲ ▶ ○ Coffee ▷ ● Basil ▼
TextMenu▶ Wi-Fi ● On
TextToggle▷ Alerts ○ Off
TextToggle○ Hold to delete ────────────
TextHoldDrive it from HoldToConfirm; ~10 updates/s as text vs ~2 as an image.● Hold to delete ━━━━━━━─────
TextHold● Deleted
TextHold[~] Hold to delete [#######-----]
TextHold▲ Battery low
TextToastKinds by shape: ▶ info, ● success, ▲ warning, ■ error.■ Sync failed Tap to retry
TextToast[+] Saved
TextToast12:45 │ Steps 8 214 │ Bat 82%
TextStatusLineHeart rate 128 bpm ↑ +4
TextReadoutLive values as text; pair with a tile drawn once.▶ Pace 5.25 min/km ↓ -0.10
TextReadoutp in 5 min, room 4B. Then: desig
TextTickerA window that moves one character per update.