webserial-core
Version:
A strongly-typed, event-driven, abstract TypeScript library for the Web Serial API with custom parsers, command queue, handshake validation, and auto-reconnect.
256 lines (217 loc) • 4.13 kB
CSS
/* Shared styles for all webserial-core demos.
* Each demo HTML sets its own CSS custom properties in an inline <style> block:
* --accent, --accent-dark, --accent-badge, --log-event
* --notice-bg, --notice-border, --notice-text, --notice-code-bg (optional)
*/
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family:
"Segoe UI",
system-ui,
-apple-system,
sans-serif;
background: #0f0f12;
color: #e4e4e7;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
#app {
width: min(640px, 94vw);
background: #18181b;
border: 1px solid #27272a;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
}
header {
padding: 20px 24px;
border-bottom: 1px solid #27272a;
display: flex;
align-items: center;
gap: 12px;
}
header h1 {
font-size: 1.15rem;
font-weight: 600;
color: var(--accent);
}
header span {
font-size: 0.8rem;
color: #71717a;
}
.badge {
background: var(--accent);
color: var(--accent-badge);
font-size: 0.65rem;
font-weight: 700;
padding: 2px 8px;
border-radius: 999px;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.controls {
display: flex;
gap: 8px;
padding: 16px 24px;
border-bottom: 1px solid #27272a;
flex-wrap: wrap;
}
button {
padding: 8px 18px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
transition:
background 0.2s,
opacity 0.2s;
}
button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
#btn-connect {
background: var(--accent);
color: var(--accent-badge);
}
#btn-connect:hover:not(:disabled) {
background: var(--accent-dark);
}
#btn-disconnect {
background: #ef4444;
color: #fff;
}
#btn-disconnect:hover:not(:disabled) {
background: #dc2626;
}
.notice {
margin: 0 24px 16px;
padding: 14px 16px;
background: var(--notice-bg, #161616);
border: 1px solid var(--notice-border, #3f3f46);
border-left: 3px solid var(--accent);
border-radius: 8px;
font-size: 0.78rem;
line-height: 1.6;
color: var(--notice-text, #e4e4e7);
}
.notice code {
background: var(--notice-code-bg, #0f0f0f);
padding: 1px 5px;
border-radius: 4px;
font-family: monospace;
}
.info-text {
margin: 0 24px 4px;
padding: 10px 0;
font-size: 0.8rem;
line-height: 1.6;
color: #a1a1aa;
border-bottom: 1px solid #27272a;
}
.info-text code {
background: #09090b;
color: #e4e4e7;
padding: 1px 5px;
border-radius: 4px;
font-family: monospace;
font-size: 0.78rem;
}
.send-row {
display: flex;
gap: 8px;
padding: 0 24px 16px;
}
.send-row input {
flex: 1;
padding: 8px 12px;
border-radius: 8px;
border: 1px solid #3f3f46;
background: #09090b;
color: #e4e4e7;
font-size: 0.85rem;
outline: none;
transition: border-color 0.2s;
}
.send-row input:focus {
border-color: var(--accent);
}
.send-row input:disabled {
opacity: 0.4;
}
#btn-send {
background: #6366f1;
color: #fff;
}
#btn-send:hover:not(:disabled) {
background: #4f46e5;
}
#mode-toggle {
background: var(--accent);
color: var(--accent-badge);
font-weight: 700;
min-width: 54px;
}
#mode-toggle:hover {
background: var(--accent-dark);
}
#log {
height: 340px;
overflow-y: auto;
padding: 16px 24px;
font-family: "Fira Code", "Cascadia Code", monospace;
font-size: 0.8rem;
line-height: 1.7;
background: #09090b;
}
.log-line {
white-space: pre-wrap;
word-break: break-all;
}
.log-info {
color: #a1a1aa;
}
.log-event {
color: var(--log-event, #38bdf8);
}
.log-data {
color: #4ade80;
}
.log-error {
color: #f87171;
}
#log::-webkit-scrollbar {
width: 6px;
}
#log::-webkit-scrollbar-track {
background: transparent;
}
#log::-webkit-scrollbar-thumb {
background: #3f3f46;
border-radius: 3px;
}
.nav-link {
display: block;
text-align: center;
padding: 10px;
color: #71717a;
font-size: 0.78rem;
text-decoration: none;
border-top: 1px solid #27272a;
}
.nav-link:hover {
color: var(--accent);
}
.nav-link + .nav-link {
border-top: none;
padding-top: 0;
}