Skip to content

Commit

Permalink
Implement main organism components for all community page sections
Browse files Browse the repository at this point in the history
This commit implements all main organism components for the community
page sections.

>> Hero

The first section is the "Hero" of the community page that renders a
description about the page's purpose and an animated SVG component.

>> Chats

The 2nd section is about Nord's community chats where each platform is
represented as card rendered in a two-column grid layout. Each card
contains the platforms official logo, colorized with colors of the
respective brand guidelines, a short summary about the platform/service
and a link component that forwards to the community within the platform.
Next to the official main channel each platform also provides
sub-channels for all port projects.

The following community chats of Nord are represented:

- Arctic Ice Studio's official community on "Spectrum" (1)
- Nord's official Keybase team chat (2)
- Nord's official Slack (3) workspace
- Nord's official Discord (4) space

>> Content

The 3th and also last section presents platforms where the community can
create content and ask questions for and about Nord. Next to the
official documentation these are knowledge bases also powered by
community. Like the chat platforms in the previous section each
platform/service is represented as card including the same information,
rendered by the same components, and also structured in a two-column
grid layout.
Next to this, each card includes the latest three items (questions,
posts etc.) of the platform's community rendered as link component with
the item's title and metadata like tags, the name of the author and the
relative creation date/time.

The following community platforms of Nord are represented:

- Latest questions from Stack Overflow (5) tagged with `nord` or
  `nordtheme`
- Nord's official "/r/nordtheme" (6) subreddit

All data is fetched from the official REST APIs from the respective
platform using the axios (7) client. The processing of any date/time
data is handled with date-fns (8), a modern and more lightweight ES6+
library with tree-shaking support that'll be used project-wide for Nord
Docs to handle any other date/time data like e.g. blog posts metadata.

>> Responsive Design

All sections follow the responsive design concept (9) to adjust the
rendered content based on the available width and provide an optimal UX
on smaller viewports.

References:
  (1) https://spectrum.chat/arcticicestudio
  (2) https://keybase.io/team/nord.chat
  (3) https://arcticicestudio.slack.com
  (4) https://discordapp.com
  (5) https://stackoverflow.com/questions/tagged/nord+or+nordtheme
  (6) https://www.reddit.com/r/nordtheme
  (7) https://github.com/axios/axios
  (8) https://github.com/date-fns/date-fns
  (9) #52

Associated epic: GH-63
GH-115
  • Loading branch information
arcticicestudio committed Jan 26, 2019
1 parent 30dd448 commit 06951a4
Show file tree
Hide file tree
Showing 43 changed files with 1,216 additions and 157 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import React from "react";

import Link from "atoms/core/Link";
import { Content } from "containers/core/Section";
import { ROUTE_COMMUNITY } from "config/routes/mappings";
import { sectionIdFor } from "utils";
import { Discord, Keybase, Slack, Spectrum } from "atoms/core/vectors/icons";
import { links } from "data/project";

import { Section } from "../../shared";
import { ChatCard, Grid } from "./styled";
import WaveDivider from "./styled/WaveDivider";

const SECTION_ID = sectionIdFor(ROUTE_COMMUNITY, 1);

/**
* The component that represents the chat channel section of the community page.
* All logos and colors are based on the official branding guidelines of the respective brand.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
* @see https://slack.com/media-kit
* @see https://www.redditinc.com/press#publish
*/
const SectionChannelCards = () => (
<Section gapWidth={1} id={SECTION_ID} variant="primary">
<Content centered decorated>
<Grid>
<ChatCard logoColor="#7b16ff" logoComponent={Spectrum} title="Spectrum" url={links.community.spectrum.url}>
A simple, powerful real-time chat platform to build, grow, manage and measure any kind of online communities
by providing a modern, scaling and easy to use cross-device app.
</ChatCard>
<ChatCard logoColor="#4c8eff" logoComponent={Keybase} title="Keybase" url={links.community.keybase.url}>
Keybase is a open source security platform powered by public-key cryptography providing end-to-end encrypted
chats, file shares, team tools and many more features across all devices.
</ChatCard>
<ChatCard logoColor="#36c5f0" logoComponent={Slack} title="Slack">
Slack is is where work flows &mdash; a cloud-based collaboration hub for communities that provides
integrations, tools and services to keep teams connected and allows to easily store and share information,
discussions and important documents in one searchable place to get things done.
</ChatCard>
<ChatCard logoColor="#7289DA" logoComponent={Discord} title="Discord">
Discord is a all-in-one voice, text and video chat for communities mainly focused on gaming and{" "}
<Link href="https://discordapp.com/open-source">open source software development</Link> that serves as a
modern, crystal clear and secure communication channel across all devices.
</ChatCard>
</Grid>
</Content>
<WaveDivider />
</Section>
);

