From e758c09fbf61aa76c26472209e132692ac5afc23 Mon Sep 17 00:00:00 2001 From: Katalina Okano Date: Sat, 19 Dec 2020 20:10:23 -0500 Subject: [PATCH] feat(UI): add initial server picker --- package.json | 1 + src/common/types/storyData.ts | 16 ++-- .../atoms/collapse/Collapse.stories.tsx | 13 +++ src/design-system/atoms/collapse/Collapse.tsx | 10 +++ src/design-system/atoms/collapse/index.ts | 1 + .../atoms/typography/typography.tsx | 10 +++ .../ServerListingCard.stories.tsx | 12 +++ .../ServerListingCard.styled.ts | 89 +++++++++++++++++++ .../server-listing-card/ServerListingCard.tsx | 60 +++++++++++++ .../molecules/server-listing-card/index.ts | 1 + .../ServersListing.stories.tsx | 12 +++ .../servers-listing/ServersListing.styled.ts | 23 +++++ .../servers-listing/ServersListing.tsx | 33 +++++++ .../organisms/servers-listing/index.ts | 1 + .../templates/servers/Servers.stories.tsx | 13 +++ .../templates/servers/Servers.tsx | 14 +++ src/design-system/templates/servers/index.ts | 1 + src/pages/servers.tsx | 16 ++-- yarn.lock | 5 ++ 19 files changed, 319 insertions(+), 12 deletions(-) create mode 100644 src/design-system/atoms/collapse/Collapse.stories.tsx create mode 100644 src/design-system/atoms/collapse/Collapse.tsx create mode 100644 src/design-system/atoms/collapse/index.ts create mode 100644 src/design-system/molecules/server-listing-card/ServerListingCard.stories.tsx create mode 100644 src/design-system/molecules/server-listing-card/ServerListingCard.styled.ts create mode 100644 src/design-system/molecules/server-listing-card/ServerListingCard.tsx create mode 100644 src/design-system/molecules/server-listing-card/index.ts create mode 100644 src/design-system/organisms/servers-listing/ServersListing.stories.tsx create mode 100644 src/design-system/organisms/servers-listing/ServersListing.styled.ts create mode 100644 src/design-system/organisms/servers-listing/ServersListing.tsx create mode 100644 src/design-system/organisms/servers-listing/index.ts create mode 100644 src/design-system/templates/servers/Servers.stories.tsx create mode 100644 src/design-system/templates/servers/Servers.tsx create mode 100644 src/design-system/templates/servers/index.ts diff --git a/package.json b/package.json index db11f96..2f92e7f 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "react-is": "^17.0.1", "react-tooltip": "^4.2.11", "styled-components": "^5.2.1", + "styled-normalize": "^8.0.7", "swr": "^0.3.9" }, "devDependencies": { diff --git a/src/common/types/storyData.ts b/src/common/types/storyData.ts index daa24bc..ffe00de 100644 --- a/src/common/types/storyData.ts +++ b/src/common/types/storyData.ts @@ -140,6 +140,13 @@ export const guild: Guild = { roles: [], }; +export const roleypolyGuild: GuildSlug = { + name: 'Roleypoly', + id: '386659935687147521', + permissionLevel: 0, + icon: 'ffee638c73ff9c972554f64ca34d67ee', +}; + export const guildMap: { [x: string]: GuildSlug } = { 'emoji megaporium': { name: guild.name, @@ -147,12 +154,7 @@ export const guildMap: { [x: string]: GuildSlug } = { permissionLevel: 0, icon: guild.icon, }, - Roleypoly: { - name: 'Roleypoly', - id: '203493697696956418', - permissionLevel: 0, - icon: 'ff08d36f5aee1ff48f8377b65d031ab0', - }, + Roleypoly: roleypolyGuild, 'chamber of secrets': { name: 'chamber of secrets', id: 'aaa', @@ -234,6 +236,6 @@ export const mastheadSlugs: GuildSlug[] = guildEnum.guilds.map( id: guild.guild.id, name: guild.guild.name, icon: guild.guild.icon, - permissionLevel: idx % 3, + permissionLevel: 1 << idx % 3, }) ); diff --git a/src/design-system/atoms/collapse/Collapse.stories.tsx b/src/design-system/atoms/collapse/Collapse.stories.tsx new file mode 100644 index 0000000..d99f469 --- /dev/null +++ b/src/design-system/atoms/collapse/Collapse.stories.tsx @@ -0,0 +1,13 @@ +import { SmallTitle } from 'roleypoly/design-system/atoms/typography'; +import { Collapse } from './Collapse'; + +export default { + title: 'Atoms/Collapse', + component: Collapse, +}; + +export const collapse = (args) => ( + + Hello, small world! + +); diff --git a/src/design-system/atoms/collapse/Collapse.tsx b/src/design-system/atoms/collapse/Collapse.tsx new file mode 100644 index 0000000..3c25bcb --- /dev/null +++ b/src/design-system/atoms/collapse/Collapse.tsx @@ -0,0 +1,10 @@ +import styled, { css } from 'styled-components'; +import { onSmallScreen } from '../breakpoints'; + +export const Collapse = styled.span<{ preventCollapse?: boolean }>` + ${(props) => + !props.preventCollapse && + onSmallScreen(css` + display: none; + `)} +`; diff --git a/src/design-system/atoms/collapse/index.ts b/src/design-system/atoms/collapse/index.ts new file mode 100644 index 0000000..5fda998 --- /dev/null +++ b/src/design-system/atoms/collapse/index.ts @@ -0,0 +1 @@ +export * from './Collapse'; diff --git a/src/design-system/atoms/typography/typography.tsx b/src/design-system/atoms/typography/typography.tsx index 2c478d7..2180d63 100644 --- a/src/design-system/atoms/typography/typography.tsx +++ b/src/design-system/atoms/typography/typography.tsx @@ -96,3 +96,13 @@ export const Link = styled.a` color: ${palette.taupe600}; } `; + +export const CompletelyStylelessLink = styled.a` + color: inherit; + text-decoration: none; + :visited, + :active, + :hover { + color: inherit; + } +`; diff --git a/src/design-system/molecules/server-listing-card/ServerListingCard.stories.tsx b/src/design-system/molecules/server-listing-card/ServerListingCard.stories.tsx new file mode 100644 index 0000000..b67e35d --- /dev/null +++ b/src/design-system/molecules/server-listing-card/ServerListingCard.stories.tsx @@ -0,0 +1,12 @@ +import { roleypolyGuild } from 'roleypoly/common/types/storyData'; +import { ServerListingCard } from './ServerListingCard'; + +export default { + title: 'Molecules/Server Listing Card', + component: ServerListingCard, + args: { + guild: { ...roleypolyGuild, permissionLevel: 4 }, + }, +}; + +export const serverListingCard = (args) => ; diff --git a/src/design-system/molecules/server-listing-card/ServerListingCard.styled.ts b/src/design-system/molecules/server-listing-card/ServerListingCard.styled.ts new file mode 100644 index 0000000..1c5755b --- /dev/null +++ b/src/design-system/molecules/server-listing-card/ServerListingCard.styled.ts @@ -0,0 +1,89 @@ +import { onSmallScreen, onTablet } from 'roleypoly/design-system/atoms/breakpoints'; +import { palette } from 'roleypoly/design-system/atoms/colors'; +import { transitions } from 'roleypoly/design-system/atoms/timings'; +import { text200, text500 } from 'roleypoly/design-system/atoms/typography'; +import styled, { css } from 'styled-components'; + +export const CardLine = styled.div<{ left?: boolean }>` + justify-content: center; + align-items: center; + display: flex; + padding: 5px; + box-sizing: border-box; + + ${(props) => + props.left && + css` + flex: 1; + justify-content: flex-end; + align-items: flex-end; + `} +`; + +export const MaxWidthTitle = styled.div` + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; + +export const PermissionTagStyled = styled.div<{ hiddenOnSmall?: boolean }>` + ${text200} + display: inline-block; + background-color: ${palette.taupe200}; + padding: 4px 6px; + border-radius: 2px; + + svg { + position: relative; + top: 1px; + ${onTablet( + css` + margin-right: 2px; + ` + )} + } + + ${(props) => + props.hiddenOnSmall && + onSmallScreen( + css` + display: none; + ` + )} +`; + +export const CardBase = styled.div` + ${text500} + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background-color: ${palette.taupe300}; + overflow-x: hidden; + text-align: center; + display: flex; + align-items: center; + padding: 10px; + border-radius: 3px; + cursor: pointer; + user-select: none; + transform: translate(0); + transition: transform ease-in-out ${transitions.actionable}s, + box-shadow ease-in-out ${transitions.actionable}s, + border-color ease-in-out ${transitions.out2in}s; + box-sizing: border-box; + max-width: 98vw; + :hover { + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.25); + transform: translate(0, -1px); + } + :active { + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); + transform: translate(0); + } + + ${onTablet(css` + flex-direction: column; + justify-content: left; + `)} +`; diff --git a/src/design-system/molecules/server-listing-card/ServerListingCard.tsx b/src/design-system/molecules/server-listing-card/ServerListingCard.tsx new file mode 100644 index 0000000..c4e809a --- /dev/null +++ b/src/design-system/molecules/server-listing-card/ServerListingCard.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { GoPerson, GoStar, GoZap } from 'react-icons/go'; +import { GuildSlug, UserGuildPermissions } from 'roleypoly/common/types'; +import { Avatar, utils } from 'roleypoly/design-system/atoms/avatar'; +import { Collapse } from 'roleypoly/design-system/atoms/collapse'; +import { + CardBase, + CardLine, + MaxWidthTitle, + PermissionTagStyled, +} from './ServerListingCard.styled'; + +type ServerListingProps = { + guild: GuildSlug; +}; + +export const ServerListingCard = (props: ServerListingProps) => ( + + + + {utils.initialsFromName(props.guild.name)} + + + {props.guild.name} + + + + +); + +const PermissionTag = (props: { permissionLevel: UserGuildPermissions }) => { + switch (props.permissionLevel) { + case UserGuildPermissions.Admin: + return ( + + + Administrator + + ); + case UserGuildPermissions.Manager: + return ( + + + Role Manager + + ); + default: + return ( + + + Member + + ); + } + + return null; +}; diff --git a/src/design-system/molecules/server-listing-card/index.ts b/src/design-system/molecules/server-listing-card/index.ts new file mode 100644 index 0000000..ca3316e --- /dev/null +++ b/src/design-system/molecules/server-listing-card/index.ts @@ -0,0 +1 @@ +export * from './ServerListingCard'; diff --git a/src/design-system/organisms/servers-listing/ServersListing.stories.tsx b/src/design-system/organisms/servers-listing/ServersListing.stories.tsx new file mode 100644 index 0000000..0cf0933 --- /dev/null +++ b/src/design-system/organisms/servers-listing/ServersListing.stories.tsx @@ -0,0 +1,12 @@ +import { mastheadSlugs } from 'roleypoly/common/types/storyData'; +import { ServersListing } from './ServersListing'; + +export default { + title: 'Organisms/Servers Listing', + component: ServersListing, + args: { + guilds: mastheadSlugs, + }, +}; + +export const serversListing = (args) => ; diff --git a/src/design-system/organisms/servers-listing/ServersListing.styled.ts b/src/design-system/organisms/servers-listing/ServersListing.styled.ts new file mode 100644 index 0000000..5f31c4f --- /dev/null +++ b/src/design-system/organisms/servers-listing/ServersListing.styled.ts @@ -0,0 +1,23 @@ +import { onTablet } from 'roleypoly/design-system/atoms/breakpoints'; +import styled, { css } from 'styled-components'; + +export const ContentContainer = styled.div` + display: flex; + flex-direction: column; + max-width: calc(98vw - 15px); + padding-bottom: 25px; + ${onTablet(css` + flex-direction: row; + flex-wrap: wrap; + `)} +`; + +export const CardContainer = styled.div` + box-sizing: border-box; + margin-bottom: 5px; + ${onTablet(css` + margin: 5px; + flex-basis: 30%; + max-width: 30%; + `)} +`; diff --git a/src/design-system/organisms/servers-listing/ServersListing.tsx b/src/design-system/organisms/servers-listing/ServersListing.tsx new file mode 100644 index 0000000..e87c19f --- /dev/null +++ b/src/design-system/organisms/servers-listing/ServersListing.tsx @@ -0,0 +1,33 @@ +import Link from 'next/link'; +import * as React from 'react'; +import { GuildSlug } from 'roleypoly/common/types'; +import { sortBy } from 'roleypoly/common/utils/sortBy'; +import { CompletelyStylelessLink } from 'roleypoly/design-system/atoms/typography'; +import { ServerListingCard } from 'roleypoly/design-system/molecules/server-listing-card'; +import { CardContainer, ContentContainer } from './ServersListing.styled'; + +type ServersListingProps = { + guilds: GuildSlug[]; +}; + +export const ServersListing = (props: ServersListingProps) => ( + + {props.guilds && + sortBy(props.guilds, 'name', (a: string, b: string) => + a.toLowerCase() > b.toLowerCase() ? 1 : -1 + ).map((guild, idx) => ( + + + + + + + + ))} + +); diff --git a/src/design-system/organisms/servers-listing/index.ts b/src/design-system/organisms/servers-listing/index.ts new file mode 100644 index 0000000..cce9a58 --- /dev/null +++ b/src/design-system/organisms/servers-listing/index.ts @@ -0,0 +1 @@ +export * from './ServersListing'; diff --git a/src/design-system/templates/servers/Servers.stories.tsx b/src/design-system/templates/servers/Servers.stories.tsx new file mode 100644 index 0000000..dcf22c2 --- /dev/null +++ b/src/design-system/templates/servers/Servers.stories.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import { mastheadSlugs, user } from 'roleypoly/common/types/storyData'; +import { ServersTemplate } from '.'; + +export default { + title: 'Templates/Servers Page', + args: { + guilds: mastheadSlugs, + user: user, + }, +}; + +export const serversPage = (args) => ; diff --git a/src/design-system/templates/servers/Servers.tsx b/src/design-system/templates/servers/Servers.tsx new file mode 100644 index 0000000..bc22413 --- /dev/null +++ b/src/design-system/templates/servers/Servers.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; +import { GuildSlug } from 'roleypoly/common/types'; +import { AppShell, AppShellProps } from 'roleypoly/design-system/organisms/app-shell'; +import { ServersListing } from 'roleypoly/design-system/organisms/servers-listing/ServersListing'; + +type ServerTemplateProps = Omit & { + guilds: GuildSlug[]; +}; + +export const ServersTemplate = (props: ServerTemplateProps) => ( + + + +); diff --git a/src/design-system/templates/servers/index.ts b/src/design-system/templates/servers/index.ts new file mode 100644 index 0000000..a3a241a --- /dev/null +++ b/src/design-system/templates/servers/index.ts @@ -0,0 +1 @@ +export * from './Servers'; diff --git a/src/pages/servers.tsx b/src/pages/servers.tsx index ed0b0cf..4bd731b 100644 --- a/src/pages/servers.tsx +++ b/src/pages/servers.tsx @@ -1,11 +1,17 @@ -import { AppShell } from 'roleypoly/design-system/organisms/app-shell'; +import Head from 'next/head'; +import { ServersTemplate } from 'roleypoly/design-system/templates/servers'; import { useAppShellProps } from 'roleypoly/providers/appShellData'; -export default () => { +const Servers = () => { const { appShellProps } = useAppShellProps(); return ( - -
-
+ <> + + Viewing your servers - Roleypoly + + + ); }; + +export default Servers; diff --git a/yarn.lock b/yarn.lock index 952b006..aab3243 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12966,6 +12966,11 @@ styled-jsx@3.3.2: stylis "3.5.4" stylis-rule-sheet "0.0.10" +styled-normalize@^8.0.7: + version "8.0.7" + resolved "https://registry.yarnpkg.com/styled-normalize/-/styled-normalize-8.0.7.tgz#e883bff6a0c59a65a39365a4eb9c6cf48372c61f" + integrity sha512-qQV4O7B9g7ZUnStCwGde7Dc/mcFF/pz0Ha/LL7+j/r6uopf6kJCmmR7jCPQMCBrDkYiQ4xvw1hUoceVJkdaMuQ== + stylelint-config-prettier@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-8.0.2.tgz#da9de33da4c56893cbe7e26df239a7374045e14e"