<script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-y/preact/10.5.7/preact.min.js" type="application/javascript"></script>
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;700&display=swap">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=VT323&display=swap">
<div id="root"></div>
HTML
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
<head> ... </head>
<body>
</body>
* {
box-sizing: border-box;
position: relative;
}
html,
body {
--colors-bg--300: #1e181e;
--colors-bg--500: #191a1e;
--colors-primary--200: #f4908b;
--colors-primary--300: #ea6f69;
--colors-primary--500: #e8615a;
--colors-primary--600: #9c3230;
--colors-primary--700: #5e2122;
--colors-primary--800: #451717;
--colors-primary--900: #3c181a;
--colors-secondary--500: #2be4ea;
--colors-secondary--900: #295459;
--colors-tertiary--500: #fed33f;
--colors-on_bg--500: var(--colors-primary--500);
--colors-on_tertiary--500: var(--colors-bg--300);
--colors-on_primary--500: var(--colors-primary--200);
--colors-active--500: #2bfea0;
--fonts-primary: "Rajdhani", sans-serif;
--fonts-secondary: "VT323", monospace;
--ui-glow: 0 0 5px var(--colors-primary--500);
--ui-glow-borders--500: 0 0 3px var(--colors-primary--500);
--ui-glow-color: currentcolor;
--ui-glow-text: -9px -6px 40px var(--ui-glow-color);
--ui-glow-text--dimmed: -9px -6px 40px var(--ui-glow-color);
--ui-elevation--1: 2px 2px 0 rgba(0, 0, 0, 0.8);
--ui-notch-amount: 1rem;
--ui-notch-hypotenuse: 22.627416px; /* hypothenuse of --ui-notch-amount */
--ui-notch-path: polygon(
0 0,
100% 0,
100% calc(100% - var(--ui-notch-amount) + 2px),
calc(100% - var(--ui-notch-amount) + 2px) 100%,
0 100%
);
background-color: var(--colors-bg--500);
background-image: radial-gradient(
ellipse at 33% 10%,
#461616 0%,
transparent 75%
);
background-repeat: no-repeat;
color: var(--colors-on_bg--500);
font-family: var(--fonts-primary);
font-size: 100%;
line-height: 1.4;
margin: 0;
min-height: 100vh;
}
a {
color: inherit;
text-decoration: none;
}
.app-skeleton {
padding: 0 1rem;
height: 100vh;
min-width: 1024px;
}
.app-header {
align-items: center;
display: flex;
grid-area: header;
justify-content: space-between;
margin-bottom: 1rem;
padding: 1rem 0 0.5rem 0;
}
.app-header::after {
background-color: var(--colors-primary--500);
box-shadow: var(--ui-glow);
bottom: 0;
content: "";
height: 2px;
position: absolute;
left: 0;
width: 100%;
}
.app-header__anchor {
padding: 0.5rem;
}
.app-header__anchor__text {
font-family: var(--fonts-secondary);
font-size: 1.25rem;
letter-spacing: 0.035rem;
text-shadow: var(--ui-glow-text);
text-transform: uppercase;
}
.app-container {
display: grid;
grid-gap: 1rem;
grid-template-areas: "a main main main side";
grid-template-columns: 280px 1fr 1fr 1fr 1fr;
height: calc(100% - 5.25rem);
}
.app-a {
grid-area: a;
height: 100%;
}
.app-b {
grid-area: side;
}
.app-main {
grid-area: main;
}
.nav-section {
padding-bottom: 0.25rem;
}
.nav-section__header {
background-color: var(--colors-bg--300);
border: 1px solid #5d2322;
border-radius: 3px;
margin-bottom: 0.5rem;
padding: 0.5rem 0.75rem;
}
.nav-section__body {
padding-left: 1rem;
}
.nav-section__title {
color: #2be4ea;
font-size: 1rem;
margin: 0;
}
.nav {
list-style: none;
margin: 0;
padding: 0;
}
.nav__link {
line-height: 1.4rem;
}
.nav__link__element + .nav__link__element {
margin-left: 0.5rem;
}
.app-header .nav {
align-items: flex-end;
display: flex;
}
.app-header .nav__item + .nav__item {
margin-left: 3rem;
}
.app-header .nav__link {
align-items: baseline;
display: flex;
text-shadow: var(--ui-glow-text);
text-transform: uppercase;
transition: transform 0.25s;
}
.app-header .nav__link:hover {
color: var(--colors-primary--200);
}
.app-header .nav__link.nav__link--active {
color: var(--colors-secondary--500);
font-size: 1.25rem;
transform: none;
}
.nav-section .nav__item + .nav__item {
margin-top: 0.125rem;
}
.nav-section .nav__link {
border: 1px solid transparent;
border-radius: 3px;
color: var(--colors-secondary--500);
display: block;
font-family: var(--fonts-primary);
padding: 0.5rem 0.75rem;
transition: background-color 0.25s;
}
.nav-section .nav__link:focus,
.nav-section .nav__link:hover {
background-color: var(--colors-bg--300);
border: 1px solid #5d2322;
}
.nav-section .nav__link--active,
.nav-section .nav__link.nav__link--active:focus,
.nav-section .nav__link.nav__link--active:hover {
background-color: #391419;
border-color: #9c3230;
}
.channel-link,
.conversation-link {
align-items: center;
display: flex;
}
.channel-link__icon,
.conversation-link__icon {
margin-right: 0.75rem;
}
.channel-link__element + .channel-link__element,
.conversation-link__element + .conversation-link__element {
margin-left: 0.75rem;
}
.conversation-link__icon {
}
.conversation-link__icon::after {
background-color: var(--colors-primary--500);
border-radius: 50%;
content: "";
display: block;
height: 0.5em;
width: 0.5em;
}
.conversation-link--online .conversation-link__icon::after {
background-color: var(--colors-active--500);
}
.channel-link--unread,
.conversation-link--unread {
font-weight: bold;
}
.badge {
border: 1.5px solid var(--colors-tertiary--500);
border-radius: 3px;
color: var(--colors-tertiary--500);
display: inline-block;
font-size: 0.92rem;
font-weight: normal;
line-height: 1;
padding: 0.15em 0.34em;
vertical-align: middle;
}
.slate__title {
font-size: 1.125rem;
margin: 0;
}
.pad {
background-color: var(--colors-bg--300);
border: 2px solid var(--colors-primary--600);
clip-path: var(--ui-notch-path);
}
.pad__body {
padding: 0.75rem;
padding-bottom: var(--ui-notch-amount);
}
.pad::before {
background-color: var(--colors-primary--600);
bottom: 5px;
content: "";
display: block;
height: 3px; /* bigger to compensate transform */
position: absolute;
right: -6px;
top: auto;
transform: rotate(-45deg);
width: var(--ui-notch-hypotenuse);
z-index: 100;
}
/* @component: form-* */
input,
textarea {
}
.form-label {
background-color: var(--colors-primary--600);
color: var(--colors-on_primary--500);
font-family: var(--fonts-secondary);
font-size: 0.92rem;
display: inline-block;
padding: 0.125em 0.75em;
padding-right: 2em;
letter-spacing: 0.065em;
line-height: 1;
text-transform: uppercase;
vertical-align: bottom; /* inline-block fix */
clip-path: polygon(
0.25em 0,
calc(100% - 1em) 0,
100% 100%,
0.33em 100%,
0 100%,
0 0.25em
);
}
.form-control {
background-color: var(--colors-bg--300);
border: 1px solid var(--colors-primary--600);
clip-path: var(--ui-notch-path);
padding-right: 0.5rem;
}
.form-control::before {
background-color: var(--colors-primary--600);
bottom: 5px;
content: "";
display: block;
height: 3px; /* bigger to compensate transform */
position: absolute;
right: -6px;
top: auto;
transform: rotate(-45deg);
width: var(--ui-notch-hypotenuse);
z-index: 100;
}
.form-control input,
.form-control textarea {
background-color: transparent;
border: 0;
box-shadow: none;
color: var(--colors-primary--500);
font-family: var(--fonts-primary);
font-size: 1rem;
letter-spacing: 0.045em;
outline: none;
padding: 0.5rem;
resize: none;
width: 100%;
}
.form-control--with-addon {
align-items: center;
display: flex;
}
.form-control--with-addon .button,
.form-control--with-addon .button:hover {
background-color: transparent;
border-color: transparent;
}
.form-control__addon {
display: inline-block;
padding: 0.45rem;
}
.form-control__addon svg {
display: block;
fill: currentcolor;
height: 1.125rem;
opacity: 0.66;
width: 1.125rem;
}
.form-control__addon--prefix {
order: -1;
}
.form-control__addon--suffix {
order: 1;
}
.form-search {
margin-bottom: 0.75rem;
}
.message {
padding-bottom: 1rem;
}
.message__body {
background-color: var(--colors-bg--300);
border: 1px solid var(--colors-tertiary--500);
border-radius: 3px;
color: var(--colors-tertiary--500);
padding: 0.75rem;
}
.message__footer {
color: var(--colors-tertiary--500);
font-size: 0.85rem;
margin-top: 0.25rem;
}
/* @component: button */
.button {
background-color: transparent;
border: 1px solid var(--colors-primary--500);
border-radius: 2px;
cursor: pointer;
color: var(--colors-primary--500);
display: inline-block;
font-family: var(--fonts-primary);
letter-spacing: 0.045em;
padding: 0.45rem;
text-align: left;
text-transform: uppercase;
}
.button:hover {
background-color: var(--colors-primary--800);
color: var(--colors-on_primary--500);
}
.button__icon {
display: block;
height: 1.125rem;
line-height: 1;
vertical-align: top;
width: 1.125rem;
}
.button__icon {
fill: currentcolor;
}
.button__content {
display: inline-block;
z-index: 2;
}
.button--size-lg,
.button--size-xl {
border-width: 2px;
clip-path: var(--ui-notch-path);
padding: 0.55rem 0.7rem 0.7rem 0.55rem;
}
.button--size-lg::before,
.button--size-xl::before {
background-color: currentcolor;
bottom: 5px;
content: "";
display: block;
height: 3px; /* bigger to compensate transform */
position: absolute;
right: -6px;
top: auto;
transform: rotate(-45deg);
width: var(--ui-notch-hypotenuse);
z-index: 100;
}
.button--size-xl {
padding: 0.55rem 1.5rem 1.5rem 0.55rem;
}
.button--primary {
color: var(--colors-secondary--500);
border-color: var(--colors-secondary--500);
}
.button--primary:hover {
background-color: var(--colors-secondary--900);
color: var(--colors-secondary--500);
}
.button-toolbar {
display: flex;
}
.button-toolbar .button {
display: block;
border-radius: 0;
}
.button-toolbar .button + .button {
margin-left: -1px;
}
.channel-feed {
display: flex;
flex-direction: column;
height: 100%;
}
.channel-feed__body {
flex-grow: 1;
}
.channel-feed__footer {
}
.channel-message-form {
align-items: flex-start;
display: flex;
padding-bottom: 1rem;
}
.channel-message-form .form-group {
flex: 1;
}
.channel-message-form .form-footer {
margin-left: 1rem;
margin-top: 1.42rem;
}
.channel-message-form .form-control {
width: 100%;
}
.text-heading1,
.text-heading2,
.text-heading3,
.text-heading4,
.text-heading5,
.text-heading6,
.text-paragraph1 {
margin: 0;
}
.segment-topbar {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
min-height: 3.5rem;
}
.segment-topbar::after {
background-color: var(--colors-primary--500);
box-shadow: var(--ui-glow);
bottom: 0;
content: "";
height: 1px;
position: absolute;
left: 0;
width: 100%;
}
.segment-topbar__header {
padding: 0.5rem 0.5rem;
padding-top: 0;
}
.segment-topbar__overline {
font-family: var(--fonts-secondary);
}
.segment-topbar__title {
letter-spacing: 0.035em;
text-shadow: var(--ui-glow-text--dimmed);
text-transform: uppercase;
}
.segment-topbar__aside {
align-self: flex-start;
box-shadow: -6px -4px 24px rgba(156, 50, 48, 0.4);
}
/** @jsx h */
const { h, render } = preact;
function App() {
return (
<div className="app-skeleton">
<header className="app-header">
<div className="app-header__anchor">
<span className="app-header__anchor__text">Night-City NetWire</span>
</div>
<nav>
<ul className="nav">
{FIXTURES.headerMenu.map((navItem, navItemIndex) => (
<NavItem key={navItemIndex} navItem={navItem} />
))}
</ul>
</nav>
<div />
</header>
<div className="app-container">
<div className="app-a">
<div className="segment-topbar">
<div className="segment-topbar__header">
<TextHeading3 className="segment-topbar__title">
Messages
</TextHeading3>
</div>
<div className="segment-topbar__aside">
<div className="button-toolbar">
<a className="button button--primary button--size-lg">
<IconFeedAdd className="button__icon" />
</a>
</div>
</div>
</div>
<form className="form-search" onSubmit={(e) => e.preventDefault()}>
<div className="form-group">
<div className="form-control form-control--with-addon">
<input name="query" placeholder="Search..." type="text" />
<div className="form-control__addon form-control__addon--prefix">
<IconSearchSubmit />
</div>
</div>
</div>
</form>
<NavSection renderTitle={(props) => <h2 {...props}>Feeds</h2>}>
<ChannelNav
activeChannel={{ id: "a0cc", name: "Watson" }}
channels={FIXTURES.feed}
/>
</NavSection>
<NavSection renderTitle={(props) => <h2 {...props}>Direct</h2>}>
<ConversationNav conversations={FIXTURES.conversation} />
</NavSection>
</div>
<div className="app-main">
<div className="channel-feed">
<div className="segment-topbar">
<div className="segment-topbar__header">
<TextOverline className="segment-topbar__overline">
NetWire_Seed: d869db7fe62fb07c25a0403ecaea55031744b5fb
</TextOverline>
<TextHeading4 className="segment-topbar__title">
<ChannelLink name="Watson" />
</TextHeading4>
</div>
<div className="segment-topbar__aside">
<div className="button-toolbar">
<a className="button button--default">
<IconFeedMute className="button__icon" />
</a>
<a className="button button--default">
<IconFeedSettings className="button__icon" />
</a>
<a className="button button--default">
<IconMenuMore className="button__icon" />
</a>
</div>
</div>
</div>
<div className="channel-feed__body">
<FeedMessage message={FIXTURES.messages[0]} />
<FeedMessage message={FIXTURES.messages[0]} />
</div>
<div className="channel-feed__footer">
<form
className="channel-message-form"
action="#"
onSubmit={(e) => e.preventDefault()}
>
<div className="form-group">
<label className="form-label" for="message">
Message
</label>
<div className="form-control">
<textarea
id="message"
className="form-control"
name="message"
></textarea>
</div>
</div>
<div className="form-footer">
<Button size="xl" type="submit" variant="primary">
Send
</Button>
</div>
</form>
</div>
</div>
</div>
<div className="app-b">
<Pad>
<TextHeading3 $as="h4">What's this?</TextHeading3>
<TextParagraph1>
A <em>fake</em> Slack or Discord type of app inspired by Cyberpunk
2077. This app is static, eg. not implementing much logic.
</TextParagraph1>
<TextParagraph1>
The goal is: showcasing a start of a UI kit. If you've played the
game, you' might be able to pick-up some similarities with the
in-game menus.
</TextParagraph1>
</Pad>
</div>
</div>
</div>
);
}
function NavSection({ children, renderTitle }) {
return (
<div className="nav-section">
<div className="nav-section__header">
{renderTitle({ className: "nav-section__title" })}
</div>
<div className="nav-section__body">{children}</div>
</div>
);
}
function FeedMessage({ message }) {
return (
<div className="message">
<div className="message__body">
<div>
{
"I got a gig lined up in Watson, no biggie. If you prove useful, expect more side gigs coming your way. I need a half-decent netrunner. Hit me up, provide credentials, eddies on completion."
}
</div>
</div>
<div className="message__footer">
<span className="message__authoring">V. M. Vargas</span>
{" - 11:04pm"}
</div>
</div>
);
}
function ChannelNav({ activeChannel = null, channels = [] }) {
return (
<ul className="nav">
{channels.map((channel) => (
<li className="nav__item">
<a
className={`nav__link ${
activeChannel && activeChannel.id === channel.id
? "nav__link--active"
: ""
}`}
href="#"
>
<ChannelLink {...channel}>{name}</ChannelLink>
</a>
</li>
))}
</ul>
);
}
function ConversationNav({ activeConversation = null, conversations = [] }) {
return (
<ul className="nav">
{conversations.map((convo) => (
<li className="nav__item">
<a
className={`nav__link ${
activeConversation && activeConversation.id === convo.id
? "nav__link--active"
: ""
}`}
href="#"
>
<ConversationLink conversation={convo} />
</a>
</li>
))}
</ul>
);
}
function ChannelLink({ icon, name, unread }) {
return (
<span
className={`channel-link ${
unread > 0 ? "conversation-link--unread" : ""
}`}
>
<span className="channel-link__icon">#</span>
<span className="channel-link__element">{name}</span>
{unread > 0 && (
<span className="channel-link__element">
<Badge>{unread}</Badge>
</span>
)}
</span>
);
}
function ConversationLink({ conversation }) {
return (
<span
className={`conversation-link ${
conversation.isOnline ? "conversation-link--online" : ""
} ${conversation.unread > 0 ? "conversation-link--unread" : ""}`}
>
{conversation.members && conversation.members.length > 2 ? (
<span className="conversation-link__icon" />
) : (
<span className="conversation-link__icon" />
)}
<span className="conversation-link__element">{conversation.name}</span>
{conversation.unread > 0 && (
<span className="conversation-link__element">
<Badge>{conversation.unread}</Badge>
</span>
)}
</span>
);
}
function Badge({ children }) {
return <span className="badge">{children}</span>;
}
function Button({
children,
type = "button",
size = "default",
variant = "default"
}) {
return (
<button
className={`button ${variant ? `button--${variant}` : ""} ${
size ? `button--size-${size}` : ""
}`}
type={type}
>
<span className="button__content">{children}</span>
</button>
);
}
function Pad({ children, renderCap = null }) {
return (
<div className="pad">
<div className="pad__body">{children}</div>
</div>
);
}
function NavItem({ navItem }) {
return (
<li className="nav__item">
<a
className={`nav__link ${navItem.isActive ? "nav__link--active" : ""}`}
href="#"
>
<span className="nav__link__element">{navItem.text}</span>
{navItem.notificationCount > 0 && (
<span className="nav__link__element">
<Badge>{navItem.notificationCount}</Badge>
</span>
)}
</a>
</li>
);
}
function MakeTextBase(classNameDefault, $asDefault) {
return ({ $as = null, children, className }) => {
const AsComponent = $as || $asDefault;
return (
<AsComponent className={`${classNameDefault} ${className}`}>
{children}
</AsComponent>
);
};
}
const TextHeading1 = MakeTextBase("text-heading1", "h1");
const TextHeading2 = MakeTextBase("text-heading2", "h2");
const TextHeading3 = MakeTextBase("text-heading3", "h3");
const TextHeading4 = MakeTextBase("text-heading4", "h4");
const TextHeading5 = MakeTextBase("text-heading5", "h5");
const TextHeading6 = MakeTextBase("text-heading6", "h6");
const TextParagraph1 = MakeTextBase("text-paragraph1", "p");
const TextOverline = MakeTextBase("segment-topbar__overline", "span");
function MakeIcon(svg) {
return ({ className }) => (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
{svg}
</svg>
);
}
const IconFeedMute = MakeIcon(
<path d="M18 9.5c2.481 0 4.5 1.571 4.5 3.503 0 1.674-1.703 3.48-4.454 3.48-.899 0-1.454-.156-2.281-.357-.584.358-.679.445-1.339.686.127-.646.101-.924.081-1.56-.583-.697-1.007-1.241-1.007-2.249 0-1.932 2.019-3.503 4.5-3.503zm0-1.5c-3.169 0-6 2.113-6 5.003 0 1.025.37 2.032 1.023 2.812.027.916-.511 2.228-.997 3.184 1.302-.234 3.15-.754 3.989-1.268.709.173 1.388.252 2.03.252 3.542 0 5.954-2.418 5.954-4.98.001-2.906-2.85-5.003-5.999-5.003zm-.668 6.5h-1.719v-.369l.938-1.361v-.008h-.869v-.512h1.618v.396l-.918 1.341v.008h.95v.505zm3.035 0h-2.392v-.505l1.306-1.784v-.011h-1.283v-.7h2.25v.538l-1.203 1.755v.012h1.322v.695zm-10.338 9.5c1.578 0 2.971-1.402 2.971-3h-6c0 1.598 1.45 3 3.029 3zm.918-7.655c-.615-1.001-.947-2.159-.947-3.342 0-3.018 2.197-5.589 5.261-6.571-.472-1.025-1.123-1.905-2.124-2.486-.644-.374-1.041-1.07-1.04-1.82v-.003c0-1.173-.939-2.123-2.097-2.123s-2.097.95-2.097 2.122v.003c.001.751-.396 1.446-1.041 1.82-4.667 2.712-1.985 11.715-6.862 13.306v1.749h9.782c.425-.834.931-1.764 1.165-2.655zm-.947-15.345c.552 0 1 .449 1 1 0 .552-.448 1-1 1s-1-.448-1-1c0-.551.448-1 1-1z" />
);
const IconFeedSettings = MakeIcon(
<path d="M6 16h-6v-3h6v3zm-2-5v-10h-2v10h2zm-2 7v5h2v-5h-2zm13-7h-6v-3h6v3zm-2-5v-5h-2v5h2zm-2 7v10h2v-10h-2zm13 3h-6v-3h6v3zm-2-5v-10h-2v10h2zm-2 7v5h2v-5h-2z" />
);
const IconMenuMore = MakeIcon(
<path d="M12 18c1.657 0 3 1.343 3 3s-1.343 3-3 3-3-1.343-3-3 1.343-3 3-3zm0-9c1.657 0 3 1.343 3 3s-1.343 3-3 3-3-1.343-3-3 1.343-3 3-3zm0-9c1.657 0 3 1.343 3 3s-1.343 3-3 3-3-1.343-3-3 1.343-3 3-3z" />
);
const IconFeedAdd = MakeIcon(
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z" />
);
const IconSearchSubmit = MakeIcon(
<path d="M21.172 24l-7.387-7.387c-1.388.874-3.024 1.387-4.785 1.387-4.971 0-9-4.029-9-9s4.029-9 9-9 9 4.029 9 9c0 1.761-.514 3.398-1.387 4.785l7.387 7.387-2.828 2.828zm-12.172-8c3.859 0 7-3.14 7-7s-3.141-7-7-7-7 3.14-7 7 3.141 7 7 7z" />
);
const IconShop = MakeIcon(
<path d="M16.53 7l-.564 2h-15.127l-.839-2h16.53zm-14.013 6h12.319l.564-2h-13.722l.839 2zm5.983 5c-.828 0-1.5.672-1.5 1.5 0 .829.672 1.5 1.5 1.5s1.5-.671 1.5-1.5c0-.828-.672-1.5-1.5-1.5zm11.305-15l-3.432 12h-13.017l.839 2h13.659l3.474-12h1.929l.743-2h-4.195zm-6.305 15c-.828 0-1.5.671-1.5 1.5s.672 1.5 1.5 1.5 1.5-.671 1.5-1.5c0-.828-.672-1.5-1.5-1.5z" />
);
const FIXTURES = {
headerMenu: [
{ notificationCount: 0, text: "Home" },
{ isActive: true, notificationCount: 11, text: "Messages" },
{ notificationCount: 0, text: "Shop" },
{ notificationCount: 0, text: "Map" },
{ notificationCount: 0, text: "Files" }
],
feed: [
{ id: "5ba5", name: "Afterlife", unread: 3 },
{ id: "4f22", name: "NCPD-Gigs" },
{ id: "fee9", name: "Pacifica" },
{ id: "a0cc", name: "Watson" },
{ id: "dee3", name: "_T_SQUAD", isPrivate: true, unread: 2 }
],
conversation: [
{
id: "cc23",
isOnline: true,
unread: 5,
name: "Rogue Amendiares"
},
{ id: "95b4", isOnline: true, name: "Takemura", unread: 1 },
{ id: "10cf", name: "Wakado O., Regina Jones" },
{ id: "e466", name: "Dexter DeShawn" },
{ id: "ca0b", name: "Megabuilding H10 Administration" }
],
messages: [
{
id: "fd0cf",
content:
"I got a gig lined up in Watson, no biggie. If you prove useful, expect more side gigs coming your way. I need a half-decent netrunner. Hit me up, provide credentials, eddies on completion.",
dateTime: "2077-10-09T11:04:57Z",
author: {
id: "d12c",
name: "V.M. Vargas"
}
}
]
};
render(<App />, document.getElementById("root"));