export default SectionChannelCards;
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
* License: MIT
*/

export { default } from "./SectionLanding";
export { default } from "./SectionChat";
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import styled from "styled-components";

import { CardAction } from "../../../shared";

/**
* A container component for an card item action.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
*/
const Action = styled(CardAction)`
${({ theme }) => theme.media.tabletPortrait`
display: flex;
align-items: flex-end;
`};
`;

export default Action;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import React from "react";

import Button from "atoms/core/Button";
import { H3, P } from "atoms/core/HTMLElements";

import { Card, CardLogo as Logo } from "../../../shared";
import Action from "./Action";

/**
* A card component that renders information about a Nord chat platform.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
*/
const ChatCard = ({ children, logoColor, logoComponent: SvgLogo, title, url, ...passProps }) => (
<Card {...passProps}>
<Logo logoColor={logoColor}>
<SvgLogo />
</Logo>
<div>
<H3>{title}</H3>
<P>{children}</P>
</div>
<Action>{url ? <Button href={url}>Join Nord on {title}</Button> : <Button disabled>Coming soon!</Button>}</Action>
</Card>
);

export default ChatCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import styled from "styled-components";

/**
* A responsive grid for chat card components.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
*/
const Grid = styled.div`
display: grid;
grid-gap: 4em;
${({ theme }) => theme.media.tabletLandscape`
grid-template-columns: repeat(2, 1fr);
`};
`;

export default Grid;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import styled from "styled-components";

