@nimhippl/gwc
v1.0.0
Published
Zero-dependency gamification web components library with TypeScript support - leaderboards, badges, rewards, tooltips, and game UI primitives
Downloads
30
Maintainers
Readme
GWC - Game Web Components
Zero-dependency game UI web components with TypeScript support, customizable themes, and framework-agnostic usage.
GWC is designed for gamification interfaces, browser games, dashboards, quests, rewards, inventories, leaderboards, player profiles, cooldowns, and achievement screens.
Features
- Zero production dependencies
- TypeScript-ready
- Framework-agnostic Web Components
- Works with Vanilla JS, Vue, React, Angular, Rails views, and plain HTML
- Built-in themes
- Customizable through attributes, config objects, and CSS variables
- Shadow DOM encapsulation
- ESM package output
Installation
npm install gwcQuick Start
import { GwcLeaderboard, type LeaderboardEntry } from 'gwc';
const leaderboard = document.querySelector('gwc-leaderboard') as GwcLeaderboard | null;
const entries: LeaderboardEntry[] = [
{ id: 1, name: 'Alice', score: 1250 },
{ id: 2, name: 'Bob', score: 980 }
];
leaderboard?.setData(entries);<gwc-leaderboard
theme="default"
title="Top Players"
max-entries="10">
</gwc-leaderboard>Browser Usage
<script type="module" src="./dist/index.js"></script>
<gwc-leaderboard title="Top Players"></gwc-leaderboard>Components
Leaderboard
Ranked player list with scores, avatars, selected player flow, and rank modes.
<gwc-leaderboard
theme="default"
title="Top Players"
max-entries="10">
</gwc-leaderboard>import { GwcLeaderboard, type LeaderboardEntry } from 'gwc';
const leaderboard = document.querySelector('gwc-leaderboard') as GwcLeaderboard | null;
const entries: LeaderboardEntry[] = [
{
id: 1,
name: 'Alice',
score: 1250,
avatar: 'https://example.com/avatar.png'
},
{
id: 2,
name: 'Bob',
score: 980
}
];
leaderboard?.setData(entries);Main attributes
theme- theme nametitle- leaderboard titlemax-entries- maximum entries to displayvariant- visual variantrank-mode- ranking behavior
Main events
gwc-leaderboard-entry-click
Badge
Achievement badge with rarity, progress, and reward states.
Badge states
locked- achievement is not completed yetunlocked- achievement is earned, no claim requiredclaimable- achievement is completed and reward can be claimedclaimed- reward has already been claimedhidden- secret badge state
<gwc-badge
theme="default"
size="medium"
show-name="true"
show-description="true"
show-progress="true"
show-state-label="true"
show-rarity="true"
claim-label="Claim reward">
</gwc-badge>import { GwcBadge, type BadgeConfig } from 'gwc';
const badge = document.querySelector('gwc-badge') as GwcBadge | null;
const config: BadgeConfig = {
id: 'streak-master',
name: 'Streak Master',
description: 'Win 10 games in a row.',
icon: '🔥',
rarity: 'epic',
state: 'claimable',
progress: 10,
maxProgress: 10
};
badge?.setConfig(config);
badge?.addEventListener('gwc-badge-claim', event => {
const nextConfig: BadgeConfig = {
...event.detail.config,
state: 'claimed',
claimedAt: new Date()
};
badge.setConfig(nextConfig);
});Main attributes
themesizeshow-nameshow-descriptionshow-progressshow-state-labelshow-rarityclaim-labelhidden-label
Main events
gwc-badge-clickgwc-badge-claim
Reward Card
Single reward card for coins, XP, items, skins, boosts, and chests.
Reward states
claimableclaimedlocked
<gwc-reward-card
theme="default"
size="medium"
show-description="true"
show-rarity="true"
show-amount="true"
show-state-label="true"
show-claim-button="true"
claim-label="Claim reward">
</gwc-reward-card>import { GwcRewardCard, type RewardConfig } from 'gwc';
const rewardCard = document.querySelector('gwc-reward-card') as GwcRewardCard | null;
const config: RewardConfig = {
id: 'coins-100',
name: '100 Coins',
description: 'Currency reward for completing the objective.',
icon: '🪙',
type: 'coins',
amount: 100,
rarity: 'common',
state: 'claimable'
};
rewardCard?.setConfig(config);
rewardCard?.addEventListener('gwc-reward-claim', event => {
const nextConfig: RewardConfig = {
...event.detail.config,
state: 'claimed',
claimedAt: new Date()
};
rewardCard.setConfig(nextConfig);
});Main attributes
themesizeshow-descriptionshow-rarityshow-amountshow-state-labelshow-claim-buttonclaim-labelclaimable-labelclaimed-labellocked-label
Main events
gwc-reward-clickgwc-reward-claim
Reward Reveal
Reward reveal flow for quest rewards, daily rewards, chest-style reveal screens, level-up rewards, and battle pass rewards.
<gwc-reward-reveal
theme="default"
title="Quest rewards"
subtitle="Open to reveal your rewards."
variant="chest"
mode="sequence"
show-close="false"
show-reset="true">
</gwc-reward-reveal>import { GwcRewardReveal, type RewardConfig } from 'gwc';
const reveal = document.querySelector('gwc-reward-reveal') as GwcRewardReveal | null;
const rewards: RewardConfig[] = [
{
id: 'coins-500',
name: '500 Coins',
icon: '🪙',
type: 'coins',
amount: 500,
rarity: 'common',
state: 'claimable'
},
{
id: 'rare-sword',
name: 'Rare Sword',
icon: '⚔️',
type: 'item',
amount: 1,
rarity: 'epic',
state: 'claimable'
}
];
reveal?.setRewards(rewards);
reveal?.open();
reveal?.addEventListener('gwc-reward-reveal-complete', event => {
const revealedRewards = event.detail.rewards;
void revealedRewards;
});Main attributes
themetitlesubtitlevariant-panel,cards,chestmode-all,sequenceshow-closeshow-resetopen-labelnext-labelclose-labelreset-labelempty-text
Main methods
setRewards(rewards)setConfig(config)getRewards()getState()open()revealNext()reset()close()
Main events
gwc-reward-reveal-opengwc-reward-reveal-startgwc-reward-reveal-itemgwc-reward-reveal-completegwc-reward-reveal-closegwc-reward-reveal-reward-click
Progress Bar
Progress bar for XP, HP, mana, stamina, quests, achievements, segmented progress, and battle pass progress.
<gwc-progress-bar
theme="default"
value="75"
max="100"
label="Player Health"
suffix="HP"
tone="health"
variant="line"
show-value="true"
show-percent="true">
</gwc-progress-bar>import { GwcProgressBar, type ProgressBarConfig } from 'gwc';
const progress = document.querySelector('gwc-progress-bar') as GwcProgressBar | null;
const config: ProgressBarConfig = {
value: 7,
max: 10,
label: 'Quest Progress',
suffix: 'wins',
tone: 'success',
variant: 'line',
showValue: true,
showPercent: true
};
progress?.setConfig(config);
progress?.setProgress(10, 10);Main attributes
themevaluemaxlabeldescriptionsuffixvariant-line,compact,segmentedtone-xp,health,mana,stamina,success,warning,danger,neutralshow-valueshow-percentanimatedstripeddisabledcompleted-labelsegments
Main methods
setConfig(config)getConfig()setValue(value)setMax(max)setProgress(value, max)
Main events
gwc-progress-changegwc-progress-complete
Countdown
Countdown timer for daily reward reset, cooldowns, boosts, crafting, match preparation, and seasonal events.
<gwc-countdown
theme="default"
label="Daily chest reset"
description="Next chest becomes available soon."
duration="3600"
tone="gold"
variant="card"
auto-start="true"
complete-label="Chest ready">
</gwc-countdown>import { GwcCountdown, type CountdownConfig } from 'gwc';
const countdown = document.querySelector('gwc-countdown') as GwcCountdown | null;
const config: CountdownConfig = {
label: 'Daily reward',
description: 'Next daily reward becomes available soon.',
duration: 3600,
tone: 'gold',
variant: 'card',
autoStart: true,
completeLabel: 'Reward ready'
};
countdown?.setConfig(config);
countdown?.addEventListener('gwc-countdown-complete', event => {
const state = event.detail.state;
void state;
});Main attributes
themelabeldescriptionend-atdurationvariant-card,compact,minimaltone-neutral,xp,success,warning,danger,goldauto-startshow-daysshow-labelsshow-controlscomplete-labelstart-labelpause-labelresume-labelreset-label
Main methods
setConfig(config)getConfig()getState()getRemainingMs()start()pause()reset()setDuration(seconds)setEndAt(endAt)addTime(seconds)
Main events
gwc-countdown-startgwc-countdown-pausegwc-countdown-resetgwc-countdown-tickgwc-countdown-complete
Stat Card
Compact stat card for level, power, wins, damage, defense, coins, rank, HP, mana, and XP.
<gwc-stat-card
theme="default"
label="Power"
value="540"
icon="⚔️"
delta="+25"
tone="danger"
variant="card">
</gwc-stat-card>import { GwcStatCard, type StatCardConfig } from 'gwc';
const statCard = document.querySelector('gwc-stat-card') as GwcStatCard | null;
const config: StatCardConfig = {
id: 'power',
label: 'Power',
value: 540,
icon: '⚔️',
description: 'Combined combat power.',
delta: '+25',
deltaLabel: 'gear bonus',
tone: 'danger',
variant: 'card'
};
statCard?.setConfig(config);Main attributes
themestat-idlabelvalueicondescriptiondeltadelta-labeltonevariant-card,compact,minimalsize-small,medium,largeinteractiveselectedshow-descriptionshow-delta
Main events
gwc-stat-card-click
Player Card
Player profile card for lobbies, match results, team lists, leaderboard details, and character selection.
<gwc-player-card
theme="default"
name="MysticMage"
title="Arcane damage dealer"
level="12"
rank="Gold"
status="online">
</gwc-player-card>import { GwcPlayerCard, type PlayerCardConfig } from 'gwc';
const playerCard = document.querySelector('gwc-player-card') as GwcPlayerCard | null;
const config: PlayerCardConfig = {
id: 'mystic-mage',
name: 'MysticMage',
title: 'Arcane damage dealer',
initials: 'MM',
level: 12,
rank: 'Gold',
score: '1,750 XP',
status: 'online',
isCurrentPlayer: true,
stats: [
{ label: 'Power', value: 540, icon: '⚔️', tone: 'danger' },
{ label: 'Wins', value: 32, icon: '🏆', tone: 'success' }
],
emblems: [
{ id: 'guardian', name: 'Guardian', icon: '🛡️', rarity: 'rare' }
],
progress: {
value: 1250,
max: 2000,
label: 'Next level',
suffix: 'XP',
tone: 'xp'
}
};
playerCard?.setConfig(config);Main attributes
themeplayer-idnametitleavatarinitialslevelrankscorestatus-online,offline,busy,awaycurrent-playervariant-card,compact,profilesize-small,medium,largetoneinteractiveselectedshow-statsshow-emblemsshow-progressshow-status
Main events
gwc-player-card-click
Quest List
Quest board for daily quests, weekly missions, achievements, battle pass tasks, and reward claim flows.
<gwc-quest-list
theme="default"
title="Quest board"
subtitle="Filter quests, inspect details, and claim ready rewards."
variant="card"
filter="all"
show-filters="true"
show-progress="true"
show-rewards="true"
show-claim-button="true">
</gwc-quest-list>import { GwcQuestList, type QuestConfig } from 'gwc';
const questList = document.querySelector('gwc-quest-list') as GwcQuestList | null;
const quests: QuestConfig[] = [
{
id: 'daily-crystals',
title: 'Collect crystals',
description: 'Collect 5 crystals in the forest zone.',
icon: '💎',
category: 'Daily',
difficulty: 'normal',
state: 'active',
progress: {
value: 4,
max: 5,
label: 'Crystals',
suffix: 'items'
},
rewards: [
{
id: 'coins-300',
name: 'Coins',
icon: '🪙',
amount: 300,
rarity: 'common',
type: 'coins'
}
]
}
];
questList?.setQuests(quests);Main attributes
themetitlesubtitlevariant-card,compact,minimalfilter-all,locked,active,completed,claimable,claimedshow-filtersshow-progressshow-rewardsshow-claim-buttonclaim-labelempty-text
Main methods
setQuests(quests)setConfig(config)getQuests()setFilter(filter)getFilter()
Main events
gwc-quest-clickgwc-quest-claimgwc-quest-filter-change
Inventory Slot
Single inventory cell for items, equipment, consumables, materials, skins, quest items, locked slots, and cooldown states.
<gwc-inventory-slot
theme="default"
slot-id="weapon-1"
name="Rare Sword"
icon="⚔️"
type="weapon"
rarity="rare"
state="filled"
action="equip"
quantity="1"
durability="82"
max-durability="100">
</gwc-inventory-slot>import { GwcInventorySlot, type InventorySlotConfig } from 'gwc';
const slot = document.querySelector('gwc-inventory-slot') as GwcInventorySlot | null;
const config: InventorySlotConfig = {
slotId: 'weapon-1',
state: 'filled',
action: 'equip',
actionLabel: 'Equip',
item: {
id: 'rare-sword',
name: 'Rare Sword',
description: 'A balanced sword for advanced quests.',
icon: '⚔️',
type: 'weapon',
rarity: 'rare',
quantity: 1,
durability: 82,
maxDurability: 100
}
};
slot?.setConfig(config);Main attributes
themeslot-iditem-idnamedescriptioniconimagetyperarityquantitymax-quantityleveldurabilitymax-durabilitycooldown-remainingcooldown-totalstate-empty,filled,equipped,locked,cooldown,disabledvariant-slot,compact,detailedaction-none,inspect,equip,unequip,use,sell,craftaction-labelselectedinteractiveshow-nameshow-quantityshow-rarityshow-durabilityshow-cooldownshow-actionempty-textlocked-reason
Main methods
setConfig(config)getConfig()clear()
Main events
gwc-inventory-slot-clickgwc-inventory-slot-actiongwc-inventory-slot-equipgwc-inventory-slot-use
Inventory Grid
Inventory board built from inventory slots. Handles layout, capacity, filters, selected item state, empty slots, and event forwarding.
<gwc-inventory-grid
theme="default"
title="Inventory"
subtitle="Items, equipment, consumables and locked slots."
capacity="24"
columns="6"
filter="all"
variant="board"
show-filters="true"
show-capacity="true"
show-empty-slots="true"
show-actions="selected"
show-names="false">
</gwc-inventory-grid>import { GwcInventoryGrid, type InventorySlotConfig } from 'gwc';
const inventory = document.querySelector('gwc-inventory-grid') as GwcInventoryGrid | null;
const slots: InventorySlotConfig[] = [
{
slotId: 'weapon-1',
state: 'filled',
action: 'equip',
item: {
id: 'rare-sword',
name: 'Rare Sword',
icon: '⚔️',
type: 'weapon',
rarity: 'rare'
}
},
{
slotId: 'potion-1',
state: 'filled',
action: 'use',
item: {
id: 'health-potion',
name: 'Health Potion',
icon: '🧪',
type: 'consumable',
rarity: 'common',
quantity: 8
}
}
];
inventory?.setConfig({
title: 'Inventory',
capacity: 24,
columns: 6,
slots,
showFilters: true,
showCapacity: true,
showEmptySlots: true,
showActions: 'selected',
showNames: false
});Main attributes
themetitlesubtitlecapacitycolumnsfilterselected-slot-idvariant-board,compact,minimalshow-filtersshow-capacityshow-empty-slotsshow-actions-true,false,selectedshow-namesempty-text
Main methods
setSlots(slots)getSlots()setConfig(config)getConfig()setFilter(filter)getFilter()selectSlot(slotId)clearSelection()
Main events
gwc-inventory-grid-slot-clickgwc-inventory-grid-slot-actiongwc-inventory-grid-selection-changegwc-inventory-grid-filter-change
Emblem
Compact game emblem for roles, classes, factions, ranks, medals, and profile badges.
<gwc-emblem
theme="default"
size="medium"
shape="shield"
interactive="true"
show-state="true">
</gwc-emblem>import { GwcEmblem, type EmblemConfig } from 'gwc';
const emblem = document.querySelector('gwc-emblem') as GwcEmblem | null;
const config: EmblemConfig = {
id: 'defender',
name: 'Defender',
description: 'Block 100 attacks.',
icon: '🛡️',
rarity: 'epic',
state: 'unlocked'
};
emblem?.setConfig(config);Main attributes
themesize-small,medium,largeshape-shield,circle,hex,diamondinteractiveselectedshow-stateshow-raritylabel
Main events
gwc-emblem-click
Tooltip
Lightweight tooltip for buttons, icons, labels, controls, rarity hints, and rank mode explanations.
<gwc-tooltip
tooltip-title="Rank mode"
text="Controls how tied scores are displayed."
position="right">
<button type="button">i</button>
</gwc-tooltip>import { GwcTooltip, type TooltipConfig } from 'gwc';
const tooltip = document.querySelector('gwc-tooltip') as GwcTooltip | null;
const config: TooltipConfig = {
title: 'Rank mode',
text: 'Controls how tied scores are displayed.',
position: 'right'
};
tooltip?.setConfig(config);Main attributes
themetooltip-titletextposition-top,right,bottom,left
Slots
- default slot - trigger element
content- custom tooltip body
Main events
gwc-tooltip-toggle
Inspector Panel
Reusable details panel for selected players, stats, rewards, emblems, quests, inventory slots, and grid selections.
<gwc-inspector-panel
theme="default"
variant="dark"
empty-text="Select an item to see details.">
</gwc-inspector-panel>import { GwcInspectorPanel, type InspectorPanelConfig } from 'gwc';
const panel = document.querySelector('gwc-inspector-panel') as GwcInspectorPanel | null;
const config: InspectorPanelConfig = {
title: 'Rare Sword',
subtitle: 'Selected item',
description: 'A balanced sword for advanced quests.',
icon: '⚔️',
eventName: 'gwc-inventory-grid-slot-click',
fields: [
{ label: 'State', value: 'filled' },
{ label: 'Rarity', value: 'rare' },
{ label: 'Quantity', value: 1 }
]
};
panel?.setConfig(config);Main attributes
themevariant-dark,cardempty-texttitlesubtitledescriptioniconimageevent-name
Main methods
setConfig(config)getConfig()clear()
Themes
Built-in themes:
defaultdarkneonforestsunsetocean
Use a theme through an attribute:
<gwc-player-card theme="dark"></gwc-player-card>
<gwc-inventory-grid theme="neon"></gwc-inventory-grid>Use a theme through JavaScript:
const element = document.querySelector('gwc-player-card');
element?.setAttribute('theme', 'dark');Use theme helpers:
import { applyTheme, themePresets } from 'gwc';
const element = document.querySelector('gwc-player-card');
if (element) {
applyTheme(element, themePresets.neon);
}CSS Variables
All components use the same base CSS variables:
:root {
--gwc-primary: #6366f1;
--gwc-secondary: #8b5cf6;
--gwc-background: #ffffff;
--gwc-text: #1f2937;
--gwc-accent: #f59e0b;
--gwc-border: #e5e7eb;
}Tooltip also supports tooltip-specific variables:
:root {
--gwc-tooltip-background: #1f2937;
--gwc-tooltip-text: #f9fafb;
--gwc-tooltip-muted-text: #e5e7eb;
--gwc-tooltip-border: rgba(255, 255, 255, 0.08);
--gwc-tooltip-radius: 10px;
--gwc-tooltip-width: 280px;
}TypeScript
GWC exports component classes and related types:
import {
GwcLeaderboard,
GwcBadge,
GwcRewardCard,
GwcRewardReveal,
GwcProgressBar,
GwcCountdown,
GwcStatCard,
GwcPlayerCard,
GwcQuestList,
GwcInventorySlot,
GwcInventoryGrid,
GwcEmblem,
GwcTooltip,
GwcInspectorPanel
} from 'gwc';
import type {
LeaderboardEntry,
BadgeConfig,
RewardConfig,
ProgressBarConfig,
CountdownConfig,
StatCardConfig,
PlayerCardConfig,
QuestConfig,
InventorySlotConfig,
InventoryGridConfig,
EmblemConfig,
TooltipConfig,
InspectorPanelConfig
} from 'gwc';Custom events are typed through HTMLElementEventMap when the package is imported.
import 'gwc';
const badge = document.querySelector('gwc-badge');
badge?.addEventListener('gwc-badge-claim', event => {
const config = event.detail.config;
void config;
});Development
Install dependencies:
npm installRun typecheck:
npm run typecheckBuild package:
npm run buildWatch TypeScript:
npm run devRun local demo:
python3 -m http.server 8080Open:
http://localhost:8080/demo.htmlPackage Check
Before publishing:
npm run test
npm run build
npm pack --dry-runThe npm package should include:
dist/
README.md
LICENSE
package.jsonBrowser Support
GWC works in modern browsers with support for:
- Custom Elements
- Shadow DOM
- ES Modules
- CSS custom properties
License
MIT
