
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
com.hydroper.metrocomponents
Advanced tools
A component and icon library for React using the Metro design.
Installation:
npm i com.hydroper.metrocomponents
Installation:
npm i @fontsource/open-sans @fontsource/courier-prime
Import it into your entry point TypeScript as follows:
// Open Sans
import "@fontsource/open-sans/300.css";
import "@fontsource/open-sans/400.css";
import "@fontsource/open-sans/500.css";
import "@fontsource/open-sans/700.css";
// Courier Prime
import "@fontsource/courier-prime";
By default, the light theme preset is used. Theme presets can be referenced in ThemePresets. You can provide a specific theme for a React section using:
import { ThemeContext, ThemePresets } from "com.hydroper.metrocomponents";
// somewhere in React content
<ThemeContext.Provider value={ThemePresets.green}>
</ThemeContext.Provider>
You can nest it as well.
Indicate whether a LTR layout or RTL layout is preferred through LocaleDirectionContext:
import { LocaleDirectionContext, LocaleDirection } from "com.hydroper.metrocomponents";
const direction: LocaleDirection = "ltr";
// somewhere in React content
<LocaleDirectionContext.Provider value={direction}>
</LocaleDirectionContext.Provider>
To opt in to using primary colors in certain components such as heading titles and checkboxes, use the PreferPrimaryContext context:
import { PreferPrimaryContext } from "com.hydroper.metrocomponents";
// somewhere in React content
<PreferPrimaryContext.Provider value={true}>
</PreferPrimaryContext.Provider>
The Icon component is colored automatically at every state (hover, pressed) according to the computed cascading color property.
The CircleIconButton component represents a circle button consisting of an icon. For example, ArrowButton is an alias to <CircleIconButton icon="fullarrow" {...rest}/>, where the fullarrow icon fits into a square circle.
Here is a list of built-in icons:
| Type | Description |
|---|---|
bullet | Correponds to the bullet character. |
checked | Something is done or checked. |
arrow | A simple left arrow. |
fullarrow | A full left arrow, used mainly as a CircleIconButton (ArrowButton). |
search | Search or zoom. |
clear | Clear. |
games | Game controller. |
ie | Internet Explorer |
video | Video. |
store | Generic store or marketplace icon. |
settings | Settings. |
mail | (e-)mail. |
user | Generic user avatar. |
security | Security or safety. |
calc | Calculator. |
camera | Camera. |
bluetooth | Bluetooth. |
news | News. |
bing | Bing search engine. |
opera | Opera browser. |
chrome | Google Chrome browser. |
firefox | Firefox browser. |
msedge | Microsoft Edge browser. |
lapis | Southwest-pointing lapis. Also used as an "edit" icon. |
idea | An upstanding lamp. |
help | Question mark. |
helpcircle | Question mark inside a circle outline. |
new | A rectangle containing a plus sign. |
Register custom icons with:
import { IconRegistry } from "com.hydroper.metrocomponents";
IconRegistry.register("iconX", { black: source, white: source });
These icons can then be used in for example Icon and CircleIconButton components.
To unregister a previously registered icon, use IconRegistry.unregister().
Retrieve a registered icon's source URI using IconRegistry.get().
The cascading font-size property in the <html> tag is used for determining the unit in points in the library. 1 point equals 0.25rem, where rem is the font-size pixels of the <html> tag.
If it is desired to grow or reduce all the user interface together, you may adjust the font-size of the <html> tag.
This library uses com.hydroper.inputaction for detecting pressed input such as keyboard arrows. You may customize the global Input.input input actions for supporting buttons other than arrow keys.
Important
Elements that may be navigated with arrow input contain the cascading class name specified by the BUTTON_NAVIGABLE constant. This is useful for applications like games for avoid duplicating focus handling by detecting that class name.
if (active_element.classList.contains(BUTTON_NAVIGABLE)) /* ignore */ return;

