From 6413d7c642b8ef2d0f1995a4cc550d1ff993fece Mon Sep 17 00:00:00 2001 From: Kata Date: Mon, 18 Mar 2019 04:52:54 -0500 Subject: [PATCH] sync, too many changes to list out --- ui/components/demos/tap.js | 12 ++++ ui/components/demos/typing.js | 92 ++++++++++++++++++++++++++++++ ui/components/discord-guild-pic.js | 61 ++++++++++++++++++++ ui/components/header/auth.js | 77 ++++++++++++++++++++++++- ui/components/header/common.js | 27 ++++++--- ui/components/header/unauth.js | 22 +++++-- ui/components/layout.js | 19 +++++- ui/components/logo.js | 14 ++--- ui/components/role/demo.js | 25 ++++++++ ui/components/role/index.js | 90 +++++++++++++++++++++++++++++ ui/lib/redirect.js | 13 +++++ ui/pages/_internal/_server_add.js | 1 + ui/pages/_test/landing-mock.js | 16 +++++- ui/pages/index.js | 32 +++++++++-- 14 files changed, 469 insertions(+), 32 deletions(-) create mode 100644 ui/components/demos/tap.js create mode 100644 ui/components/demos/typing.js create mode 100644 ui/components/discord-guild-pic.js create mode 100644 ui/components/role/demo.js create mode 100644 ui/components/role/index.js create mode 100644 ui/lib/redirect.js create mode 100644 ui/pages/_internal/_server_add.js diff --git a/ui/components/demos/tap.js b/ui/components/demos/tap.js new file mode 100644 index 0000000..37c039d --- /dev/null +++ b/ui/components/demos/tap.js @@ -0,0 +1,12 @@ +// @flow +import * as React from 'react' +// import styled from 'styled-components' +import Role from '../role/demo' + +const roles = [ + 'cute', 'vanity', 'brave', 'proud', 'wonderful', '日本語' +] + +export default () =>
+ { roles.map((v, i) => ) } +
diff --git a/ui/components/demos/typing.js b/ui/components/demos/typing.js new file mode 100644 index 0000000..4242072 --- /dev/null +++ b/ui/components/demos/typing.js @@ -0,0 +1,92 @@ +import * as React from 'react' +import moment from 'moment' +import Typist from 'react-typist' +import styled from 'styled-components' + +const Outer = styled.div` + --not-quite-black: #23272A; + --dark-but-not-black: #2C2F33; + --greyple: #99AAB5; + --blurple: var(--c-discord); + + background-color: var(--dark-but-not-black); + padding: 10px; + text-align: left; + color: var(--c-white); +` + +const Chat = styled.div` + padding: 10px 0; + & span { + display: inline-block; + margin-left: 5px; + } +` + +const TextArea = styled.div` + background-color: hsla(218,5%,47%,.3); + border-radius: 5px; + padding: 10px; + + & .Typist .Cursor { + + display: inline-block; + color: transparent; + border-left: 1px solid var(--c-white); + user-select: none; + + &--blinking { + + opacity: 1; + animation: blink 2s ease-in-out infinite; + + @keyframes blink { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + } + } +` + +const Timestamp = styled.span` + font-size: 0.7em; + color: hsla(0,0%,100%,.2); +` + +const Username = styled.span` + font-weight: bold; +` + +const Typing = () => + + {moment().format('LT')} + okano「岡野」 + Hey, I want some roles! + + + + +export default Typing diff --git a/ui/components/discord-guild-pic.js b/ui/components/discord-guild-pic.js new file mode 100644 index 0000000..105af01 --- /dev/null +++ b/ui/components/discord-guild-pic.js @@ -0,0 +1,61 @@ +// @flow +// export default ({ id, icon, ...rest }) => +import * as React from 'react' +import styled from 'styled-components' + +export type GuildPicProps = { + id: string, + icon: string, + name: string +} + +export type GuildPicState = { + src: ?string, + ok: boolean +} + +const Fallback = styled.div` + display: flex; + justify-content: center; + align-items: center; + + background-color: hsl(${(props: any) => '' + (props.serverName.codePointAt(0) % 360)},50%,50%); +` + +export default class DiscordGuildPic extends React.Component { + state = { + src: this.src, + ok: false + } + + get src () { + return `https://cdn.discordapp.com/icons/${this.props.id}/${this.props.icon}.png` + } + + renderFallback () { + const { name, id, icon, ...rest } = this.props + return {name[0]} + } + + onError = () => { + // console.log('onError') + this.setState({ + src: null + }) + } + + onLoad = () => { + this.setState({ + ok: true + }) + } + + renderImg () { + const { name, id, icon, ...rest } = this.props + return + } + + render () { + return (this.state.src === null) ? this.renderFallback() : this.renderImg() + } +} diff --git a/ui/components/header/auth.js b/ui/components/header/auth.js index a12c9fc..e7d5b0e 100644 --- a/ui/components/header/auth.js +++ b/ui/components/header/auth.js @@ -2,12 +2,85 @@ import * as React from 'react' import HeaderBarCommon, { Logomark } from './common' import { type User } from '../../containers/user' +import DiscordIcon from '../discord-guild-pic' +import styled from 'styled-components' +import { Hide } from '../../kit/media' +import Link from 'next/link' + +const temporaryServer = { + id: '423497622876061707', + name: 'Placeholder', + icon: '8d03476c186ec8b2f6a1a4f5e55b13fe' +} + +const LogoBox = styled.a` + flex: 0; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +` + +const StyledServerPic = styled(DiscordIcon)` + border-radius: 100%; + box-shadow: inset 0 0 5px rgba(0,0,0,0.3); + height: 35px; + width: 35px; + margin-right: 10px; + display: flex; + align-items: center; + justify-content: center; +` + +const StyledAvatar = styled.img` + border-radius: 100%; + border: 1px solid var(--c-green); + height: 35px; + width: 35px; + margin-left: 10px; + display: flex; + align-items: center; + justify-content: center; +` + +const ServerSelector = (props) =>
+
+ +
+
+ { temporaryServer.name } +
+
+ +const StyledServerSelector = styled(ServerSelector)` + flex: 1; + display: flex; + align-items: center; + justify-content: left; +` + +const UserSection = ({ user, ...props }) =>
+ { user.username } + +
+ +const StyledUserSection = styled(UserSection)` + display: flex; + align-items: center; + justify-content: flex-end; + text-align: right; +` const HeaderBarAuth: React.StatelessFunctionalComponent<{ user: User }> = ({ user }) => ( <> - - Hey there, {user.username}#{user.discriminator} + + + + + + + ) diff --git a/ui/components/header/common.js b/ui/components/header/common.js index a55dc78..51fa98e 100644 --- a/ui/components/header/common.js +++ b/ui/components/header/common.js @@ -5,12 +5,14 @@ import styled from 'styled-components' import * as logo from '../logo' export type CommonProps = { - children: React.Element + children: React.Element, + noBackground: boolean } const Header = styled.div` - background-color: var(--c-dark); - + ${({ noBackground }: any) => noBackground === false ? 'background-color: var(--c-dark);' : ''} + position: relative; + transition: background-color 0.3s ease-in-out; ` const HeaderInner = styled.div` @@ -21,6 +23,13 @@ const HeaderInner = styled.div` width: 100vw; margin: 0 auto; height: 50px; + padding: 3px 5px; + position: relative; + top: -1px; + + & > div { + margin: 0 0.5em; + } ` export const Logotype = styled(logo.Logotype)` @@ -28,16 +37,16 @@ export const Logotype = styled(logo.Logotype)` ` export const Logomark = styled(logo.Logomark)` - width: 50px; - height: 50px; + width: 40px; + height: 40px; ` - +// const DebugBreakpoints = dynamic(() => import('../../kit/debug-breakpoints')) -const HeaderBarCommon = ({ children }: CommonProps) => ( -
+const HeaderBarCommon = ({ children, noBackground }: CommonProps) => ( +
+ { (process.env.NODE_ENV === 'development') && } - { (process.env.NODE_ENV === 'development') && } { children }
diff --git a/ui/components/header/unauth.js b/ui/components/header/unauth.js index 8f7d10e..086faa7 100644 --- a/ui/components/header/unauth.js +++ b/ui/components/header/unauth.js @@ -1,11 +1,25 @@ // @flow import * as React from 'react' -import HeaderBarCommon, { Logotype } from './common' +import HeaderBarCommon, { Logotype, type CommonProps } from './common' +import styled from 'styled-components' +import Link from 'next/link' -const HeaderBarUnauth: React.StatelessFunctionalComponent<{}> = () => ( - +const LogoBox = styled.a` + flex: 1; + display: flex; + align-items: center; + justify-content: flex-start; + cursor: pointer; +` + +const HeaderBarUnauth: React.StatelessFunctionalComponent = (props) => ( + <> - + + + + + Hey stranger. diff --git a/ui/components/layout.js b/ui/components/layout.js index d8c89dd..42c54e8 100644 --- a/ui/components/layout.js +++ b/ui/components/layout.js @@ -4,13 +4,26 @@ import GlobalColors from './global-colors' import SocialCards from './social-cards' import HeaderBar from '../containers/header-bar' import { type User } from '../containers/user' +import styled from 'styled-components' -const Layout = ({ children, user }: {children: React.Element, user: User }) => <> +const ContentBox = styled.div` + margin: 0 auto; + width: 960px; + max-width: 100vw; + padding: 5px; + /* padding-top: 50px; */ + overflow-y: scroll; + max-height: calc(100vh - 50px); +` + +const Layout = ({ children, user, noBackground }: {children: React.Element, user: User, noBackground: boolean }) => <>
- - {children} + + + {children} +
diff --git a/ui/components/logo.js b/ui/components/logo.js index 3bb9721..49ff37a 100644 --- a/ui/components/logo.js +++ b/ui/components/logo.js @@ -1,32 +1,30 @@ import * as React from 'react' const Logotype = ({ fill = 'var(--c-7)', width, height, circleFill = 'var(--c-3)', typeFill, style, className }) => ( - + - + - + ) const Logomark = ({ fill = 'var(--c-7)', width, height, circleFill = 'var(--c-3)', typeFill, style, className }) => ( - - - - + + - + diff --git a/ui/components/role/demo.js b/ui/components/role/demo.js new file mode 100644 index 0000000..5b2d6f2 --- /dev/null +++ b/ui/components/role/demo.js @@ -0,0 +1,25 @@ +// @flow +import * as React from 'react' +import Role, { type RoleData } from './index' + +export type DemoRoleProps = { + role: RoleData +} + +type DemoRoleState = { + active: boolean +} + +export default class RoleDemo extends React.Component { + state = { + active: false + } + + onToggle = (n: boolean) => { + this.setState({ active: n }) + } + + render () { + return + } +} diff --git a/ui/components/role/index.js b/ui/components/role/index.js new file mode 100644 index 0000000..b52d014 --- /dev/null +++ b/ui/components/role/index.js @@ -0,0 +1,90 @@ +// @flow +import * as React from 'react' +import styled from 'styled-components' +import MediaQuery from '../../kit/media' + +export type RoleData = { + color: string, + name: string, +} + +export type RoleProps = { + active?: boolean, // is lit up as if it's in use + disabled?: boolean, // is interaction-disabled + type?: 'drag' | 'button', + role: RoleData, + isDragging?: boolean, + onToggle?: (nextState: boolean, lastState: boolean) => void, + connectDragSource?: (component: React.Node) => void +} + +const Outer = styled.div` + box-sizing: border-box; + padding: 4px 0.5em; + padding-top: 2px; + border: solid 1px var(--outer-color); + display: inline-block; + border-radius: 1.2em; + margin: 0.3em; + font-size: 1.2em; + transition: box-shadow 0.3s ease-in-out; + text-shadow: 1px 1px 1px rgba(0,0,0,0.45); + cursor: pointer; + user-select: none; + ${(props: any) => (props.active) ? 'box-shadow: inset 0 0 0 3em var(--outer-color);' : ''} + position: relative; + + &:hover::after { + transform: translateY(-1px); + box-shadow: 0 0 1px rgba(0,0,0,0.75); + } + + &:active::after { + transform: none; + } + + &::after { + display: none; + content: ''; + position: absolute; + box-sizing: border-box; + top: 4px; + left: 4px; + bottom: 2px; + border-radius: 100%; + width: 22px; + height: 22px; + clip-path: border-box circle(50% at 50% 50%); /* firefox fix */ + transform: none; + border: 1px solid var(--outer-color); + transition: border 0.3s ease-in-out, transform 0.1s ease-in-out; + ${(props: any) => (props.active) ? 'border-left-width: 21px;' : ''} + } + + ${(props: any) => MediaQuery({ + md: ` + font-size: 1em; + text-shadow: none; + padding-left: 32px; + ${(props.active) ? 'box-shadow: none;' : ''} + &::after { + display: block; + } + ` + })} + + +` + +export default class Role extends React.Component { + onToggle = () => { + if (!this.props.disabled && this.props.onToggle) { + const { active = false } = this.props + this.props.onToggle(!active, active) + } + } + + render () { + return {this.props.role.name} + } +} diff --git a/ui/lib/redirect.js b/ui/lib/redirect.js new file mode 100644 index 0000000..1f7d533 --- /dev/null +++ b/ui/lib/redirect.js @@ -0,0 +1,13 @@ +import Router from 'next/router' + +export default (context, target) => { + if (context.res) { + // server + // 303: "See other" + context.res.writeHead(303, { Location: target }) + context.res.end() + } else { + // In the browser, we just pretend like this never even happened ;) + Router.replace(target) + } +} diff --git a/ui/pages/_internal/_server_add.js b/ui/pages/_internal/_server_add.js new file mode 100644 index 0000000..30d7648 --- /dev/null +++ b/ui/pages/_internal/_server_add.js @@ -0,0 +1 @@ +export default () =>

s/add

diff --git a/ui/pages/_test/landing-mock.js b/ui/pages/_test/landing-mock.js index 62b9778..bfe6621 100644 --- a/ui/pages/_test/landing-mock.js +++ b/ui/pages/_test/landing-mock.js @@ -4,6 +4,20 @@ import type { PageProps } from '../../types' export default class LandingTest extends React.Component { render () { - return
+ return
+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Suscipit accusantium quidem adipisci excepturi, delectus iure omnis, eos corrupti, ea ex iusto magnam! Incidunt accusamus repellat natus esse facilis animi aut.

+
} } diff --git a/ui/pages/index.js b/ui/pages/index.js index b652d95..83ea762 100644 --- a/ui/pages/index.js +++ b/ui/pages/index.js @@ -1,10 +1,32 @@ -import React from 'react' +import * as React from 'react' +import redirect from '../lib/redirect' // import Link from 'next/link' // import Head from '../components/head' // import Nav from '../components/nav' +import TypingDemo from '../components/demos/typing' +import TapDemo from '../components/demos/tap' -const Home = () => ( -

Hi there.

-) +export default class Home extends React.Component { + static async getInitialProps (ctx, rpc) { + if (ctx.user != null) { + redirect(ctx, '/s/add') + } -export default Home + ctx.layout.noBackground = true + } + + render () { + return
+

A bot to tame your self-assignable Discord roles.

+
+ +

What is this? 2005?

+
+
+ +

Just click or tap.

+
+ +
+ } +}