Hex to binary
Here's a hex to binary converter with a bold, retro-terminal aesthetic:
import { useState, useCallback } from "react";
const HEX_CHARS = "0123456789ABCDEFabcdef";
function hexToBinary(hex) {
const clean = hex.replace(/\s+/g, "").replace(/^0x/i, "");
if (!clean) return { binary: "", groups: [] };
const groups = [];
for (const char of clean.toUpperCase()) {
if (!HEX_CHARS.includes(char)) return { error: `Invalid hex character: '${char}'` };
const bin = parseInt(char, 16).toString(2).padStart(4, "0");
groups.push({ hex: char, bin });
}
const binary = groups.map(g => g.bin).join(" ");
return { binary, groups, clean };
}
function binaryToHex(bin) {
const clean = bin.replace(/\s+/g, "");
if (!clean) return { hex: "", groups: [] };
if (!/^[01]+$/.test(clean)) return { error: "Invalid binary: only 0s and 1s allowed" };
const padded = clean.padStart(Math.ceil(clean.length / 4) * 4, "0");
const groups = [];
for (let i = 0; i < padded.length; i += 4) {
const nibble = padded.slice(i, i + 4);
const hexChar = parseInt(nibble, 2).toString(16).toUpperCase();
groups.push({ hex: hexChar, bin: nibble });
}
return { hex: groups.map(g => g.hex).join(""), groups };
}
export default function App() {
const [hexInput, setHexInput] = useState("");
const [binInput, setBinInput] = useState("");
const [hexResult, setHexResult] = useState(null);
const [binResult, setBinResult] = useState(null);
const [copied, setCopied] = useState(null);
const [activeTab, setActiveTab] = useState("hex");
const handleHexChange = useCallback((val) => {
setHexInput(val);
setHexResult(val.trim() ? hexToBinary(val) : null);
}, []);
const handleBinChange = useCallback((val) => {
setBinInput(val);
setBinResult(val.trim() ? binaryToHex(val) : null);
}, []);
const copy = (text, id) => {
navigator.clipboard.writeText(text);
setCopied(id);
setTimeout(() => setCopied(null), 1500);
};
const styles = {
page: {
minHeight: "100vh",
background: "#0a0a0a",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
fontFamily: "'Courier New', monospace",
padding: "24px",
position: "relative",
overflow: "hidden",
},
scanlines: {
position: "fixed", inset: 0, pointerEvents: "none", zIndex: 0,
background: "repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,255,100,0.015) 2px, rgba(0,255,100,0.015) 4px)",
},
card: {
position: "relative", zIndex: 1,
width: "100%", maxWidth: 680,
border: "1px solid #1a3a1a",
borderRadius: 4,
background: "#0d0d0d",
boxShadow: "0 0 40px rgba(0,255,80,0.08), inset 0 0 60px rgba(0,0,0,0.5)",
},
header: {
borderBottom: "1px solid #1a3a1a",
padding: "16px 24px",
display: "flex", alignItems: "center", gap: 12,
},
dot: (color) => ({ width: 10, height: 10, borderRadius: "50%", background: color }),
title: {
color: "#00ff55", fontSize: 13, letterSpacing: "0.2em",
textTransform: "uppercase", marginLeft: 8,
textShadow: "0 0 10px rgba(0,255,85,0.5)",
},
tabs: {
display: "flex", borderBottom: "1px solid #1a3a1a",
},
tab: (active) => ({
flex: 1, padding: "12px 0", background: "transparent", border: "none",
color: active ? "#00ff55" : "#2a4a2a",
fontSize: 11, letterSpacing: "0.2em", textTransform: "uppercase",
cursor: "pointer", fontFamily: "inherit",
borderBottom: active ? "2px solid #00ff55" : "2px solid transparent",
transition: "all 0.2s",
textShadow: active ? "0 0 8px rgba(0,255,85,0.4)" : "none",
}),
body: { padding: 24 },
label: {
color: "#2a6a2a", fontSize: 10, letterSpacing: "0.25em",
textTransform: "uppercase", marginBottom: 8, display: "block",
},
input: {
width: "100%", background: "#050505", border: "1px solid #1a3a1a",
borderRadius: 3, color: "#00ff55", fontFamily: "inherit",
fontSize: 16, padding: "14px 16px",
outline: "none", boxSizing: "border-box",
caretColor: "#00ff55",
letterSpacing: "0.05em",
transition: "border-color 0.2s, box-shadow 0.2s",
},
arrow: {
display: "flex", justifyContent: "center", alignItems: "center",
padding: "12px 0", color: "#1a5a1a", fontSize: 20,
},
resultBox: (hasError) => ({
background: "#050505", border: `1px solid ${hasError ? "#3a1a1a" : "#1a3a1a"}`,
borderRadius: 3, padding: "14px 16px", minHeight: 52,
display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12,
}),
resultText: (hasError) => ({
color: hasError ? "#ff4444" : "#00ff55", fontSize: 13,
letterSpacing: "0.12em", lineHeight: 1.8, flex: 1, wordBreak: "break-all",
textShadow: hasError ? "none" : "0 0 8px rgba(0,255,85,0.3)",
}),
copyBtn: (done) => ({
background: "transparent", border: `1px solid ${done ? "#00ff55" : "#1a3a1a"}`,
borderRadius: 2, color: done ? "#00ff55" : "#2a5a2a",
fontSize: 9, letterSpacing: "0.15em", textTransform: "uppercase",
padding: "4px 8px", cursor: "pointer", fontFamily: "inherit",
flexShrink: 0, transition: "all 0.2s",
}),
nibbles: {
display: "flex", flexWrap: "wrap", gap: 8, marginTop: 14,
},
nibble: {
background: "#050505", border: "1px solid #152515",
borderRadius: 2, padding: "6px 10px", textAlign: "center",
},
nibbleHex: {
color: "#00cc44", fontSize: 14, letterSpacing: "0.1em",
display: "block", marginBottom: 4,
},
nibbleBin: {
color: "#005522", fontSize: 10, letterSpacing: "0.1em",
},
examples: {
marginTop: 20, paddingTop: 16, borderTop: "1px solid #0f2a0f",
display: "flex", gap: 8, flexWrap: "wrap",
},
exLabel: {
color: "#1a4a1a", fontSize: 9, letterSpacing: "0.2em", width: "100%",
textTransform: "uppercase", marginBottom: 4,
},
exBtn: {
background: "transparent", border: "1px solid #152515",
borderRadius: 2, color: "#2a6a2a", fontSize: 10,
letterSpacing: "0.1em", padding: "4px 10px", cursor: "pointer",
fontFamily: "inherit", transition: "all 0.15s",
},
};
const hexExamples = ["FF", "A5", "DEAD", "0xFF", "C0DE"];
const binExamples = ["1010", "11001100", "11111111", "10101010"];
return (
);
}
Features:
Hex → Binary and Binary → Hex conversion via tabs
Nibble-by-nibble breakdown showing each hex digit mapped to its 4-bit group
Handles 0x prefixes and spaces gracefully
Inline error messages for invalid characters
One-click copy button for results
Quick-fill example buttons to try common values
hex ↔ binary converter
{activeTab === "hex" ? (
<>
handleHexChange(e.target.value)}
placeholder="e.g. FF or 0xDEAD"
spellCheck={false}
autoComplete="off"
/>
▼
{hexResult?.error ? (
⚠ {hexResult.error}
) : (
{hexResult?.binary || awaiting input...}
{hexResult?.binary && (
)}
)}
{hexResult?.groups?.length > 0 && (
{hexResult.groups.map((g, i) => (
)}
{g.hex}
{g.bin}
))}
try an example
{hexExamples.map(ex => (
))}
>
) : (
<>
handleBinChange(e.target.value)}
placeholder="e.g. 11001010"
spellCheck={false}
autoComplete="off"
/>
▼
{binResult?.error ? (
⚠ {binResult.error}
) : (
{binResult?.hex
? `0x${binResult.hex}`
: awaiting input...}
{binResult?.hex && (
)}
)}
{binResult?.groups?.length > 0 && (
{binResult.groups.map((g, i) => (
)}
{g.hex}
{g.bin}
))}
try an example
{binExamples.map(ex => (
))}
>
)}
Comments
Post a Comment