Displaying context menus (typically these from a right click) is supported by the library.
import {
useContextMenu, ContextMenu,
ContextMenuItem, ContextMenuIcon, ContextMenuLabel, ContextMenuRight,
ContextMenuSeparator, ContextMenuSubmenu, ContextMenuSubmenuList,
ContextMenuSubIcon,
} from "com.hydroper.metrocomponents";
function MyComp()
{
const { id: contextMenuId, show: showContextMenu } = useContextMenu();
function item1_onClick()
{
console.log("clicked item 1");
}
showContextMenu();
return (
<>
<ContextMenu id={contextMenuId}>
<ContextMenuItem click={item1_onClick}>
<ContextMenuIcon></ContextMenuIcon>
<ContextMenuLabel>Item 1</ContextMenuLabel>
<ContextMenuRight></ContextMenuRight>
</ContextMenuItem>
<ContextMenuSeparator/>
<ContextMenuSubmenu>
<ContextMenuIcon></ContextMenuIcon>
<ContextMenuLabel>Submenu 1</ContextMenuLabel>
<ContextMenuRight><ContextMenuSubIcon/></ContextMenuRight>
</ContextMenuSubmenu>
<ContextMenuSubmenuList>
<ContextMenuItem disabled={true}>
<ContextMenuIcon></ContextMenuIcon>
<ContextMenuLabel>Item A</ContextMenuLabel>
<ContextMenuRight></ContextMenuRight>
</ContextMenuItem>
</ContextMenuSubmenuList>
</ContextMenu>
</>
);
}
If a context menu contains "checked" or "option" items, prepend a <ContextMenuCheck/> column to every item with the attribute state set to either none, checked or option.
(
<ContextMenuItem>
<ContextMenuCheck state="none"/>
<ContextMenuIcon></ContextMenuIcon>
<ContextMenuLabel>Item 1</ContextMenuLabel>
<ContextMenuRight></ContextMenuRight>
</ContextMenuItem>
<ContextMenuItem>
<ContextMenuCheck state="checked"/>
<ContextMenuIcon></ContextMenuIcon>
<ContextMenuLabel>Item 2</ContextMenuLabel>
<ContextMenuRight></ContextMenuRight>
</ContextMenuItem>
);
Tip: it is common, for instance, to disable opening a common context menu on buttons, as in the following code snippet:
function on_context_menu(e: MouseEvent): void { let p = e.target as HTMLElement | null; while (p) { if (!p.matches(":hover")) break; if (p instanceof HTMLButtonElement || (p instanceof HTMLInputElement && p.type == "button")) return; p = p.parentElement; } show_context_menu(); }

Live tiles are supported, though partially since during dragging tiles the library will not shift tiles automatically, and "vertical" tile containers are not supported. In the future these cases might be implemented.
Here's an usage example:
const tiles_controller = new TilesController();
useEffect(() => {
// Add tiles and their groups
tiles_controller.addGroup({
id: "group1",
label: "Group 1",
});
tiles_controller.addTile({
id: "tile1",
group: "group1",
x: 0,
y: 0,
size: "large",
color: "#A8143A",
icon: IconRegistry.get("video", "white"),
label: "Video",
});
tiles_controller.addTile({
id: "tile2",
group: "group1",
x: 0,
y: 4,
size: "wide",
color: "#008000",
icon: IconRegistry.get("games", "white"),
label: "Games",
livePages: [
{
html: `<div style='width:100%;height:100%;background: url("${xboxWallpaper}") no-repeat center 25%;background-size:cover'></div>`,
},
],
});
tiles_controller.addGroup({
id: "group2",
label: "Group 2",
});
tiles_controller.addTile({
id: "tile3",
group: "group2",
x: 0,
y: 0,
size: "small",
color: "#2572E1",
icon: IconRegistry.get("ie", "white"),
label: "Internet Explorer",
});
}, []);
return (
<>
<Tiles
controller={tiles_controller}
direction="horizontal"/>
</>
);
// Disable certain key behaviors
window.addEventListener("keydown", e => {
// Ctrl+A
if (e.key.toLowerCase() == "a" && e.ctrlKey && !e.shiftKey && !e.altKey)
{
if (!(
document.activeElement instanceof HTMLInputElement ||
document.activeElement instanceof HTMLTextAreaElement
)) e.preventDefault();
}
});
Apache 2.0
FAQs
Metro design components and icons
We found that com.hydroper.metrocomponents demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.