diff --git a/src/assets/images/resources/logoPM.png b/src/assets/images/resources/logoPM.png new file mode 100644 index 0000000..7824140 Binary files /dev/null and b/src/assets/images/resources/logoPM.png differ diff --git a/src/components/blocks/Menu/Menu.scss b/src/components/blocks/Menu/Menu.scss index 197daab..6e3a795 100644 --- a/src/components/blocks/Menu/Menu.scss +++ b/src/components/blocks/Menu/Menu.scss @@ -69,6 +69,10 @@ &:hover > &__icon { color: $primary; } + + .resourceCards { + left: -272px; + } } &__menu { diff --git a/src/components/blocks/ResourceCards/ResourceCards.js b/src/components/blocks/ResourceCards/ResourceCards.js new file mode 100644 index 0000000..fac3543 --- /dev/null +++ b/src/components/blocks/ResourceCards/ResourceCards.js @@ -0,0 +1,47 @@ +// @flow +import React, { Component } from 'react'; +import { Mixpanel } from '../../../Mixpanel'; +import { ResourceCard } from '../../elements'; + +import './ResourceCards.scss'; + +type ResourceCardProps = Object; // TODO - define real props inside Object e.g. { title: string... } + +type Props = { + key: string, + categoryTitle: string, + onCardClick: Function, + resourceCards: Array, // TODO - define real props inside Object e.g. { title: string... } +}; + +export default class ResourceCards extends Component { + render() { + const { key, categoryTitle, resourceCards } = this.props; + + return ( +
+

{categoryTitle}

+
+ {resourceCards.map(resourceCard => { + return ( + + ); + })} +
+
+ ); + } + + onClick = (resourceCard: ResourceCardProps) => { + Mixpanel.track(`Onboarding: ${resourceCard.title}`); + + this.props.onCardClick(); + }; +} diff --git a/src/components/blocks/ResourceCards/ResourceCards.scss b/src/components/blocks/ResourceCards/ResourceCards.scss new file mode 100644 index 0000000..adb7770 --- /dev/null +++ b/src/components/blocks/ResourceCards/ResourceCards.scss @@ -0,0 +1,24 @@ +@import '../../../styles/main'; + +.resourceCards { + @include col; + @include padding(left, 3); + @include padding(top, 4); + + h4 { + @include row; + @include padding(top, 5); + @include padding(bottom, 3); + @include padding(left, 1); + text-align: left; + } + + &__cards { + @include wrap; + @include padding(bottom, 5); + + @media (min-width: $screen-sm-min) { + // + } + } +} diff --git a/src/components/blocks/ResourceMenu/ResourceMenu.js b/src/components/blocks/ResourceMenu/ResourceMenu.js new file mode 100644 index 0000000..f1660d4 --- /dev/null +++ b/src/components/blocks/ResourceMenu/ResourceMenu.js @@ -0,0 +1,74 @@ +// @flow +import React, { Component } from 'react'; +import { MenuItem } from '../../elements'; + +import './ResourceMenu.scss'; + +type Props = { + onMenuItemClick: Function, + menuItems: Object, // TODO - define real props inside Object e.g. { title: string... } +}; + +type State = { + activeItem: ?string, +}; + +type MenuItemProps = { + id: string, + title: string, + onMenuItemClick: Function, + menuItems: Object, +}; + +export default class ResourceMenu extends Component { + constructor(props: Props) { + super(props); + + this.state = { + activeItem: null, + }; + this.handleMenuItemClick = this.handleMenuItemClick.bind(this); + } + + componentWillMount() { + // check writing prompts enabled or disabled + // const enableWritingPrompts = persistedStore.get(WRITING_PROMPTS_ENABLED) + // if (enableWritingPrompts) { + // this.setState({ menuHidden: true, revealMenu: false }) + // } + } + + render() { + const { menuItems } = this.props; + const { activeItem } = this.state; + + return ( +
+
+
+ {menuItems.map(menuItem => { + const isActive = activeItem === menuItem.id; + return ( + + ); + })} +
+
+
+ ); + } + + // handleMenuItemClick = (id: string) => { + handleMenuItemClick = (menuItem: MenuItemProps) => { + this.setState({ + activeItem: menuItem.id, + }); + + this.props.onMenuItemClick(); + }; +} diff --git a/src/components/blocks/ResourceMenu/ResourceMenu.scss b/src/components/blocks/ResourceMenu/ResourceMenu.scss new file mode 100644 index 0000000..4233acc --- /dev/null +++ b/src/components/blocks/ResourceMenu/ResourceMenu.scss @@ -0,0 +1,30 @@ +@import '../../../styles/main'; + +.resourceMenu { + @include background-very-light; + @include col; + @include fade-in; + @include padding(top, 7); + transition: box-shadow 0.3s ease-in-out; + + &__menu { + @include flex; + @include padding(left, reset); + @include transition-in-out; + box-shadow: inset -4px 0 10px #e0e0e024; + + @media (min-width: $screen-sm-min) { + @include padding(left, 2); + } + + @media (min-width: $screen-md-min) { + @include padding(left, 5); + } + + &_list { + @include col; + @include padding(top bottom, 2); + width: 100%; + } + } +} diff --git a/src/components/blocks/index.js b/src/components/blocks/index.js index b68286f..6886eab 100644 --- a/src/components/blocks/index.js +++ b/src/components/blocks/index.js @@ -12,6 +12,8 @@ export { default as OnboardingCards } from './OnboardingCards/OnboardingCards.js export { default as ProductShowcase } from './ProductShowcase/ProductShowcase'; export { default as ReferralBlock } from './ReferralBlock/ReferralBlock'; export { default as RefereeInput } from './RefereeInput/RefereeInput'; +export { default as ResourceCards } from './ResourceCards/ResourceCards.js'; +export { default as ResourceMenu } from './ResourceMenu/ResourceMenu.js'; export { default as Section } from './Section/Section.js'; export { default as SectionSummary } from './SectionSummary/SectionSummary.js'; export { default as Testimonials } from './Testimonials/Testimonials'; diff --git a/src/components/elements/MenuItem/MenuItem.scss b/src/components/elements/MenuItem/MenuItem.scss index 3ecea95..9720f04 100644 --- a/src/components/elements/MenuItem/MenuItem.scss +++ b/src/components/elements/MenuItem/MenuItem.scss @@ -7,19 +7,16 @@ @include margin(top bottom, 0); @include row; @include transition-in-out; - max-width: 288px; // Shared SCSS properties &__row { @include padding(top bottom, 1); @include padding(left, 1); - @include padding(right, 1); @include row; align-items: center; justify-content: space-between; max-height: 24px; - min-width: 248px; text-align: left; &:hover { @@ -30,11 +27,12 @@ // Shared SCSS properties &__title { @include cursor-pointer; + @include flex; @include padding(top bottom, 1); @include padding(left, 0); @include transition-in-out; - min-width: 220px; text-align: left; + width: 100%; } // Shared SCSS properties diff --git a/src/components/elements/ResourceCard/ResourceCard.js b/src/components/elements/ResourceCard/ResourceCard.js new file mode 100644 index 0000000..eed57f0 --- /dev/null +++ b/src/components/elements/ResourceCard/ResourceCard.js @@ -0,0 +1,47 @@ +// @flow +import React, { Component } from 'react'; +import './ResourceCard.scss'; + +import { Icon, Card } from '..'; + +type Props = { + onClick: Function, + logo: string, + logoAlt: string, + title: string, + description: string, +}; + +export default class ResourceCard extends Component { + render() { + const { onClick, logo, logoAlt, title, description } = this.props; + + return ( +
+ +
+
+ {logoAlt} +
+
+
{title}
+

{description}

+
+ +
+
+ +
+
+
+ ); + } +} diff --git a/src/components/elements/ResourceCard/ResourceCard.scss b/src/components/elements/ResourceCard/ResourceCard.scss new file mode 100644 index 0000000..fda5c7f --- /dev/null +++ b/src/components/elements/ResourceCard/ResourceCard.scss @@ -0,0 +1,111 @@ +@import '../../../styles/main'; + +.resourceCard { + @include margin(all, 0); + max-width: 288px; + min-width: 240px; + + &__bg { + @include background-dark; + @include card-image-corner-radius; + @include flex; + min-height: 96px; + width: 100%; + + // Logo container + &_container { + @include background-light; + @include border-white; + @include circular-radius; + @include flex; + @include position-center; + height: 64px; + left: 10px; + position: relative; + top: 48px; + width: 64px; + } + + // Logo image + &_logo { + width: 66%; + } + } + + &__title, + &__description { + text-align: left; + } + + &__title { + @include padding(top, 3); + @include padding(left right, 1); + } + + &__description { + @include text; + @include small; + @include padding(left right, 1); + @include padding(bottom, 2); + } + + &__open { + @include transition-in-out; + bottom: 4px; + left: 85%; + opacity: 0; + position: relative; + } + + &__icon { + color: $primary; + } + + &__share { + @include circular-radius; + @include transition-in-out; + border: solid 2px $white-transparent; + bottom: 204px; + left: 83%; + opacity: 0; + position: relative; + } + + // On Hover + + &:hover &__open { + @include transition-in; + bottom: 8px; + opacity: 100%; + } + + &:hover &__share { + @include transition-in; + bottom: 200px; + opacity: 100%; + + &:hover { + border: solid 2px $white-low-opacity; + opacity: 80%; + } + } + + &:hover &__title { + color: $primary; + } +} + +// Card Overrides + +.card { + @include margin(all, reset); +} + +.cardDefault { + @include padding(all, reset); + + &:hover { + border-color: $light-grey; + transform: translateY(-1px); + } +} diff --git a/src/components/elements/index.js b/src/components/elements/index.js index 4cb126d..5149511 100644 --- a/src/components/elements/index.js +++ b/src/components/elements/index.js @@ -9,5 +9,6 @@ export { default as Loading } from './Loading/Loading'; export { default as MenuItem } from './MenuItem/MenuItem.js'; export { default as Modal } from './Modal/Modal.js'; export { default as OnboardingCard } from './OnboardingCard/OnboardingCard.js'; +export { default as ResourceCard } from './ResourceCard/ResourceCard.js'; export { default as Tag } from './Tag/Tag'; export { default as Toggle } from './Toggle/Toggle'; diff --git a/src/components/views/Resources/Resources.js b/src/components/views/Resources/Resources.js new file mode 100644 index 0000000..e0ffffc --- /dev/null +++ b/src/components/views/Resources/Resources.js @@ -0,0 +1,114 @@ +// @flow +import React, { Component } from 'react'; + +import { ResourceMenu, ResourceCards } from '../../blocks'; + +import { Button } from '../../elements'; + +import './Resources.scss'; + +import logoPM from '../../../assets/images/resources/logoPM.png'; + +// Menu Items +const menuItems = [ + { + id: '1', + title: 'Vision', + icon: 'keyboard_arrow_right', + }, + { + id: '2', + title: 'Strategy', + icon: 'keyboard_arrow_right', + }, + { + id: '3', + title: 'Roadmap', + icon: 'add', + }, +]; + +// Resources Card Content +const resourceCards = [ + { + id: '1', + title: 'Article Title', + description: + 'A long description about this article. And here is some more text.', + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '2', + title: 'Article Title', + description: + 'A long description about this article. And here is some more text.', + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '3', + title: 'Article Title', + description: + 'A long description about this article. And here is some more text.', + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '4', + title: 'Article Title', + description: + 'A long description about this article. And here is some more text.', + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '5', + title: 'Article Title', + description: + 'A long description about this article. And here is some more text.', + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '6', + title: 'Article Title', + description: + 'A long description about this article. And here is some more text.', + logo: logoPM, + logoAlt: 'Article Title', + }, +]; + +export default class Resources extends Component { + render() { + return ( +
+
+ +
+
+ +
+
+ +
+
+ ); + } + + handleMenuSelect = () => { + // console.log("click menu item"); + }; + + handleCardClick = () => { + // console.log("card click"); + }; +} diff --git a/src/components/views/Resources/Resources.scss b/src/components/views/Resources/Resources.scss new file mode 100644 index 0000000..b1f51e1 --- /dev/null +++ b/src/components/views/Resources/Resources.scss @@ -0,0 +1,23 @@ +@import '../../../styles/main'; + +.resources { + @include row; + + &__btn { + position: absolute; + right: 24px; + top: 16px; + z-index: 100; + } + + &__menuwrap { + min-width: 27%; + position: fixed; + } + + &__cardswrap { + left: 27%; + position: relative; + width: 70%; + } +} diff --git a/src/components/views/index.js b/src/components/views/index.js index bed674f..9e716d6 100644 --- a/src/components/views/index.js +++ b/src/components/views/index.js @@ -7,3 +7,4 @@ export { default as Privacy } from './Privacy/Privacy'; export { default as Register } from './Register/Register'; export { default as Referee } from './Referee/Referee'; export { default as Referral } from './Referral/Referral'; +export { default as Resources } from './Resources/Resources'; diff --git a/src/styles/atoms/_colors.scss b/src/styles/atoms/_colors.scss index 58987ff..0b1c142 100644 --- a/src/styles/atoms/_colors.scss +++ b/src/styles/atoms/_colors.scss @@ -16,3 +16,7 @@ $modal-background: rgba(0, 0, 0, 0.54); // State $error: #ff7979; $success: #a2ffd4; + +// Share Circle +$white-transparent: #fff0; +$white-low-opacity: #ffffff15; diff --git a/src/styles/atoms/_flex.scss b/src/styles/atoms/_flex.scss index f5ad550..3791c87 100644 --- a/src/styles/atoms/_flex.scss +++ b/src/styles/atoms/_flex.scss @@ -38,6 +38,12 @@ $column: $col; flex-direction: row; } +// Used for grids +@mixin wrap { + flex-wrap: wrap; + overflow: scroll; +} + @mixin position-center { align-items: center; justify-content: center; @@ -57,6 +63,7 @@ $column: $col; } @mixin wrap { + @extend %flex; flex-wrap: wrap; overflow: auto; } diff --git a/src/styles/atoms/_text.scss b/src/styles/atoms/_text.scss index 7f60b28..80c0dd2 100644 --- a/src/styles/atoms/_text.scss +++ b/src/styles/atoms/_text.scss @@ -78,6 +78,7 @@ h4 { @extend %header-text; font-family: 'Karla', sans-serif; font-size: 17px; + letter-spacing: 1px; } h5 { diff --git a/stories/resourceCard.stories.js b/stories/resourceCard.stories.js new file mode 100644 index 0000000..f2ec4b5 --- /dev/null +++ b/stories/resourceCard.stories.js @@ -0,0 +1,73 @@ +import React from "react"; + +import { storiesOf } from "@storybook/react"; +import { action } from "@storybook/addon-actions"; +import { ResourceCard } from '../src/components/elements' +import { ResourceCards } from '../src/components/blocks' + +import logoPM from '../src/assets/images/resources/logoPM.png'; + +// Onboarding Card Content +const resourceCards = [ + { + id: '1', + title: 'Article Title', + description: "A long description about this article. And here is some more text.", + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '2', + title: 'Article Title', + description: "A long description about this article. And here is some more text.", + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '3', + title: 'Article Title', + description: "A long description about this article. And here is some more text.", + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '4', + title: 'Article Title', + description: "A long description about this article. And here is some more text.", + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '5', + title: 'Article Title', + description: "A long description about this article. And here is some more text.", + logo: logoPM, + logoAlt: 'Article Title', + }, + { + id: '6', + title: 'Article Title', + description: "A long description about this article. And here is some more text.", + logo: logoPM, + logoAlt: 'Article Title', + }, +]; + +storiesOf("Elements/Resources", module) + .add("Resource Card", () => ( + + )) + .add("Resource Cards", () => ( + + )) +; diff --git a/stories/resources.stories.js b/stories/resources.stories.js new file mode 100644 index 0000000..2d04733 --- /dev/null +++ b/stories/resources.stories.js @@ -0,0 +1,12 @@ +import React from "react"; + +import { storiesOf } from "@storybook/react"; +// import { action } from "@storybook/addon-actions"; +import { Resources } from '../src/components/views' + +storiesOf("Views/Resources", module) + .add("Resources", () => ( + + )) +;