gdev-html-report
v2.1.0
Published
GDEV corporate HTML report component library v2 — dark/light themes, 32 components
Readme
GDEV UI
Corporate component library for GDEV HTML reports and dashboards.
One <script> tag gives you the full GDEV design system: Anton + Roboto Condensed typography, #FF4E02 accent color system, dark/light themes, 32 ready-to-use components, and the GDEV logo — with zero build steps, zero CSS files, and zero configuration.
Author: Dmitry Filippov
Install
CDN (recommended)
<script src="https://cdn.jsdelivr.net/npm/gdev-html-report/gdev-html-report.js"></script>npm
npm install gdev-html-reportSelf-hosted
Download gdev-html-report.js (~178KB) and serve from any static host.
Quick Start
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Report</title>
<script src="https://cdn.jsdelivr.net/npm/gdev-html-report/gdev-html-report.js"></script>
</head>
<body>
<script>
GDEV.init({ skill: 'ANALYTICS' });
var G = GDEV.html;
var content = '';
content += G.reportHeader({ label: 'Q4 2025', title: 'REVENUE ANALYSIS' });
content += G.metricsGrid([
{ label: 'Revenue', value: '$2.4M', status: 'good', sub: '+18% vs Q3' },
{ label: 'Churn', value: '3.2%', status: 'warning', sub: 'Target: <2%' },
{ label: 'NPS', value: '72', status: 'good', sub: 'Up from 58' }
]);
document.body.insertAdjacentHTML('beforeend', G.container(content));
</script>
</body>
</html>That's a complete, working report. No external CSS. No font files. No build step.
What's Inside (~178KB)
The library bundles everything into a single JS file:
| Asset | Details | |-------|---------| | Anton font | v2.300 with full Cyrillic support, embedded as base64 woff2. Google Fonts CDN serves v2.000 which lacks Cyrillic — this is the only reliable way to get Anton + кириллица. | | Roboto Condensed | Loaded from Google Fonts CDN at init time. | | Full CSS design system | Variables, reset, all component styles, responsive breakpoints, dark + light themes, print styles. | | GDEV logo | Inline SVG, auto-themed (adapts to dark/light). | | 32 component generators | HTML string builders — compose and inject once. | | Utility functions | Theme toggle, print, collapsible block toggle, score classifier, tab switcher, chart hover handlers, ID generator. |
Initialization
GDEV.init(options)
Call once, before using any components. Injects CSS, loads fonts, optionally creates the page header.
GDEV.init({
skill: 'NEGOTIATOR', // Creates sticky header with GDEV logo + this label
theme: 'dark', // 'dark' (default) or 'light'
css: '.custom { ... }' // Extra CSS to inject (optional)
});| Option | Type | Default | Description |
|--------|------|---------|-------------|
| skill | string | — | If set, auto-creates the sticky page header with GDEV logo, skill name, theme toggle button, and print button. |
| theme | 'dark' | 'light' | 'dark' | Initial color theme. Dark: #0C0C0E background. Light: #F5F4F0 background. |
| css | string | — | Additional CSS rules injected after the design system. Use for skill-specific overrides. |
What init() does internally:
- Injects
<link>for Roboto Condensed from Google Fonts - Adds preconnect hints for
fonts.googleapis.comandfonts.gstatic.com - Creates a
<style>element with the entire design system CSS (including the base64 Anton@font-face) - Applies light theme class to
<html>iftheme: 'light' - Injects extra CSS if provided
- Inserts page header into
<body>ifskillis provided
Calling init() more than once is safe — it's a no-op after the first call.
Component API
All components live under GDEV.html. Every method returns an HTML string. The pattern is always the same: build strings, then inject once.
var G = GDEV.html;
// Build
var content = '';
content += G.reportHeader({ title: 'MY REPORT' });
content += G.metricsGrid([...]);
content += G.block({ title: 'Details', content: G.field('Key', 'Value') });
// Inject once
document.body.insertAdjacentHTML('beforeend', G.container(content));Layout Components
G.header(skillName)
Page header with GDEV logo, skill label, theme toggle, and print button. Sticky, z-index: 100.
Note: You don't need to call this directly —
GDEV.init({ skill: '...' })creates it automatically.
G.header('ANALYTICS')G.container(html)
Max-width wrapper (855px) with responsive padding. Wrap your entire report content in this.
G.container(content)G.grid2(leftHtml, rightHtml)
Two-column responsive grid. Collapses to single column below 860px.
G.grid2(
G.card({ title: 'Left Card', desc: 'Content here' }),
G.card({ title: 'Right Card', desc: 'Content here' })
)G.grid3(a, b, c)
Three-column responsive grid.
G.grid3(G.field('A', '1'), G.field('B', '2'), G.field('C', '3'))G.grid4(a, b, c, d)
Four-column responsive grid.
G.grid5(a, b, c, d, e)
Five-column responsive grid.
G.stack(items, gap?)
Vertical flex container. Default gap: 12px. Accepts an array of HTML strings or a single concatenated string.
G.stack([
G.field('First', 'Value'),
G.field('Second', 'Value'),
G.field('Third', 'Value')
], '16px')G.divider()
Thin horizontal line (0.5px, --border-default color).
G.divider()Report Structure
G.eyebrow(text)
Small pill badge with an orange dot. Used at the top of reports for status indicators or labels.
G.eyebrow('Live · Updated 2 min ago')G.reportHeader(options)
Main report title block. Appears once, at the top.
G.reportHeader({
label: 'Weekly Report', // Small orange label above title
title: 'TEAM PERFORMANCE', // Large Anton heading (auto-uppercase)
subtitle: 'Week 48, Q4 2025' // Gray subtitle below
})| Param | Type | Required | Description |
|-------|------|----------|-------------|
| label | string | no | Orange uppercase micro-label (--accent color, 11px) |
| title | string | no | Main heading (Anton font, 32px, uppercase) |
| subtitle | string | no | Gray description line (Roboto Condensed, 16px) |
G.section(options)
Section wrapper with label, title, description, and inner content. Use to group related components.
G.section({
label: 'Section 01',
title: 'Key Findings',
desc: 'Summary of the most critical discoveries this quarter.',
content: G.metricsGrid([...])
})| Param | Type | Required | Description |
|-------|------|----------|-------------|
| label | string | no | Section number or category (orange-dim, 11px, uppercase) |
| title | string | no | Section heading (Anton, 24px) |
| desc | string | no | Description paragraph (max-width 540px) |
| content | string | no | HTML string of inner components |
| id | string | no | DOM id for anchor links. Auto-generated from title or label if omitted (same algorithm as G.toc). |
TOC integration:
G.tocauto-generates the scroll targetidfrom item text using the same slug algorithm assectionauto-generates itsid. SoG.toc(['Key Findings'])andG.section({ title: 'Key Findings', ... })connect automatically with no extra config.
Data Display
G.metricsGrid(metrics[])
Responsive flex row of metric cards. Cards auto-size, min-width 140px.
G.metricsGrid([
{ label: 'Revenue', value: '$2.4M', status: 'good', sub: '+18% vs Q3', prev: '$2.0M' },
{ label: 'Churn', value: '3.2%', status: 'warning', sub: 'Target: <2%' },
{ label: 'NPS', value: '34', status: 'critical' },
{ label: 'Users', value: '14K', status: 'accent' }
])| Item Param | Type | Required | Description |
|-----------|------|----------|-------------|
| label | string | yes | Uppercase label above the number |
| value | string | yes | The big number (Anton font, 36px) |
| status | string | no | Color: 'good' (green), 'warning' (yellow), 'critical' (red), 'accent' (orange). Omit for default white. |
| sub | string | no | Small text below the number |
| prev | string | no | Previous value shown below sub |
G.field(label, value, variant?)
Left-bordered information field. The core building block for displaying labeled data inside blocks and cards. Returns empty string if value is falsy.
G.field('Situation', 'Market share declining in APAC region.')
G.field('Risk', 'Immediate action required.', 'warning')
G.field('Blocked', 'No budget approved.', 'critical')
G.field('Resolved', 'Contract signed.', 'success')
G.field('Note', 'For reference only.', 'neutral')| Param | Type | Required | Description |
|-------|------|----------|-------------|
| label | string | yes | Uppercase label (11px, faint) |
| value | string | yes | Content text (15px, bright). Returns empty string if falsy. |
| variant | string | no | Border color: 'warning' (yellow), 'critical' (red), 'success' (green), 'neutral' (gray), 'accent' (orange). Default: accent orange. |
G.progressGroup(items[])
Vertical stack of horizontal progress bars.
G.progressGroup([
{ name: 'Revenue Target', value: 72, status: 'success' },
{ name: 'Migration', value: 45, status: 'warning' },
{ name: 'Bug Backlog', value: 18, status: 'critical' }
])| Item Param | Type | Required | Description |
|-----------|------|----------|-------------|
| name | string | yes | Label on the left |
| value | number | yes | Percentage (0–100), controls bar width |
| status | string | no | Bar color: 'success', 'warning', 'critical'. Default: accent orange. |
Content Blocks
G.block(options)
Collapsible section with a click-to-expand header.
G.block({
title: 'Strategic Analysis',
open: true,
content: G.stack([
G.field('Situation', 'Description here'),
G.field('Risk', 'Assessment here', 'warning'),
G.field('Action', 'Next steps here', 'success')
])
})| Param | Type | Required | Description |
|-------|------|----------|-------------|
| title | string | yes | Block heading (Anton, 16px, uppercase) |
| content | string | no | HTML content inside the collapsible body |
| open | boolean | no | Start expanded. Default: false (collapsed). |
| id | string | no | Custom DOM ID. Auto-generated if omitted. |
G.card(options)
Surface card with background color (--bg-surface).
G.card({
name: 'Hero Wars',
title: 'Core Platform',
desc: '8M DAU, growing 12% MoM.',
avatar: 'https://example.com/avatar.png', // optional image URL
content: G.tags([{ text: 'Gaming', cls: 'tag-accent' }])
})| Param | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | no | Large name heading (18px, bold). Also used to auto-generate initials avatar. |
| title | string | no | Title (16px, bold) |
| desc | string | no | Description paragraph |
| avatar | string | no | Image URL. Overrides auto-generated initials. |
| content | string | no | Any additional HTML |
G.callout(variant, label, text)
Bordered alert block. The base component behind escalation and reply.
G.callout('warning', 'Heads Up', 'Deployment window is this Friday.')
G.callout('success', 'Done', 'Migration completed successfully.')
G.callout('neutral', 'Note', 'This applies to all regions.')Variants: 'accent' (orange), 'critical' (red), 'warning' (yellow), 'success' (green), 'neutral' (gray).
G.escalation(label, text)
Red-bordered alert block. Shorthand for callout('critical', ...).
G.escalation(
'Critical Issue',
'APAC revenue dropped 23% in 2 weeks. Immediate executive review required.'
)G.reply(label, text)
Orange-bordered block for suggested responses or action items. Shorthand for callout('accent', ...).
G.reply(
'Suggested Response',
'Thank you for flagging this. We are scheduling an emergency review for Thursday.'
)G.quote(text, author, variant?)
Block quote with decorative quotation mark SVG.
G.quote('Every decision should be reversible.', 'Andrey Fadeev')
G.quote('Speed is a feature.', 'CEO Keynote 2025', 'hero')| Param | Type | Required | Description |
|-------|------|----------|-------------|
| text | string | yes | Quote body text |
| author | string | no | Attribution line below the quote |
| variant | string | no | 'hero' — larger, no background. Default: with surface background. |
People
G.participantList(items[])
Vertical list of participants with avatar (auto-generated from initials), name, role, score, and tags.
G.participantList([
{ name: 'Alice Chen', role: 'Tech Lead · 8 PRs', score: 92,
tags: [{ text: 'Top Performer', cls: 'tag-success' }] },
{ name: 'Bob Kim', role: 'Senior Dev · 5 PRs', score: 78,
tags: [{ text: 'On Track', cls: 'tag-accent' }] },
{ name: 'Carol Dubois', role: 'Junior Dev · 3 PRs', score: 61,
tags: [{ text: 'Needs Support', cls: 'tag-warning' }],
avatar: 'https://example.com/carol.jpg' } // optional image override
])| Item Param | Type | Required | Description |
|-----------|------|----------|-------------|
| name | string | yes | Person's name (16px, bold, bright) |
| role | string | no | Role description (13px, muted) |
| score | number | no | Numeric score on the right (Anton, 22px) |
| tags | array | no | Array of { text, cls } tag pills |
| avatar | string | no | Image URL. Overrides auto-generated initials. |
Tags
G.tag(text, cssClass?)
Single pill-shaped tag.
G.tag('Active', 'tag-success')G.tags(items[])
Flex row of tags. Accepts strings (default tag-gray) or { text, cls } objects.
G.tags(['Tag A', 'Tag B'])
G.tags([
{ text: 'Active', cls: 'tag-success' },
{ text: 'Blocked', cls: 'tag-critical' }
])Available tag classes:
| Class | Color | Use for |
|-------|-------|---------|
| tag-accent | Orange (#FF4E02) | Primary labels, highlights |
| tag-success / tag-green | Green (#32c00e) | Positive states, completed |
| tag-warning / tag-yellow | Yellow (#f5a623) | Caution, needs attention |
| tag-critical / tag-red | Red (#e72424) | Errors, blockers, urgent |
| tag-neutral / tag-gray | Gray | Informational, inactive |
Buttons
Six button styles, all uppercase Roboto Condensed. All accept an optional onclick string.
G.btnCta('Submit Report') // Solid orange — primary action
G.btnGhost('Download') // Ghost with border
G.btnOutline('Export') // Alias for btnGhost
G.btnMono('Settings') // Monochrome solid
G.btnMonoGhost('Reset') // Monochrome ghost
G.btnAction('Cancel') // Subtle gray — low-emphasis action
// With onclick handlers
G.btnCta('Run Analysis', 'startAnalysis()')
G.btnGhost('Export', 'exportData()')Wrap multiple buttons in a row:
'<div class="btn-row">' +
G.btnCta('Primary') +
G.btnGhost('Secondary') +
G.btnAction('Cancel') +
'</div>'Tables
G.table(data, opts?)
Full-featured data table.
G.table({
cols: ['Name', 'Status', { text: 'Score', align: 'right', shrink: true }],
rows: [
['Alice Chen', { text: 'Active', cls: 'cell-good' }, '92'],
['Bob Kim', { text: 'Pending', cls: 'cell-warning' }, '78'],
['Carol D.', { text: 'At Risk', cls: 'cell-critical' }, '61']
]
}, { variant: 'striped', compact: false })data object:
| Key | Type | Description |
|-----|------|-------------|
| cols | array | Column headers. String or { text, align?, width?, shrink? }. shrink: true collapses column to minimum width. |
| rows | array | Array of row arrays. Each cell: string or { text, cls }. |
opts object:
| Key | Type | Description |
|-----|------|-------------|
| variant | string | '' (default) | 'striped' | 'bordered' |
| compact | boolean | Tighter row padding |
Cell color classes: cell-good, cell-warning, cell-critical, cell-accent
Lists
G.list(items[], type?)
Styled list in five formats.
// Bulleted
G.list(['First item', 'Second item', 'Third item'], 'ul')
// Numbered (padded: 01, 02...)
G.list(['Step one', 'Step two'], 'ol')
// Numbered alternate style
G.list(['Step one', 'Step two'], 'ol-alt')
// Checklist (toggle on click)
G.list([
{ text: 'Deploy to staging', checked: true },
{ text: 'Run smoke tests', checked: false },
{ text: 'Update docs' }
], 'checklist')
// Description list (title + body)
G.list([
{ title: 'Velocity', desc: '47 story points per sprint, consistently above target.' },
{ title: 'Bug Rate', desc: 'Trending upward since sprint 3.' }
], 'desc')Types: 'ul' (default), 'ol', 'ol-alt', 'checklist', 'desc'
Navigation & Structure
G.tabs(tabsArray, defaultIdx?)
Tabbed panels with a click-to-switch tab bar.
G.tabs([
{ label: 'Overview', content: G.metricsGrid([...]) },
{ label: 'Details', content: G.block({ title: 'Analysis', content: '...' }) },
{ label: 'History', content: G.timeline([...]) }
], 0)| Param | Type | Description |
|-------|------|-------------|
| tabsArray | array | { label, content } objects |
| defaultIdx | number | Initially active tab index. Default: 0. |
G.toc(items)
Table of contents with numbered entries. Clicking scrolls to the matching section via GDEV.scrollTo. No anchor links — works in GAS and other environments that block navigation.
Each item is a string (ID derived from text) or { text, id? } where id is the target element's DOM id (without #).
G.toc([
{ text: 'Executive Summary', id: 'summary' },
{ text: 'Key Metrics', id: 'metrics' },
'Appendix' // id auto-generated as 'appendix'
])G.footer(opts?)
Report footer with GDEV logo, text, and date.
G.footer()
G.footer({ text: 'GDEV Inc. — Internal', date: 'Q4 2025' })| Param | Type | Description |
|-------|------|-------------|
| text | string | Left text. Default: 'GDEV Inc. — Confidential' |
| date | string | Right text. Default: current month + year. |
Charts
G.barChart(items, opts?)
Horizontal or vertical bar chart with hover tooltips.
// Horizontal (default)
G.barChart([
{ label: 'Hero Wars', value: 68, color: '#32c00e' },
{ label: 'Pixel Gun', value: 45 },
{ label: 'AvZ', value: 29, pct: 29 } // pct overrides display label
])
// Vertical
G.barChart([
{ label: 'Q1', value: 120, label2: '$120K' },
{ label: 'Q2', value: 185, label2: '$185K' },
{ label: 'Q3', value: 210, label2: '$210K' }
], { type: 'vertical' })Item params:
| Key | Type | Description |
|-----|------|-------------|
| label | string | Bar label |
| value | number | Bar length/height (0–100 for horizontal, absolute for vertical) |
| pct | number | Horizontal only: overrides value for display percentage label |
| color | string | Bar color (CSS color string). Auto-assigned from palette if omitted. |
| label2 | string | Vertical only: value label shown above bar |
opts params:
| Key | Type | Description |
|-----|------|-------------|
| type | string | 'horizontal' (default) | 'vertical' |
| legend | array | Vertical only: custom legend items [{ text, color, labelValue }] |
G.donutChart(items, opts?)
SVG pie/donut chart with hover tooltips and legend.
G.donutChart([
{ label: 'Mobile', value: 58, color: '#ff4e02', labelValue: '58%' },
{ label: 'Web', value: 27, color: '#f5a623', labelValue: '27%' },
{ label: 'Other', value: 15, labelValue: '15%' }
])| Item Param | Type | Description |
|-----------|------|-------------|
| label | string | Legend label |
| value | number | Slice size (any unit — proportional) |
| color | string | Slice color. Auto-assigned if omitted. |
| labelValue | string | Label drawn inside the slice (shown only if slice ≥ 10%) |
| opts Param | Type | Description |
|-------------|------|-------------|
| size | number | SVG dimensions in px. Default: 285. |
Timeline
G.timeline(items[])
Vertical timeline with dots, connector lines, and future-state styling.
G.timeline([
{ date: 'Jan 2025', title: 'Series A Closed', desc: '$12M raised.' },
{ date: 'Mar 2025', title: 'APAC Launch', desc: 'Entered 4 new markets.' },
{ date: 'Q3 2025', title: 'Mobile Relaunch', future: true },
{ date: 'Q4 2025', title: 'IPO Target', future: true }
])| Item Param | Type | Description |
|-----------|------|-------------|
| date | string | Date or period label |
| title | string | Event title |
| desc | string | Optional description below title |
| future | boolean | Renders dot and line as dashed/muted. Default: false. |
Utility Functions
GDEV.tog(id)
Toggle a collapsible block open/closed by DOM ID. Called automatically by block headers.
GDEV.tog('my-block-id')GDEV.sc(value, [goodThreshold, warnThreshold])
Returns a CSS class based on score thresholds.
Default thresholds: [80, 50]. Pass explicit thresholds to override.
GDEV.sc(87, [80, 60]) // → 'good' (≥80)
GDEV.sc(71, [80, 60]) // → 'warning' (≥60, <80)
GDEV.sc(45, [80, 60]) // → 'critical' (<60)
GDEV.sc(87) // → 'good' (≥80, default)
GDEV.sc(55) // → 'warning' (≥50, <80, default)
GDEV.sc(30) // → 'critical' (<50, default)GDEV.toggleTheme()
Toggle between dark and light themes. Adds/removes .light-theme on <html>.
GDEV.printReport()
Triggers window.print().
GDEV.tabSwitch(groupId, idx)
Programmatically switch a tab panel. groupId is the id attribute on the tabs container.
GDEV.scrollTo(id)
Smoothly scrolls to an element by DOM ID. Called automatically by G.toc links; available for custom use.
GDEV.scrollTo('section-metrics')GDEV.uid(prefix?)
Generate a unique ID string. Used internally; available for custom use.
GDEV.uid('section') // → 'section1'
GDEV.uid() // → 'u2'GDEV.LOGO_SVG
Raw SVG string of the GDEV logo. Available if you need to place it outside the header.
Design System Reference
Typography
| Token | Font | Weight | Usage |
|-------|------|--------|-------|
| --font-display | Anton | 400 | All headings (h1–h4), report title, section title, block title, metric values, participant scores. Always uppercase. |
| --font-ui | Roboto Condensed | 300–700 | Everything else: body text, labels, buttons, descriptions, fields. |
Type scale:
| Size | Elements |
|------|----------|
| 36px | .metric-value |
| 32px | .report-title, h1 |
| 24px | .section-title, h2 |
| 22px | .participant-score |
| 20px | h3, .card-metric-value |
| 18px | .card-name |
| 16px | h4, .block-title, .card-title, .report-subtitle, .participant-name |
| 15px | Body text: .field-value, .section-desc, .card-desc, .escalation-text, .reply-text |
| 13px | .progress-name, .participant-role, .metric-sub, .card-meta-value |
| 11px | Labels: .section-label, .metric-label, .field-label, .escalation-label, .tag, .header-btn, .eyebrow-text |
Colors
Accent:
| Variable | Value | Usage |
|----------|-------|-------|
| --accent | #FF4E02 | Primary color. CTAs, metric highlights, section labels, links. |
| --accent-dim | rgba(255,78,2,0.75) | Section labels, secondary accent text. |
| --accent-subtle | rgba(255,78,2,0.12) | Tag backgrounds, badge fills. |
| --accent-border | rgba(255,78,2,0.35) | Eyebrow borders, reply block borders. |
Semantic:
| Variable | Value | Usage |
|----------|-------|-------|
| --success | #32c00e | Positive metrics, good scores, success tags. |
| --warning | #f5a623 | Caution metrics, warning fields, attention tags. |
| --critical | #e72424 | Error metrics, critical fields, escalation blocks. |
Text hierarchy (dark theme):
| Variable | Value | Usage |
|----------|-------|-------|
| --text-bright | #FAFAF8 | Headings, primary text |
| --text-mid | rgba(255,255,255,0.72) | Secondary headings, highlighted text |
| --text-muted | rgba(255,255,255,0.55) | Body text (default) |
| --text-dim | rgba(255,255,255,0.38) | Descriptions, subtitles |
| --text-faint | rgba(255,255,255,0.28) | Field labels, tertiary text |
| --text-ghost | rgba(255,255,255,0.15) | Arrows, divider text |
Surfaces:
| Variable | Dark | Light |
|----------|------|-------|
| --bg-page | #0C0C0E | #F5F4F0 |
| --bg-surface | #141416 | #FFFFFF |
Borders:
| Variable | Dark | Light |
|----------|------|-------|
| --border-strong | rgba(255,255,255,0.15) | rgba(0,0,0,0.12) |
| --border-default | rgba(255,255,255,0.10) | rgba(0,0,0,0.08) |
| --border-subtle | rgba(255,255,255,0.06) | rgba(0,0,0,0.04) |
Spacing & Radii
| Variable | Value | Usage |
|----------|-------|-------|
| --radius-sm | 8px | Buttons, small cards, field corners |
| --radius-md | 12px | — |
| --radius-lg | 16px | Cards, metric cards, escalation, reply blocks |
| --radius-xl | 20px | Collapsible blocks |
| --radius-pill | 100px | Tags, eyebrow badge, header buttons |
Design Constraints
These are hard rules of the GDEV design system. The library enforces them, but be aware if adding custom CSS:
- Flat only. No gradients, no
box-shadow, nobackdrop-filter, no blur. - 0.5px borders. Never thicker (except print media).
- Anton is always uppercase. Never use Anton in sentence case.
- Two fonts only. Anton for display, Roboto Condensed for everything else.
#FF4E02is the only accent. No other brand colors.- Surfaces create hierarchy. Use background differences, not drop shadows.
CSS Classes Available
If you need to build custom HTML beyond the component API, these utility classes are available:
<!-- Text colors -->
<span class="text-accent">Orange text</span>
<span class="text-bright">Bright text</span>
<span class="text-mid">Mid text</span>
<span class="text-dim">Dim text</span>
<span class="text-success">Green text</span>
<span class="text-warning">Yellow text</span>
<span class="text-critical">Red text</span>
<!-- Typography -->
<span class="font-display">Anton font</span>
<span class="uppercase">Force uppercase</span>
<span class="strike">Strikethrough</span>All component classes (.block, .card, .field, .metric-card, etc.) are also available for direct HTML use.
Overriding Styles
Use the css option in init() for skill-specific customizations:
GDEV.init({
skill: 'CUSTOM REPORT',
css: `
.report-title { font-size: 48px; }
.container { max-width: 1100px; }
.metric-card { min-width: 200px; }
`
});Or override CSS variables:
GDEV.init({
skill: 'BRANDED',
css: `
:root {
--accent: #0066FF;
--accent-subtle: rgba(0, 102, 255, 0.12);
--accent-border: rgba(0, 102, 255, 0.35);
}
`
});Complete Example
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Q4 Team Review</title>
<script src="https://cdn.jsdelivr.net/npm/gdev-html-report/gdev-html-report.js"></script>
</head>
<body>
<script>
GDEV.init({ skill: 'TEAM REVIEW' });
var G = GDEV.html;
var data = {
quarter: 'Q4 2025',
metrics: [
{ label: 'Velocity', value: '47', status: 'good', sub: 'Story points/sprint' },
{ label: 'Bug Rate', value: '12%', status: 'warning', sub: 'Target: <8%' },
{ label: 'Coverage', value: '68%', status: 'critical', sub: 'Target: >80%' }
],
team: [
{ name: 'Alice Chen', role: 'Tech Lead · 8 PRs', score: 92,
tags: [{ text: 'Top Performer', cls: 'tag-success' }] },
{ name: 'Bob Kim', role: 'Senior Dev · 5 PRs', score: 78,
tags: [{ text: 'On Track', cls: 'tag-accent' }] },
{ name: 'Carol Dubois', role: 'Junior Dev · 3 PRs', score: 61,
tags: [{ text: 'Needs Support', cls: 'tag-warning' }] }
]
};
var content = '';
content += G.eyebrow('Confidential · ' + data.quarter);
content += G.reportHeader({
label: 'Engineering',
title: 'TEAM PERFORMANCE REVIEW',
subtitle: data.quarter + ' Sprint Retrospective'
});
content += G.section({
label: 'Overview',
title: 'Sprint Metrics',
content: G.metricsGrid(data.metrics)
});
content += G.section({
label: 'People',
title: 'Individual Performance',
content: G.participantList(data.team)
});
content += G.section({
label: 'Details',
title: 'Analysis',
content: G.stack([
G.block({
title: 'Strengths', open: true,
content: G.stack([
G.field('Velocity', 'Consistently above target for 3 sprints.', 'success'),
G.field('Collaboration', 'Cross-team PR reviews up 40%.', 'success')
])
}),
G.block({
title: 'Risks',
content: G.stack([
G.field('Bug Rate', 'Trending up since sprint 3. Root cause: rushed QA.', 'warning'),
G.escalation('Test Coverage', 'Below 70% threshold. Deployment gate may trigger.')
])
}),
G.block({
title: 'Action Items',
content: G.stack([
G.field('Priority 1', 'Dedicate 2 days next sprint to test backlog.', 'critical'),
G.field('Priority 2', 'Pair Carol with Alice on complex tickets.'),
G.reply('Message to Team', 'Great velocity this quarter. Let us focus sprint 1 of Q1 on test coverage.')
])
})
], '16px')
});
content += G.footer({ text: 'GDEV Inc. — Internal', date: data.quarter });
document.body.insertAdjacentHTML('beforeend', G.container(content));
</script>
</body>
</html>For AI Assistants (Claude, GPT, etc.)
When generating GDEV reports, use this pattern:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>{{PAGE_TITLE}}</title>
<script src="https://cdn.jsdelivr.net/npm/gdev-html-report/gdev-html-report.js"></script>
</head>
<body>
<script>
GDEV.init({ skill: '{{SKILL_NAME}}' });
var G = GDEV.html;
var D = {{REPORT_DATA_JSON}};
var content = '';
// ... G.reportHeader(), G.metricsGrid(), G.block(), etc.
document.body.insertAdjacentHTML('beforeend', G.container(content));
</script>
</body>
</html>Key benefit: No need to emit CSS, font data, SVG logos, or helper functions. Just data + G.* calls. This reduces generation time and token usage by ~80% compared to inline HTML+CSS reports.
Browser Support
Works in all modern browsers (Chrome, Firefox, Safari, Edge). The library uses ES5-compatible code — no arrow functions, no const/let, no template literals in the runtime.
Versioning
@1.0.0— Initial release (broken: octal escape in CSS template literal)@1.0.1— Fixed build@2.0.0— Major rewrite: 32 components (up from 24), addedgrid3/grid4/grid5,table,list,tabs,toc,footer,barChart(vertical mode),donutChart,quote,timeline,callout,btnAction,btnOutline, accessiblearia-labelon all elements, interactive chart tooltips@2.0.4— Previous release@2.0.5— Spacing system overhaul, component polish, print improvements@2.0.6— Fix donutChart legend showing value by default, fix toc to use scrollTo only (no anchors), fix stack gap=0@2.0.11— barChart vertical legend refinements, general component improvements@2.1.0— Current release
To pin a version: [email protected]. To get latest: gdev-html-report@latest.
License
Internal use — GDEV.