import { WaveWobbly } from "atoms/core/vectors/divider";
import { colors, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme";

const fillColor = themedMode({
[MODE_BRIGHT_SNOW_FLURRY]: colors.background.sectioning.secondary[MODE_BRIGHT_SNOW_FLURRY],
[MODE_DARK_NIGHT_FROST]: colors.background.sectioning.secondary[MODE_DARK_NIGHT_FROST]
});

/**
* A "wobbly" vector wave to render a visual differentiation to the next section.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
*/
const WaveDivider = styled(WaveWobbly)`
fill: ${fillColor};
margin-bottom: -1px;
transition: fill ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out;
`;

export default WaveDivider;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import ChatCard from "./ChatCard/ChatCard";
import Grid from "./Grid";

export { ChatCard, Grid };
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import React, { PureComponent } from "react";
import axios from "axios";
import { formatDistance, fromUnixTime } from "date-fns";

import { WaveFooter } from "atoms/core/vectors/divider";
import Section, { Content } from "containers/core/Section";
import { ROUTE_COMMUNITY } from "config/routes/mappings";
import { decodeCodeCharacterHtmlEntities, sectionIdFor } from "utils";
import { Reddit, StackOverflow } from "atoms/core/vectors/icons";
import { links, tags } from "data/project";

import { Grid, RedditCard, StackOverflowCard } from "./styled";

const SECTION_ID = sectionIdFor(ROUTE_COMMUNITY, 2);
const stackOverflowTagUrl = `https://stackoverflow.com/questions/tagged/${tags.join("+or+")}`;

/**
* The component that represents the content section of the community page.
*
* The rendered grid will extend to use 2 rows only if at least one card contains fetched data. This prevents the
* layout problem that one card will be streched and deformed when there was a error when fetching the data while the
* other element card renders fetched data. For example while fetching the data from the Reddit API a error about
* missing CORS headers might occur or the request is blocked by the browser's security features (Firefox Content
* Blocking).
* This would result in no data for the component showing the latest Reddit posts "stretching" it down to the size of
* the other component in the grid that was able to fetch and render data.
* Therefore the grid will adjust the used rows based on the result of the data fetch requests to ensure a ncie layout
* for both elements even when only one card component renderes fetched data.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
* @see https://stackoverflow.com/company/logos
* @see https://www.redditinc.com/press#publish
*/
export default class SectionContent extends PureComponent {
state = {
stackOverflowQuestions: [],
redditPosts: []
};

async componentDidMount() {
const [stackOverflowQuestions, redditPosts] = await axios.all([
this.fetchStackOverflowQuestions(),
this.fetchRedditPosts()
]);
this.setState({ stackOverflowQuestions, redditPosts });
}

fetchStackOverflowQuestions = async () => {
let questions = [];
try {
const latestQuestions = await axios.get("https://api.stackexchange.com/2.2/search", {
params: {
pagesize: 3,
order: "desc",
sort: "creation",
tagged: tags.join(";"),
site: "stackoverflow"
}
});
questions = latestQuestions.data.items.map(({ answer_count: answerCount, link, tags: questionTags, title }) => ({
answerCount,
link,
title: decodeCodeCharacterHtmlEntities(title),
tags: questionTags
}));
} catch (error) {
console.error("Unexpected problems while fetching content data from Stack Overflow!", error);
}
return questions;
};

fetchRedditPosts = async () => {
let posts = [];
try {
const latestPosts = await axios.get(`https://www.reddit.com/r/${links.community.reddit.id}/new.json`, {
params: { limit: 3 }
});
posts = latestPosts.data.data.children.map(
({ data: { author, created_utc: createdUtc, num_comments: numComments, title, url } }) => ({
author,
created: formatDistance(fromUnixTime(createdUtc), Date.now(), { addSuffix: true }),
numComments,
title,
url
})
);
} catch (error) {
console.error("Unexpected problems while fetching content data from Reddit!", error);
}
return posts;
};

render() {
const { stackOverflowQuestions, redditPosts } = this.state;
return (
<Section id={SECTION_ID} variant="secondary">
<Content centered>
<Grid isExtended={stackOverflowQuestions.length || redditPosts.length}>
<StackOverflowCard
brandColor="#0095ff"
logoColor="#ff6801"
logoComponent={StackOverflow}
questions={stackOverflowQuestions}
title="Stack Overflow"
url={stackOverflowTagUrl}
>
Stack Overflow is the largest, most trusted online community for developers to learn and share their
knowledge to help solve coding problems, develop new skills and build their careers on a wide range of
topics in computer programming.
</StackOverflowCard>
<RedditCard
brandColor="#0079D3"
logoColor="#FF4500"
logoComponent={Reddit}
posts={redditPosts}
title="Reddit"
url={links.community.reddit.url}
>
Reddit is home to thousands of communities, endless conversation, and authentic human connection where
millions of people around the world post, vote, chat and comment in communities organized around their
interests.
</RedditCard>
</Grid>
</Content>
<WaveFooter />
</Section>
);
}
}
10 changes: 10 additions & 0 deletions src/components/organisms/page/community/SectionContent/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

export { default } from "./SectionContent";
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]>
* Copyright (C) 2018-present Sven Greb <[email protected]>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import styled from "styled-components";

/**
* A configurable and responsive grid for card components.
*
* @author Arctic Ice Studio <[email protected]>
* @author Sven Greb <[email protected]>
* @since 0.7.0
*/
const Grid = styled.div`
display: grid;
grid-gap: 4em;
${({ theme }) => theme.media.tabletLandscape`
grid-template-columns: repeat(2, 1fr);
${({ isExtended }) => isExtended && "grid-template-rows: repeat(2, auto)"};
`};
`;

export default Grid;
Loading

0 comments on commit 06951a4

Please sign in to comment.