mirror of
https://github.com/fluencelabs/fluent-pad
synced 2025-06-09 05:41:20 +00:00
better css
This commit is contained in:
parent
6d7b03c34e
commit
f7e57bf9b3
@ -3,6 +3,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tonsky/FiraCode@4/distr/fira_code.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
|
@ -1,22 +1,223 @@
|
||||
.App {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
$bg-color1: white;
|
||||
$bg-color2: #f4f4f4;
|
||||
$font-color1: black;
|
||||
$font-color1-disabled: lightgray;
|
||||
|
||||
$color1: black;
|
||||
$color2: rgb(214, 214, 214);
|
||||
|
||||
$accent-color: rgb(225, 30, 90);
|
||||
|
||||
$header-height: 60px;
|
||||
$border-radius: 10px;
|
||||
|
||||
@mixin font($size) {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: $size;
|
||||
}
|
||||
|
||||
$shadow: 0px 5px 20px rgba(0, 0, 0, 0.1);
|
||||
|
||||
body {
|
||||
background-color: $bg-color2;
|
||||
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
.header-wrapper {
|
||||
padding: 0 20px;
|
||||
height: $header-height;
|
||||
|
||||
background-color: $bg-color1;
|
||||
color: $font-color1;
|
||||
|
||||
box-shadow: $shadow;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
|
||||
width: 1200px;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
width: calc(100vw - 80px);
|
||||
margin-left: 20px;
|
||||
margin-right: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
.App div {
|
||||
margin: 20px;
|
||||
.content {
|
||||
width: 1200px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
width: calc(100vw - 80px);
|
||||
margin-left: 35px;
|
||||
margin-right: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 500px;
|
||||
height: 200px;
|
||||
.welcome-form {
|
||||
display: block;
|
||||
|
||||
width: 600px;
|
||||
height: auto;
|
||||
min-height: 300px;
|
||||
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 120px;
|
||||
|
||||
padding: 50px 80px;
|
||||
box-sizing: border-box;
|
||||
|
||||
box-shadow: $shadow;
|
||||
border-radius: $border-radius;
|
||||
|
||||
background-color: $bg-color1;
|
||||
color: $font-color1;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
.fluent-pad {
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
font-size: 40px;
|
||||
height: 60px;
|
||||
color: $accent-color;
|
||||
}
|
||||
|
||||
.userlist {
|
||||
margin-top: 10px;
|
||||
height: 30px;
|
||||
|
||||
& li {
|
||||
display: inline;
|
||||
margin-right: 10px;
|
||||
@include font(14px);
|
||||
}
|
||||
}
|
||||
|
||||
.code-editor {
|
||||
width: 100%;
|
||||
min-height: 500px;
|
||||
|
||||
resize: none;
|
||||
padding: 1em 0.5em 0.5em 0.5em;
|
||||
|
||||
box-shadow: $shadow;
|
||||
|
||||
font-size: 12px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
|
||||
background-color: $bg-color1;
|
||||
color: $font-color1;
|
||||
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.text-input {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding-left: 15px;
|
||||
padding-top: 10px;
|
||||
box-sizing: border-box;
|
||||
|
||||
margin-top: 5px;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: 2px solid $color2;
|
||||
|
||||
font-style: normal;
|
||||
@include font(15px);
|
||||
color: $color1;
|
||||
|
||||
&::placeholder {
|
||||
color: $color2;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: 1px solid white;
|
||||
border-bottom: 2px solid $accent-color;
|
||||
}
|
||||
}
|
||||
|
||||
.form-caption {
|
||||
color: $accent-color;
|
||||
text-align: center;
|
||||
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
@include font(20px);
|
||||
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.join-button {
|
||||
background-color: white;
|
||||
color: $accent-color;
|
||||
border: 2px solid $accent-color;
|
||||
|
||||
border-radius: $border-radius;
|
||||
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
|
||||
margin-top: 20px;
|
||||
|
||||
outline: none;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $accent-color;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.header-item {
|
||||
@include font(14px);
|
||||
text-transform: uppercase;
|
||||
|
||||
& button {
|
||||
@include font(14px);
|
||||
text-transform: uppercase;
|
||||
|
||||
background: none;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $accent-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.red {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.accent {
|
||||
color: $accent-color;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -42,39 +42,57 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<FluenceClientContext.Provider value={client}>
|
||||
<div className="App">
|
||||
<div>
|
||||
<div>Connection status: {client ? 'connected' : 'disconnected'}</div>
|
||||
<div>
|
||||
<label>Nickname: </label>
|
||||
<input
|
||||
type="text"
|
||||
value={nickName}
|
||||
disabled={isInRoom}
|
||||
onChange={(e) => {
|
||||
const name = e.target.value;
|
||||
setNickName(name);
|
||||
}}
|
||||
/>
|
||||
<div className="header-wrapper">
|
||||
<div className="header">
|
||||
<div className="header-item">
|
||||
{isInRoom && (
|
||||
<button className="button" disabled={!isInRoom} onClick={leaveRoom}>
|
||||
Leave
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<button disabled={isInRoom || !client} onClick={joinRoom}>
|
||||
Join Room
|
||||
|
||||
<div className="header-item">
|
||||
<button className="button" onClick={() => calls.clean(client!)}>
|
||||
Clean
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button disabled={!isInRoom} onClick={leaveRoom}>
|
||||
Leave Room
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={() => calls.clean(client!)}>Clean</button>
|
||||
|
||||
<div className="header-item">
|
||||
Connection status: {client ? <span className="accent">connected</span> : 'disconnected'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="content">
|
||||
{!isInRoom && (
|
||||
<div className="welcome-form">
|
||||
<h1 className="form-caption">Welcome to FluentPad</h1>
|
||||
<input
|
||||
className="text-input"
|
||||
placeholder="Your name"
|
||||
type="text"
|
||||
value={nickName}
|
||||
disabled={isInRoom}
|
||||
onChange={(e) => {
|
||||
const name = e.target.value;
|
||||
setNickName(name);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="wrapper">
|
||||
<div>{isInRoom && client && <CollaborativeEditor />}</div>
|
||||
<div>{isInRoom && client && <UserList selfName={nickName} />}</div>
|
||||
<button className="join-button" disabled={isInRoom || !client} onClick={joinRoom}>
|
||||
Join
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isInRoom && (
|
||||
<div className="room-wrapper">
|
||||
<h1 className="fluent-pad">FluentPad</h1>
|
||||
<UserList selfName={nickName} />
|
||||
<CollaborativeEditor />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</FluenceClientContext.Provider>
|
||||
|
@ -64,9 +64,5 @@ export const CollaborativeEditor = () => {
|
||||
broadcastUpdates(newText, syncClient);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<textarea value={text} onChange={handleTextUpdate} />
|
||||
</div>
|
||||
);
|
||||
return <textarea spellCheck={false} className="code-editor" value={text} onChange={handleTextUpdate} />;
|
||||
};
|
||||
|
@ -9,8 +9,10 @@ import { useFluenceClient } from '../app/FluenceClientContext';
|
||||
import * as calls from 'src/app/api';
|
||||
import { subscribeToEvent } from '@fluencelabs/fluence';
|
||||
|
||||
type PeerId = string;
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
id: PeerId;
|
||||
name: string;
|
||||
isOnline: boolean;
|
||||
shouldBecomeOnline: boolean;
|
||||
@ -24,8 +26,6 @@ const turnUserAsOfflineCandidate = (u: User): User => {
|
||||
};
|
||||
};
|
||||
|
||||
type PeerId = string;
|
||||
|
||||
const refreshTimeoutMs = 2000;
|
||||
|
||||
export const UserList = (props: { selfName: string }) => {
|
||||
@ -112,14 +112,12 @@ export const UserList = (props: { selfName: string }) => {
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="userlist">
|
||||
<ul>
|
||||
{usersArray.map((x) => (
|
||||
<li key={x.id}>
|
||||
{x.name}{' '}
|
||||
<span style={{ color: x.isOnline ? 'green' : 'red' }}>
|
||||
({x.isOnline ? 'online' : 'offline'})
|
||||
</span>
|
||||
<span className={x.id === client.selfPeerId.toB58String() ? 'bold' : ''}>{x.name}</span>
|
||||
<span className={x.isOnline ? 'green' : 'red'}> ({x.isOnline ? 'online' : 'offline'})</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
Loading…
x
Reference in New Issue
Block a user