First commit

This commit is contained in:
2019-10-19 00:53:52 +05:30
parent 60a6e378ad
commit 249bd0aaa9
66 changed files with 16604 additions and 0 deletions

13081
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

31
package.json Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "picturestory-v2",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.10.2",
"react-dom": "^16.10.2",
"react-scripts": "3.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

43
public/index.html Normal file
View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

25
public/manifest.json Normal file
View File

@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

2
public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *

View File

@@ -0,0 +1,4 @@
.c-login {
// Root Class. Contains all core styles, typically for the component's
// wrapper element.
}

View File

@@ -0,0 +1,40 @@
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
class Login extends React.Component {
render() {
const {
className,
text
} = this.props
const classes = classNames('c-login', {
// 'c--modifier': bool ? true : false
}, className)
return (
<div className={classes}>
I am an example! {text}
</div>
)
}
}
Login.propTypes = {
/**
* PropTypes comments are REQUIRED for components to be included
* in the styleguide
*/
text: PropTypes.string.isRequired,
/**
* Adds values to the attribute of the root element
*/
className: PropTypes.string,
}
export default Login

View File

View File

@@ -0,0 +1,6 @@
.c-page-loader__offline {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
export class PageLoader extends React.Component {
render() {
return (
<div className="c-page-loader">
{/* <SkeletonBlock height="100vh" width="100vw" /> */}
</div>
)
}
}
PageLoader.propTypes = {
}
export default PageLoader

View File

@@ -0,0 +1,31 @@
import React from 'react'
import {shallow} from 'enzyme'
import {PageLoader} from './index'
import SkeletonBlock from 'progressive-web-sdk/dist/components/skeleton-block'
import DangerousHTML from 'progressive-web-sdk/dist/components/dangerous-html'
import sinon from 'sinon'
test('PageLoader renders a Skeleton', () => {
const wrapper = shallow(<PageLoader />)
expect(wrapper.length).toBe(1)
expect(wrapper.find(SkeletonBlock).length).toBe(1)
})
test('PageLoader renders a DangerousHTML', () => {
const wrapper = shallow(<PageLoader error={new Error('offline')} />)
expect(wrapper.length).toBe(1)
expect(wrapper.find(SkeletonBlock).length).toBe(0)
expect(wrapper.find(DangerousHTML).length).toBe(1)
expect(wrapper.find('div.c-page-loader__offline > p').length).toBe(1)
})
test('PageLoader retries to load component on failure', () => {
const retry = sinon.stub().returns(Promise.resolve())
const wrapper = shallow(
<PageLoader error={new Error('offline')} retry={retry} offlineModeStartTime={123} />
)
expect(retry.called).toBe(false)
wrapper.setProps({offlineModeStartTime: null})
expect(retry.called).toBe(true)
})

39
src/app/styles/_base.scss Normal file
View File

@@ -0,0 +1,39 @@
// Project-Wide Base Styles
// ===
// General
// ---
//
// These cover generic styles that affect your entire site, e.g. html, body,
// [attribute-selectors], etc.
@import 'base/general';
// Typography
// ---
//
// Styles for your text, headers, links, etc.
@import 'base/typography';
// Forms
// ---
//
// Styles for your forms, inputs, selects, radio buttons, checkboxes, fields,
// legends, etc.
@import 'base/forms';
// Lists
// ---
@import 'base/lists';
// Tables
// ---
@import 'base/tables';

View File

@@ -0,0 +1,8 @@
// Components
// ===
// @import '../components/footer/style';
// @import '../components/header/style';
// @import '../components/email-subscribe/style';
// @import '../components/page-loader/style';
// @import '../preloader/preload';

View File

@@ -0,0 +1,7 @@
// Pages
// ===
@import '../index';
// @import '../pages/home/style';
// @import '../pages/product-list/style';
// @import '../pages/product-details/style';

View File

@@ -0,0 +1,21 @@
// Themes
// ===
// Progressive Web Themes
// ---
//
// All styles for the Progressive Web SDK components live here. This includes
// the component's base styles (that come from the SDK node module) as well as
// their locally defined themes.
@import 'themes/pw-components';
// Other Project Themes
// ---
//
// Project specific theme styles can be added here. For example, if your site
// styles unique to the different localizations, or if different categories of
// the site require unique themes.
//
// @import 'themes/your-theme';

View File

@@ -0,0 +1,25 @@
// Utilities
// ===
//
// Use wrap-at-root mixin to allow overriding existing styles with extreme
// specificity while keeping source code clean and readable. Does not override
// !important or inline styles; those must be dealt with separately.
@import 'base/mixins';
@include wrap-at-root("#app", 1) {
@import 'utilities/border';
@import 'utilities/box-shadow';
@import 'utilities/color';
@import 'utilities/flexbox';
@import 'utilities/heading';
@import 'utilities/layout';
@import 'utilities/margin';
@import 'utilities/padding';
@import 'utilities/text-content';
@import 'utilities/text';
@import 'utilities/display';
@import 'utilities/visibility';
@import 'utilities/z-index';
}

View File

@@ -0,0 +1,221 @@
// Project-Wide Variables
// ===
//
// Edit these as needed. Some guidelines:
//
// - Names should be lowercase and dash-separated;
// - Qualifiers should be added to the beginning of related variables: use
// `$small-font-size`, not `$font-size-small`;
// - Numeric scales should use increments of 10; these numbers are arbitrary and
// should not map to actual values. If really necessary, additional values can
// be added in between, e.g. $neutral-15 between 10 and 20.
//
//
// Table of Contents
// ---
//
// [AAA] Basic Layout
// [BBB] Responsive Layout
// [CCC] Typography
// [DDD] Color Palette
// [EEE] Appearance
// [FFF] Z-Index
// [GGG] Shorthands
// [AAA] Basic Layout
// ---
// Basic unit for spacing and alignment; 6 to 12px recommended. Apply in whole
// or half multiples.
$sub-unit: 4px;
$unit: 8px;
// Standard tap-target size
$tap-size: 44px;
// Container max-width.
$max-width: 1280px;
// Content Height Calculations
$header-height: 64px;
$footer-height: 173px;
$content-height: calc(100vh - #{$header-height} - #{$footer-height});
// [BBB] Responsive Layout
// ---
//
// Media query breakpoints and grid setup. Please see Mobify's Responsive Best
// Practices doc here: https://bit.ly/2tmRnEi, and our Responsive Grid
// documentation here: http://docs.mobify.com/latest/guides/responsive-grid/
//
// Note: $small-breakpoint isn't needed, since it is 0px
$medium-breakpoint: 600px;
$large-breakpoint: 960px;
$xlarge-breakpoint: $max-width;
$susy: (
// Add color to show the columns and gutters
'svg-grid-colors': hsl(0, 0%, 95%),
'columns': susy-repeat(4),
'gutters': 12px
);
$medium-layout: (
'svg-grid-colors': hsl(0, 0%, 95%),
'columns': susy-repeat(12),
'gutters': 12px
);
$large-layout: (
'svg-grid-colors': hsl(0, 0%, 95%),
'columns': susy-repeat(12),
'gutters': 24px
);
// [CCC] Typography
// ---
$font-family: 'San Francisco', 'Roboto', 'Fira Sans', 'Segoe UI', sans-serif;
$header-font-family: 'Avenir Next Condensed', 'Roboto Condensed', 'Helvetica Neue', 'Roboto', sans-serif;
$loaded-header-font-family: 'Roboto', $header-font-family;
// Line height
$huge-line-height: 32px;
$bigger-line-height: 28px;
$big-line-height: 24px;
$line-height: 20px;
$small-line-height: 16px;
$smaller-line-height: 12px;
$tiny-line-height: 8px;
// Font sizes
$huge-font-size: 28px;
$bigger-font-size: 24px;
$big-font-size: 20px;
$font-size: 16px;
$small-font-size: 14px;
$smaller-font-size: 12px;
$tiny-font-size: 8px;
// Font weight
$thin-font-weight: 100;
$extra-light-font-weight: 200;
$light-font-weight: 300;
$regular-font-weight: 400;
$medium-font-weight: 500;
$semi-bold-font-weight: 600;
$bold-font-weight: 700;
// [DDD] Color Palette
// ---
// Neutrals
$neutral-00: #fff;
$neutral-10: #f7f7f7;
$neutral-15: #eee;
$neutral-20: #d5d5d5;
$neutral-30: #bfbfbf;
$neutral-40: #999;
$neutral-50: #696969;
$neutral-60: #333;
$neutral-70: #000;
// Brand colors
$brand-color: #017e9b; // blue
$secondary-brand-color: #005569;
$tertiary-brand-color: #83bdcb;
$quaternary-brand-color: #bfdfe6;
// UI Kit colors
$ui-brand-color: #005c83; // dark blue
// Accent colors
$accent-color: #ff852c; // orange
$light-accent-color: lighten($accent-color, 15%);
$dark-accent-color: darken($accent-color, 15%);
// Primary Action
$primary-action-color: #dc0a3c;
$light-primary-action-color: lighten($primary-action-color, 15%);
$dark-primary-action-color: darken($primary-action-color, 15%);
// Secondary Action
$secondary-action-color: #ff852c;
$light-secondary-action-color: lighten($secondary-action-color, 15%);
$dark-secondary-action-color: darken($secondary-action-color, 15%);
// Success colors
$success-color: #037b30;
$light-success-color: lighten($success-color, 15%);
$dark-success-color: darken($success-color, 15%);
// Error colors
$error-color: #c70936;
$light-error-color: lighten($error-color, 15%);
$feedback-error-color: #f8e7eb;
$dark-error-color: darken($error-color, 15%);
// Sale color
$sale-color: $error-color;
// Social colors
$facebook-color: #3a5a93;
$twitter-color: #55aace;
$instagram-color: #405de6;
$pinterest-color: #bd081c;
$youtube-color: #e52d27;
$google-plus-color: #dd4b39;
$yelp-color: #af0606;
// [EEE] Appearance
// ---
$font-color: $neutral-60;
$link-color: $ui-brand-color;
$active-link-color: $dark-accent-color;
$focus-color: $brand-color;
$border-color: $neutral-20;
$border-radius: 4px;
$input-background-color: $neutral-00;
$input-border-color: $border-color;
$focused-input-border-color: $secondary-brand-color;
$disabled-input-color: $neutral-40;
$disabled-input-background-color: $neutral-15;
$disabled-button-background-color: $neutral-15;
$horizontal-input-padding: $unit;
$vertical-input-padding: $unit;
$background-color: $neutral-10;
$overlay-color: rgba($neutral-00, 0.85);
// [FFF] Z-Index
// ---
// Organizes z-index usage by name. Values can be incremented/decremented
// slightly as necessary. eg. $z1-layer + 1;
$z1-depth: 1; // background
$z2-depth: 10; // icon or other ui element
$z3-depth: 100; // modal shade or similar
$z4-depth: 1000; // modal dialog or similar
// [GGG] Shorthands
// ---
$border: 1px solid $border-color;
$light-border: 1px solid $neutral-15;
$input-padding: $vertical-input-padding $horizontal-input-padding;
$box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.3);
$large-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.3);
$inset-box-shadow: inset 0 2px 2px -2px rgba(0, 0, 0, 0.3), inset 0 -2px 2px -2px rgba(0, 0, 0, 0.3);
$input-box-shadow: inset 0 0 5px 0 rgba(0, 0, 0, 0.3);

View File

@@ -0,0 +1,15 @@
// Animations
// ===
//
// Background Shimmer
// ---
@keyframes background-shimmer {
0% {
background-position: 150vw 0;
}
100% {
background-position: -150vw 0;
}
}

View File

@@ -0,0 +1,333 @@
// Forms
// ===
$base__radio-checkmark: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ffffff"><path d="M18.8 6l-9.1 9.2-4.3-4.3L4 12.3 9.7 18 20.2 7.4z"/></svg>';
// General Form Elements
// ---
//
// 1. Address Firefox 4+ setting `line-height` on `input` using `!important` in
// the UA stylesheet.
// 2. Remove padding so people arent caught out if they zero out fieldsets.
// 3. Remove inner padding and border in Firefox 4+.
// 4. Correct color not being inherited. Known issue: affects color of disabled
// elements.
// 5. Correct font properties not being inherited.
// 6. Address margins set differently in Firefox 4+, Safari, and Chrome.
// 7. Set font-size to 16px to avoid zooming in on iOS (https://stackoverflow.com/questions/11064237/prevent-iphone-from-zooming-form)
fieldset {
min-width: 0;
margin: 0;
padding: 0;
border: 0;
}
input {
margin: 0; // 6
color: inherit; // 4
font: inherit; // 5
font-family: $font-family;
font-size: $font-size + 2; // 7
line-height: normal; // 1
&::-moz-focus-inner {
padding: 0; // 3
border: 0; // 3
}
}
textarea {
margin: 0; // 6
color: inherit; // 4
font: inherit; // 5
}
label,
textarea {
font-family: $font-family;
font-size: $font-size;
}
label {
display: inline-block;
margin-bottom: $unit / 2;
font-weight: $semi-bold-font-weight;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
&:active {
color: $active-link-color;
}
}
select,
textarea,
[type="text"],
[type="search"],
[type="password"],
[type="tel"],
[type="url"],
[type="number"],
[type="email"] {
width: 100%;
min-height: $tap-size;
padding: $input-padding;
border: $border;
border-radius: 0;
background-color: $input-background-color;
line-height: $line-height;
-webkit-appearance: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
&::-webkit-input-placeholder {
color: $neutral-50;
}
&:active,
&:focus {
border-color: $focus-color;
box-shadow: $input-box-shadow;
}
}
legend {
padding: 0; // 2
}
// Search input
// ---
//
// These properties must be set with a slightly higher specificity for search
// inputs because Normalize's defaults are a bit too specific
//
// 1. Address `appearance` set to `searchfield` in Safari and Chrome.
// 2. Remove inner padding and search cancel button in Safari and Chrome on OS X.
// Safari (but not Chrome) clips the cancel button when the search input has
// padding (and `textfield` appearance).
input[type="search"] {
box-sizing: border-box;
-webkit-appearance: none; // 1
&::-webkit-search-cancel-button,
&::-webkit-search-decoration {
-webkit-appearance: none; // 2
}
}
// Select
// ---
//
// 1. Restore browser default styling. If youre taking full control of select
// styling, remove both these lines.
// 2. Simulate the position of the down-arrow as if it were a Icon component in
// a button.
// 3. Address inconsistent `text-transform` inheritance for `button` and `select`.
// All other form control elements do not inherit `text-transform` values.
// Correct `button` style inheritance in Firefox and Opera. Correct `select`
// style inheritance in Firefox.
// 4. Correct color not being inherited. Known issue: affects color of disabled
// elements.
// 5. Set font-size to 16px to avoid zooming in on iOS (https://stackoverflow.com/questions/11064237/prevent-iphone-from-zooming-form)
// 6. Address margins set differently in Firefox 4+, Safari, and Chrome.
select {
height: $tap-size; // 1
margin: 0; // 6
border-radius: 0;
color: $brand-color;
font-family: $font-family;
font-size: $font-size + 2; // 5
text-transform: none; // 3
&,
&[disabled] {
background-repeat: no-repeat;
background-position: calc(100% - 14px) center; // 2
background-size: 12px 6px;
}
}
optgroup {
margin: 0; // 6
color: inherit; // 4
font: inherit; // 5
}
// Checkbox and Radios
// ---
[type="checkbox"],
[type="radio"] {
position: relative;
display: inline-block;
width: $unit*3;
height: $unit*3;
margin-right: $unit;
border: $border;
background: $neutral-00;
vertical-align: middle;
-webkit-appearance: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
&:active {
background: $neutral-30;
}
&:checked {
border: 0;
background: $brand-color;
&::after {
content: '';
position: absolute;
display: block;
}
}
&:disabled {
border: 0;
background: rgba($neutral-20, 0.5);
}
}
[type="radio"] {
border-radius: 50%;
&:after {
top: $unit;
right: $unit;
bottom: $unit;
left: $unit;
border-radius: 50%;
background: $neutral-00;
}
}
[type="checkbox"] {
&:checked {
&:after {
content: '';
top: 0;
display: block;
width: $unit*3;
height: $unit*3;
background: url($base__radio-checkmark);
color: $neutral-00;
line-height: 0;
pointer-events: none;
}
}
}
// Buttons
// ---
//
// 1. Address margins set differently in Firefox 4+, Safari, and Chrome.
// 2. Correct color not being inherited. Known issue: affects color of disabled
// elements.
// 3. Correct font properties not being inherited.
// 4. Address inconsistent `text-transform` inheritance for `button` and `select`.
// All other form control elements do not inherit `text-transform` values.
// Correct `button` style inheritance in Firefox and Opera. Correct `select`
// style inheritance in Firefox.
// 5. Remove inner padding and border in Firefox 4+.
// 6. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
// and `video` controls.
// 7. Correct inability to style clickable `input` types in iOS.
button,
[type="submit"] {
display: block;
margin: 0; // 1
padding: 0;
border: 0;
background: $neutral-15;
color: inherit; // 2
font: inherit; // 3
line-height: $line-height;
text-transform: none; // 4
-webkit-appearance: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
&::-moz-focus-inner {
padding: 0; // 5
border: 0; // 5
}
&:active {
background: $neutral-30;
}
}
html input[type="button"],
// 6
input[type="reset"] {
-webkit-appearance: button; // 7
}
// Disabled
// ---
//
// 1. web-kit default disabled style
// 2. Disabled style for button, checkbox, radio, input and select
// 3. Checkbox and Radio style
[disabled] {
opacity: 1;
background: $disabled-input-background-color;
color: $disabled-input-color;
-webkit-text-fill-color: $disabled-input-color; // 1
// 2
&:active,
&:checked {
border-color: $disabled-input-color;
background: $disabled-input-background-color;
&::after {
color: $disabled-input-color; // 3
}
}
&[type="radio"]:after {
background-color: $disabled-input-color;
}
}

View File

@@ -0,0 +1,128 @@
// General
// ===
// Document
// ---
//
// 1. Applying styles to *::before or *::after is a performance issue on some
// legacy Android devices (4.1.x). As such, these are disabled by default.
// 2. Prevent iOS text size adjust after orientation change, without disabling
// user zoom.
// 3. Remove default margin in all browsers.
// *::before, // 1
// *::after, // 1
* {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
html {
color: $font-color;
font-family: $font-family;
font-size: $font-size;
line-height: $line-height;
-ms-text-size-adjust: 100%; // 2
-webkit-text-size-adjust: 100%; // 2
}
body {
margin: 0; // 3
}
// Grouping content
// ---
//
// 1. Address margin not present in Safari.
// 2. Contain overflow in all browsers.
// 3. Address odd `em`-unit font size rendering in all browsers.The duplication
// of `monospace` is intentional
// ([Source](http://en.wikipedia.org/wiki/User:Davidgothberg/Test59)).
figure {
margin: 1em 40px; // 1
}
pre {
overflow: auto; // 2
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace; // 3
font-size: 1em; // 3
}
// New HTML5 elements
// ---
// Correct `block` display not defined for `main` in mobile Safari 6 and
// Android 4.3.
//
// Correct `block` display not defined for `menu`.
main,
menu {
display: block;
}
// Normalize vertical alignment of `progress` in Chrome and Firefox.
audio,
canvas,
progress,
video {
vertical-align: baseline;
}
// Prevent modern browsers from displaying `audio` without controls.
// Remove excess height in iOS 5 devices.
audio:not([controls]) {
display: none;
height: 0;
}
// Hide the `template` element in mobile Safari.
template {
display: none;
}
// Prevent `sub` and `sup` affecting `line-height` in all browsers.
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
// Hidden
// ---
//
// Hide visually and from screen readers. `u-visually-hidden` class is preferred
// to ensure that it's working in all conditions.
[hidden] {
display: none;
}

View File

@@ -0,0 +1,40 @@
// Lists
// ===
// Ordered and Unordered Lists
// ---
//
// We default to unstyled lists because they seem to be a more common usecase.
// Use the extensions to re-add the defaults back in.
//
// It is our recommendation that instead of styling the ul and ol directly that
// you create a list component that can be added to lists when needed.
ul,
ol {
margin: 0;
padding: 0;
list-style-type: none;
}
// Definition Lists
// ---
dl {
margin-bottom: $unit;
line-height: $line-height;
}
dt {
margin-top: $unit;
font-weight: $semi-bold-font-weight;
}
dd {
margin: 0;
}

View File

@@ -0,0 +1,81 @@
// Mixins
// ===
//
// Background Shimmer
// ---
@mixin background-shimmer() {
overflow: hidden;
background: $neutral-10;
background-image: linear-gradient(to right,
$neutral-10 0%, scale-color($neutral-15, $lightness: -5%) 50%, $neutral-10 100%);
background-repeat: no-repeat;
background-size: 100vw 100vh;
animation: 1.5s linear infinite background-shimmer;
}
// Visually Hidden
// ---
@mixin visually-hidden() {
position: absolute;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
width: 1px;
height: 1px;
padding: 0;
border: 0;
}
// Wrap At Root
// ---
//
// Wraps the nested blocks in the `$selector` of your choice, and at the root
// level. Specificity of the selector can be increased by increasing the
// `$degree` to a higher number than the default `1`.
// Examples:
// ---
//
// Default:
//
// @include wrap-at-root("#app") {
// .u-border-red { border: 1px solid red; }
// }
//
// Output: #app .u-border-red { border: 1px solid red; }
//
//
// Custom:
//
// @include wrap-at-root("#app", 3) {
// .u-border-red { border: 1px solid red; }
// }
//
// Output: #app#app#app .u-border-red { border: 1px solid red; }
// Parameters
// ---
//
// @param $selector [String]: ID selector.
// @param $degree [Number]: Effectively the number of id-level selectors you
// need to override.
@mixin wrap-at-root($selector, $degree: 1) {
$selector-chain: '';
// Build an id selector by chaining the same id onto itself once more than
// the specified degree. So if degree: 3, we get #id#id#id.
@for $i from 1 through $degree {
$selector-chain: $selector-chain + $selector;
}
@at-root #{$selector-chain} {
@content;
}
}

View File

@@ -0,0 +1,26 @@
// Tables
// ===
table {
border-spacing: 0;
border-collapse: collapse;
width: 100%;
margin: $unit 0;
}
th {
padding: $unit 0;
font-weight: $semi-bold-font-weight;
text-align: left;
}
td {
padding: $unit 0;
}
tr,
td,
th {
vertical-align: middle;
}

View File

@@ -0,0 +1,112 @@
// Typography
// ===
// Headers
// ---
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
font-family: $header-font-family;
font-weight: $regular-font-weight;
line-height: 1.25;
// Added with webfontloader. See loadFonts() in app/container.js
.wf-active & {
font-family: $loaded-header-font-family;
}
}
h1,
%h1 {
font-weight: $light-font-weight;
font-size: $huge-font-size;
line-height: $huge-line-height;
}
h2,
%h2 {
font-size: $bigger-font-size;
line-height: $bigger-line-height;
}
h3,
%h3,
h4,
%h4 {
font-size: $big-font-size;
line-height: $big-line-height;
}
h5,
%h5 {
font-size: $font-size + 2;
line-height: $line-height;
}
h6,
%h6 {
font-size: $font-size;
line-height: $line-height;
}
// Text Elements
// ---
p {
margin: 0;
}
a {
color: $link-color;
text-decoration: none;
&:active,
&:focus {
color: $active-link-color;
}
}
b,
strong {
font-weight: $semi-bold-font-weight;
}
small {
font-size: 80%;
}
// Miscellaneous Elements
// ---
//
// 1. Address differences between Firefox and other browsers.
hr {
box-sizing: content-box; // 1
height: 0; // 1
margin: ($unit * 2) 0;
border: $border;
border-width: 0 0 1px;
-moz-box-sizing: content-box; // 1
}
img {
max-width: 100%;
margin: 0;
}
blockquote {
margin: ($unit * 2) 0;
padding-left: $unit;
border-left: 2px solid $border-color;
color: lighten($font-color, 15);
}

View File

@@ -0,0 +1,67 @@
// Progressive Web Theme
// ===
//
// Table Of Contents
// ---
//
// [AAA] Progressive Web SDK Base Styles
// [BBB] Progressive Web SDK Custom Styles for Scaffold
// [AAA] Progressive Web SDK Base Styles
// ---
//
// Most of the Progressive Web SDK components have base styles and are often
// required in order for that component to function correctly.
@import 'node_modules/progressive-web-sdk/dist/components/breadcrumbs/base';
@import 'node_modules/progressive-web-sdk/dist/components/button/base';
@import 'node_modules/progressive-web-sdk/dist/components/carousel/base';
@import 'node_modules/progressive-web-sdk/dist/components/field-row/base';
@import 'node_modules/progressive-web-sdk/dist/components/field/base';
@import 'node_modules/progressive-web-sdk/dist/components/divider/base';
@import 'node_modules/progressive-web-sdk/dist/components/header-bar/base';
@import 'node_modules/progressive-web-sdk/dist/components/icon/base';
@import 'node_modules/progressive-web-sdk/dist/components/icon-label/base';
@import 'node_modules/progressive-web-sdk/dist/components/image/base';
@import 'node_modules/progressive-web-sdk/dist/components/list-tile/base';
@import 'node_modules/progressive-web-sdk/dist/components/mega-menu/base';
@import 'node_modules/progressive-web-sdk/dist/components/mega-menu-item/base';
@import 'node_modules/progressive-web-sdk/dist/components/nav/base';
@import 'node_modules/progressive-web-sdk/dist/components/nav-header/base';
@import 'node_modules/progressive-web-sdk/dist/components/nav-item/base';
@import 'node_modules/progressive-web-sdk/dist/components/nav-menu/base';
@import 'node_modules/progressive-web-sdk/dist/components/ratio/base';
@import 'node_modules/progressive-web-sdk/dist/components/sheet/base';
@import 'node_modules/progressive-web-sdk/dist/components/skeleton-block/base';
@import 'node_modules/progressive-web-sdk/dist/components/skeleton-inline/base';
@import 'node_modules/progressive-web-sdk/dist/components/skeleton-text/base';
@import 'node_modules/progressive-web-sdk/dist/components/skip-links/base';
@import 'node_modules/progressive-web-sdk/dist/components/swatch/base';
@import 'node_modules/progressive-web-sdk/dist/components/tile/base';
// [BBB] Progressive Web SDK Custom Styles
// ---
@import 'pw-components/breadcrumbs';
@import 'pw-components/button';
@import 'pw-components/carousel';
@import 'pw-components/field-row';
@import 'pw-components/field';
@import 'pw-components/header-bar';
@import 'pw-components/icon';
@import 'pw-components/icon-label';
@import 'pw-components/image';
@import 'pw-components/link';
@import 'pw-components/list-tile';
@import 'pw-components/mega-menu-item';
@import 'pw-components/nav';
@import 'pw-components/nav-item';
@import 'pw-components/nav-menu';
@import 'pw-components/sheet';
@import 'pw-components/skeleton-block';
@import 'pw-components/skeleton-inline';
@import 'pw-components/skeleton-text';
@import 'pw-components/swatch';
@import 'pw-components/tile';

View File

@@ -0,0 +1,13 @@
// Breadcrumbs Theme
// ===
.pw-breadcumbs__item {
&:not(:last-of-type)::after {
content: '>';
margin: 0 $unit;
color: $brand-color;
}
}

View File

@@ -0,0 +1,115 @@
// Button Theme
// ===
//
// 1. Slightly larger than standard font size, at 18px
.pw-button {
display: inline-table;
padding: 0;
background: none;
font-family: $font-family;
font-size: $font-size + 2; // 1
letter-spacing: 1px;
transition: background 0.5s ease-in;
-webkit-appearance: none;
&:active,
&:focus {
background: rgba(255, 255, 255, 0.1);
}
}
// Inner
// ---
//
// 1. Ensures that the borderless and bordered buttons appear the same size
// 2. Match the width of the parent `pw-button` container
.pw-button__inner {
display: flex;
justify-content: center;
align-items: center;
width: 100%; // 2
min-width: $tap-size;
min-height: $tap-size;
padding: $unit $unit * 2.5;
border-top: 1px solid transparent; // 1
border-bottom: 1px solid transparent; // 1
&.pw--no-min-width {
min-width: initial;
}
&.pw--no-min-height {
min-height: initial;
}
}
// Themes
// ---
.pw-button.pw--primary {
background-color: $primary-action-color;
color: #fff;
&:active,
&:focus {
background-color: $dark-primary-action-color;
}
}
.pw-button.pw--secondary {
background-color: $secondary-action-color;
color: #fff;
&:active,
&:focus {
background-color: $dark-secondary-action-color;
}
}
.pw-button.pw--tertiary {
background-color: transparent;
color: $brand-color;
&:active,
&:focus {
border-color: $tertiary-brand-color;
color: $tertiary-brand-color;
}
.pw-button__inner {
border: 1px solid $brand-color;
}
&[disabled] {
background-color: $neutral-15;
color: $neutral-30;
.pw-button__inner {
border-color: transparent;
}
}
}
.pw-button.pw--primary,
.pw-button.pw--secondary {
&[disabled] {
background-color: $neutral-15;
color: $neutral-30;
}
}
.pw-button.pw--icon-only {
line-height: 0;
}

View File

@@ -0,0 +1,20 @@
// Carousel Theme
// ===
//
// 1. Position context for the child `.pw--side-controls .pw-carousel__previous`
// and `.pw--side-controls .pw-carousel__next` elements
.pw-carousel {
position: relative; // 1
}
// Carousel Controls
// ---
//
// 1. Hide the carousel slide numbers from being displayed
.pw-carousel__controls {
padding-top: $unit * 1.5;
padding-bottom: $unit * 1.5;
}

View File

@@ -0,0 +1,14 @@
// Field Row
// ===
.pw-field-row {
margin-bottom: $unit;
> * + * {
margin-left: $unit * 1.5;
}
& + & {
margin-top: 0;
}
}

View File

@@ -0,0 +1,58 @@
// Field Theme
// ---
//
// Inner
// ---
.pw-field__inner {
display: inline-block;
width: 100%;
}
// Label Wrap
// ---
.pw-field__label-wrap {
display: flex;
flex: 1 1 auto;
}
// Label
// ---
//
.pw-field__label {
flex: 1 1 auto;
margin-bottom: $unit;
font-weight: $semi-bold-font-weight;
font-size: $font-size;
line-height: 1em;
}
// Field: Error
// ---
.pw-field__error {
margin-top: $sub-unit;
color: $error-color;
font-size: $small-font-size;
line-height: $small-line-height;
}
// Modifier: Error Field
// ---
.pw-field.pw--error {
.pw-field__label {
color: $error-color;
}
input,
select,
.pw-field__input > * {
border-color: $error-color;
}
}

View File

@@ -0,0 +1,20 @@
// Header Bar Theme
// ===
.pw-header-bar {
min-height: $header-height;
background-color: $ui-brand-color;
color: $neutral-00;
}
// Title
// ---
.pw-header-bar__title {
justify-content: flex-start;
flex: initial;
line-height: 0;
}

View File

@@ -0,0 +1,18 @@
// Icon Label Theme
// ===
.pw-icon-label {
line-height: 0;
}
// Label
// ---
.pw-icon-label__label {
margin-top: $unit/2;
font-size: 11px;
line-height: $unit*1.5;
letter-spacing: 0;
}

View File

@@ -0,0 +1,28 @@
// Icon Theme
// ===
.pw-icon {
width: $unit*2.75; // 22px
height: $unit*2.75;// 22px
padding: 2px;
&.pw--small {
width: $unit*2; // 16px
height: $unit*2; // 16px
}
&.pw--medium {
width: $unit*3.5; // 28px
height: $unit*3.5; // 28px
}
&.pw--large {
width: $unit*4.25; // 34px
height: $unit*4.25; // 34px
}
&.pw--huge {
width: $unit*14; // 112px
height: $unit*14; // 112px
}
}

View File

@@ -0,0 +1,10 @@
// Image Theme
// ===
.pw-image {
display: inline-block;
}
.pw--is-transitioning {
opacity: 0.5;
}

View File

@@ -0,0 +1,6 @@
// Link
// ===
.pw-link.pw--underline {
text-decoration: underline;
}

View File

@@ -0,0 +1,43 @@
// List Tile Theme
// ===
.pw-list-tile {
&.pw--instructional-block {
margin-bottom: $unit * 2;
border: $border;
.pw-list-tile__primary {
background-color: $neutral-00;
}
}
}
// Primary
// ---
//
// 1. Slightly larger than standard font size, at 15px
.pw-list-tile__primary {
font-size: $font-size + 1; // 1
}
// Content
// ---
.pw-list-tile__content {
padding: $unit $unit * 2.5;
}
// Action
// ---
.pw-list-tile__action {
display: flex;
justify-content: center;
align-items: center;
min-width: $tap-size;
min-height: $tap-size;
}
.pw-list-tile__action + .pw-list-tile__content {
padding-left: 0;
}

View File

@@ -0,0 +1,41 @@
// MegaMenuItem Theme
// ===
// MegaMenu root
// ---
//
// .pw-mega-menu-item_ {}
// Content
// ---
.pw-mega-menu-item__content {
&.pw--depth-1 {
color: $neutral-00;
font-weight: $semi-bold-font-weight;
text-align: center;
}
&.pw--depth-1.pw--active {
background: $neutral-00;
color: $secondary-brand-color;
}
&.pw--depth-2 {
font-weight: $semi-bold-font-weight;
}
}
// Children
// ---
.pw-mega-menu-item__children {
&.pw--depth-0 {
background: $brand-color;
}
&.pw--depth-1 {
padding: $unit * 1.5;
}
}

View File

@@ -0,0 +1,87 @@
// NavItem Theme
// ===
//
// Compared to the original Progressive Web SDK's NavItem component, this one
// is customized to include extra icons, etc
//
// 1) Provides the positioning context for (2)
// 2) Is positioned relative to (1)
$nav-item__active-color: #f1f0f7;
.pw-nav-item {
display: block;
height: $unit * 5.5;
border-bottom: $border;
background-color: $neutral-00;
color: $neutral-60;
font-size: 15px;
line-height: 20px;
letter-spacing: 0;
text-align: left;
&:active,
&:focus {
border: 0;
background: none;
}
}
.pw-nav-item.pw--selected {
background-color: $nav-item__active-color;
color: $brand-color;
}
.pw-nav-item--with-before-icon {
padding: 0;
}
.pw-nav-item--with-before-icon.pw--selected {
background-color: $nav-item__active-color;
color: $neutral-60;
}
.pw-nav-item--with-before-icon,
.pw-nav-item--sign-in.pw--selected {
background-color: $neutral-10;
}
.pw-nav-item__inner {
height: 100%;
}
.pw-nav-item__before-icon {
width: $unit * 2;
height: $unit * 2;
}
.pw-nav-item__icon {
position: relative; // 1
width: $unit * 5.5;
height: $unit * 5.5;
}
.pw-nav-item__icon-content {
position: absolute; // 2
top: 50%;
left: 50%;
width: $unit * 2;
height: $unit * 2;
transform: translate(-50%, -50%);
}
.pw-nav-item.pw--with-icon {
.pw-nav-item__inner {
padding: 0;
}
}
.pw-nav-item .pw-list-tile__primary {
color: inherit;
}

View File

@@ -0,0 +1,6 @@
// Nav Menu Theme
// ===
.pw-nav-menu__panel {
overflow-y: auto;
}

View File

@@ -0,0 +1,8 @@
// Nav Theme
// ===
.c-header__nav-modal {
border-top: 1px solid $neutral-20;
border-bottom: 1px solid $neutral-20;
background-color: $neutral-00;
color: $neutral-60;
}

View File

@@ -0,0 +1,57 @@
// Sheet Theme
// ===
// Mask
// ---
.pw-sheet__mask {
background: $neutral-70;
}
// Wrapper
// ---
.pw-sheet__wrapper {
box-shadow: $box-shadow;
}
// Inner
// ---
// 1. requested by designer
// 2. to make modal stay on right of the container
// 3. to cover the available space since it's absolute positioned
.pw-sheet.pw--slide-right,
.pw-sheet.pw--slide-left {
.pw-sheet__inner {
max-width: 340px; // 1
}
}
.pw-sheet.pw--slide-right {
.pw-sheet__inner {
left: initial; // 2
width: 100%; // 3
}
}
// States
// ---
//
// @TODO: Replace pw--no-shadow by adding a similar class (but probably
// pw--has-shrink-to-content instead) so the shadow can be removed with
// built-in functionality.
.pw-sheet.pw--no-shadow {
.pw-sheet__wrapper {
box-shadow: none;
}
.pw--shrink-to-content {
box-shadow: $box-shadow;
}
}

View File

@@ -0,0 +1,10 @@
// Skeleton Block Theme
// ===
.pw-skeleton-block {
@include background-shimmer;
&.short {
margin: 5px 0;
}
}

View File

@@ -0,0 +1,6 @@
// Skeleton Inline Theme
// ===
.pw-skeleton-inline {
@include background-shimmer;
}

View File

@@ -0,0 +1,10 @@
// Skeleton Text Theme
// ===
//
// 1. Temporary fix while waiting for an SDK change. @TODO Remove this once the
// SkeletonText component's base styles this with `inline-block`
.pw-skeleton-text__line {
display: inline-block; // 1
height: 1em;
}

View File

@@ -0,0 +1,81 @@
// Swatch Theme
// ===
// Item
// ---
.pw-swatch__item {
border: $border;
&.pw--selected {
border-width: $sub-unit/2;
border-color: $brand-color;
+ .pw-swatch__error {
display: none;
}
}
}
// Label
// ---
.pw-swatch__label {
display: inline-block;
margin-bottom: 4px;
font-weight: $semi-bold-font-weight;
}
// Button
// ---
.pw-swatch__button {
color: $neutral-50;
text-transform: uppercase;
}
.pw-swatch__button-inner {
padding: 0;
}
// Chip
// ---
//
// 1. This is a diagonal line - pythagoras
.pw-swatch__chip {
&.pw--disabled {
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
display: block;
width: 1px;
height: 65px; // 1
background-color: $neutral-20;
transform: rotate(-45deg);
transform-origin: 0 0;
}
.pw-swatch__chip-inner {
opacity: 0.5;
}
}
}
// Error
// ---
.pw-swatch__error {
color: $error-color;
}

View File

@@ -0,0 +1,5 @@
.pw-tile__details {
width: 80%;
margin: auto;
font-size: $font-size + 3; // 1
}

View File

@@ -0,0 +1,61 @@
// Border
// ===
// Border (Width and Color)
// ---
.u-border {
border: $border;
}
.u-border-0 {
border: 0;
}
.u-border-top {
border-top: $border;
}
.u-border-end {
border-right: $border;
}
.u-border-bottom {
border-bottom: $border;
}
.u-border-start {
border-left: $border;
}
// Light Border (Width and Color)
// ---
.u-border-light {
border: $light-border;
}
.u-border-light-top {
border-top: $light-border;
}
.u-border-light-end {
border-right: $light-border;
}
.u-border-light-bottom {
border-bottom: $light-border;
}
.u-border-light-start {
border-left: $light-border;
}
// Border (Other)
// ---
.u-border-radius {
border-radius: $border-radius;
}

View File

@@ -0,0 +1,18 @@
// Box Shadow
// ===
.u-box-shadow {
box-shadow: $box-shadow;
}
.u-box-shadow-inset {
box-shadow: $inset-box-shadow;
}
.u-box-shadow-lg {
box-shadow: $large-box-shadow;
}
.u-box-shadow-input {
box-shadow: $input-box-shadow;
}

View File

@@ -0,0 +1,177 @@
// Color
// ===
// Neutral Colors
// ---
.u-color-neutral-00 {
color: $neutral-00;
fill: $neutral-00;
}
.u-color-neutral-10 {
color: $neutral-10;
fill: $neutral-10;
}
.u-color-neutral-15 {
color: $neutral-15;
fill: $neutral-15;
}
.u-color-neutral-20 {
color: $neutral-20;
fill: $neutral-20;
}
.u-color-neutral-30 {
color: $neutral-30;
fill: $neutral-30;
}
.u-color-neutral-40 {
color: $neutral-40;
fill: $neutral-40;
}
.u-color-neutral-50 {
color: $neutral-50;
fill: $neutral-50;
}
.u-color-neutral-60 {
color: $neutral-60;
fill: $neutral-60;
}
.u-color-neutral-70 {
color: $neutral-70;
fill: $neutral-70;
}
// Other Colors
// ---
.u-color-brand {
color: $brand-color;
fill: $brand-color;
}
.u-color-accent {
color: $accent-color;
fill: $accent-color;
}
.u-color-primary-action {
color: $primary-action-color;
fill: $primary-action-color;
}
.u-color-secondary-action {
color: $secondary-action-color;
fill: $secondary-action-color;
}
.u-color-success {
color: $success-color;
fill: $success-color;
}
.u-color-error {
color: $error-color;
fill: $error-color;
}
.u-color-sale {
color: $sale-color;
fill: $sale-color;
}
// Background Colors
// ---
.u-bg-color-neutral-00 {
background-color: $neutral-00;
}
.u-bg-color-neutral-10 {
background-color: $neutral-10;
}
.u-bg-color-neutral-15 {
background-color: $neutral-15;
}
.u-bg-color-neutral-20 {
background-color: $neutral-20;
}
.u-bg-color-neutral-30 {
background-color: $neutral-30;
}
.u-bg-color-neutral-40 {
background-color: $neutral-40;
}
.u-bg-color-neutral-50 {
background-color: $neutral-50;
}
.u-bg-color-neutral-60 {
background-color: $neutral-60;
}
.u-bg-color-neutral-70 {
background-color: $neutral-70;
}
// Other Background Colors
// ---
.u-bg-color-brand {
background-color: $brand-color;
}
.u-bg-color-accent {
background-color: $accent-color;
}
.u-bg-color-primary-action {
background-color: $primary-action-color;
}
.u-bg-color-secondary-action {
background-color: $secondary-action-color;
}
.u-bg-color-success {
background-color: $success-color;
}
.u-bg-color-error {
background-color: $error-color;
}
.u-bg-color-sale {
background-color: $sale-color;
}

View File

@@ -0,0 +1,42 @@
// Display
// ===
// Display: Block
// ---
.u-display-block {
display: block;
}
// Display: Inline Block
// ---
.u-display-inline-block {
display: inline-block;
}
// Display: Inline
// ---
.u-display-inline {
display: inline;
}
// Dispaly: Inline Table
// ---
.u-display-inline-table {
display: inline-table;
}
// Display: None
// ---
.u-display-none {
display: none;
}

View File

@@ -0,0 +1,158 @@
// Flexbox
// ===
//
// Flexbox and align a row of items with a lot of control. Provides a
// declarative, robust cross-browser way of using flexbox.
// Flex (Grow)
// ---
//
// Ensures that the flex child will grow to fill the available space.
//
// Note! This utility class should come **BEFORE** the `u-flexbox` class in
// order to ensure that an element with both classes inherits only the
// `display: flex` property.
// 1. Ensure inline elements are treated as block-level.
// 2. Prevent width collapsing in old implementations.
.u-flex {
display: block; // 1
flex: 1 1 auto;
width: 100%; // 2
}
// Flex (Shrink)
// ---
//
// 1. Ensure width collapses in old implementations.
.u-flex-shrink {
flex: initial;
width: auto; // 1
}
// Flex (None)
// ---
//
// Neither grow nor shrink!
.u-flex-none {
flex: 0 0 auto;
}
// Flexbox
// ---
//
// Includes gutters, for grid-like functionality.
//
// Note! This should come **AFTER** the `u-flex` utility class in order to
// ensure an element that has both classes inherits `display: flex`!
// 1. Remove default styles present on common root elements.
// 2. Ensure in iOS 5 and 6 that flex-direction isn't inherited from
// any flexbox parents that has flex-direction set to row-reverse
.u-flexbox {
display: flex;
flex-direction: row; // 2
margin: 0; // 1
padding: 0; // 1
list-style: none; // 1
}
// Directions
// ---
.u-direction-column {
flex-direction: column;
}
.u-direction-column-reverse {
flex-direction: column-reverse;
}
.u-direction-row {
flex-direction: row;
}
.u-direction-row-reverse {
flex-direction: row-reverse;
}
// Align Items
// ---
.u-align-top {
align-items: flex-start;
}
.u-align-center {
align-items: center;
}
.u-align-bottom {
align-items: flex-end;
}
// Justify Content
// ---
.u-justify-start {
justify-content: flex-start;
}
.u-justify-end {
justify-content: flex-end;
}
.u-justify-between {
justify-content: space-between;
}
.u-justify-center {
justify-content: center;
}
.u-justify-around {
justify-content: space-around;
}
// Order
// ---
//
// Re-arrange the display order of up to six items. Add additional modifiers in
// your own stylesheet to re-order more.
.u-order-1 {
order: 1;
}
.u-order-2 {
order: 2;
}
.u-order-3 {
order: 3;
}
.u-order-4 {
order: 4;
}
.u-order-5 {
order: 5;
}
.u-order-6 {
order: 6;
}

View File

@@ -0,0 +1,26 @@
// Heading
// ===
.u-h1 {
@extend %h1;
}
.u-h2 {
@extend %h2;
}
.u-h3 {
@extend %h3;
}
.u-h4 {
@extend %h4;
}
.u-h5 {
@extend %h5;
}
.u-h6 {
@extend %h6;
}

View File

@@ -0,0 +1,97 @@
// Layout utils
// ===
// Floats
// ---
//
// Writing-direction independent floats. For RTL stylesheets, re-define
// these styles with the opposite direction. Templates need not be changed.
.u-float-start {
float: left;
}
.u-float-end {
float: right;
}
// Contain floats
// ---
//
// Contain all floated children and their margins.
//
// 1. Avoid an Opera bug when the contenteditable attribute is included anywhere
// else in the document.
// 2. Contain the the first childs top margin. Ensures rendering is consistent
// with the other common clearfix method, `overflow: hidden`.
.u-clearfix {
&::before,
&::after {
content: ' '; // 1
display: table; // 2
}
&::after {
clear: both;
}
}
// Positioning relative
// ---
//
// Create a new positioning context.
.u-position-relative {
position: relative;
}
// Positioning absolute
// ---
//
// Create a new positioning context.
.u-position-absolute {
position: absolute;
}
// Positioning fixed
// ---
//
// Create a new positioning context.
.u-position-fixed {
position: fixed;
}
// Positioning coordinate
// ---
.u-position-top {
top: 0;
}
.u-position-right {
right: 0;
}
.u-position-bottom {
bottom: 0;
}
.u-position-left {
left: 0;
}
.u-position-full {
top: 0;
right: 0;
bottom: 0;
left: 0;
}

View File

@@ -0,0 +1,159 @@
// Margin
// ===
// Miscellanous
// ---
.u-margin-0 {
margin: 0;
}
.u-margin-center {
margin: 0 auto;
}
.u-margin-all {
margin-top: $unit;
margin-right: $unit;
margin-bottom: $unit;
margin-left: $unit;
}
// Vertical Margins
// ---
//
// Granular control over vertical spacing independent of a component. Includes
// values based on global spacing.
//
// Suffixes:
// 0: none
// sm: small
// md: medium
// lg: large
.u-margin-top-0 {
margin-top: 0;
}
.u-margin-top {
margin-top: $unit;
}
.u-margin-top-sm {
margin-top: ($unit / 2);
}
.u-margin-top-md {
margin-top: $unit * 1.5;
}
.u-margin-top-lg {
margin-top: $unit * 2;
}
.u-margin-bottom-0 {
margin-bottom: 0;
}
.u-margin-bottom {
margin-bottom: $unit;
}
.u-margin-bottom-sm {
margin-bottom: ($unit / 2);
}
.u-margin-bottom-md {
margin-bottom: $unit * 1.5;
}
.u-margin-bottom-lg {
margin-bottom: $unit * 2;
}
// Horizontal Margins
// ---
//
// Granular control over horizontal spacing independent of a component. Includes
// values based on global spacing, and adds values based on relative typographic
// sizes.
//
// `start` and `end` are writing-direction independent forms for `left` and
// `right`. For right-to-left localizations, create an alternate version of this
// stylesheet with the property directions reversed.
//
// Suffixes:
//
// 0: none
// th: thick space (about 1.5× a “normal” word space)
// en: en space (half an em)
// em: em space
// sm: small
// md: medium
// lg: large
.u-margin-start-0 {
margin-left: 0;
}
.u-margin-start {
margin-left: $unit;
}
.u-margin-start-th {
margin-left: 0.333em;
}
.u-margin-start-en {
margin-left: 0.5em;
}
.u-margin-start-em {
margin-left: 1em;
}
.u-margin-start-sm {
margin-left: ($unit / 2);
}
.u-margin-start-md {
margin-left: $unit * 1.5;
}
.u-margin-start-lg {
margin-left: $unit * 2;
}
.u-margin-end-0 {
margin-right: 0;
}
.u-margin-end {
margin-right: $unit;
}
.u-margin-end-th {
margin-right: 0.333em;
}
.u-margin-end-en {
margin-right: 0.5em;
}
.u-margin-end-em {
margin-right: 1em;
}
.u-margin-end-sm {
margin-right: ($unit / 2);
}
.u-margin-end-md {
margin-right: $unit * 1.5;
}
.u-margin-end-lg {
margin-right: $unit * 2;
}

View File

@@ -0,0 +1,164 @@
// Padding
// ===
// Miscellanous
// ---
.u-padding-0 {
padding: 0;
}
.u-padding {
padding: $unit;
}
.u-padding-sm {
padding: ($unit / 2);
}
.u-padding-md {
padding: $unit * 1.5;
}
.u-padding-lg {
padding: $unit * 2;
}
// Vertical Padding
// ---
//
// Granular control over vertical spacing independent of a component. Includes
// values based on global spacing.
//
// Suffixes:
// 0: none
// sm: small
// md: medium
// lg: large
.u-padding-top-0 {
padding-top: 0;
}
.u-padding-top {
padding-top: $unit;
}
.u-padding-top-sm {
padding-top: ($unit / 2);
}
.u-padding-top-md {
padding-top: $unit * 1.5;
}
.u-padding-top-lg {
padding-top: $unit * 2;
}
.u-padding-bottom-0 {
padding-bottom: 0;
}
.u-padding-bottom {
padding-bottom: $unit;
}
.u-padding-bottom-sm {
padding-bottom: ($unit / 2);
}
.u-padding-bottom-md {
padding-bottom: $unit * 1.5;
}
.u-padding-bottom-lg {
padding-bottom: $unit * 2;
}
// Horizontal Padding
// ---
//
// Granular control over horizontal spacing independent of a component. Includes
// values based on global spacing, and adds values based on relative typographic
// sizes.
//
// `start` and `end` are writing-direction independent forms for `left` and
// `right`. For right-to-left localizations, create an alternate version of this
// stylesheet with the property directions reversed.
//
// Suffixes:
//
// 0: none
// th: thick space (about 1.5× a “normal” word space)
// en: en space (half an em)
// em: em space
// sm: small
// md: medium
// lg: large
.u-padding-start-0 {
padding-left: 0;
}
.u-padding-start {
padding-left: $unit;
}
.u-padding-start-th {
padding-left: 0.333em;
}
.u-padding-start-en {
padding-left: 0.5em;
}
.u-padding-start-em {
padding-left: 1em;
}
.u-padding-start-sm {
padding-left: ($unit / 2);
}
.u-padding-start-md {
padding-left: $unit * 1.5;
}
.u-padding-start-lg {
padding-left: $unit * 2;
}
.u-padding-end-0 {
padding-right: 0;
}
.u-padding-end {
padding-right: $unit;
}
.u-padding-end-th {
padding-right: 0.333em;
}
.u-padding-end-en {
padding-right: 0.5em;
}
.u-padding-end-em {
padding-right: 1em;
}
.u-padding-end-sm {
padding-right: ($unit / 2);
}
.u-padding-end-md {
padding-right: $unit * 1.5;
}
.u-padding-end-lg {
padding-right: $unit * 2;
}

View File

@@ -0,0 +1,27 @@
// Text Content
// ===
//
// This is used to apply text-based-content styles to a container. Think of a
// blog post as an example of text content.
.u-text-content {
.u-h1 {
text-transform: uppercase;
}
.u-h2 {
font-weight: $semi-bold-font-weight;
}
.u-h3 {
color: $brand-color;
}
.u-h4 {
text-transform: uppercase;
}
p + p {
margin-top: $unit;
}
}

View File

@@ -0,0 +1,206 @@
// Text utils
// ===
// Font-Family
// ---
.u-text-family {
font-family: $font-family;
}
.u-text-family-header {
font-family: $header-font-family;
// Added with webfontloader. See loadFonts() in app/container.js
.wf-active & {
font-family: $loaded-header-font-family;
}
}
.u-text-family-loaded {
font-family: $loaded-header-font-family;
}
// Weights & Style
// ---
.u-text-weight-thin {
font-weight: $thin-font-weight;
}
.u-text-weight-extra-light {
font-weight: $extra-light-font-weight;
}
.u-text-weight-light {
font-weight: $light-font-weight;
}
.u-text-weight-regular {
font-weight: $regular-font-weight;
}
.u-text-weight-medium {
font-weight: $medium-font-weight;
}
.u-text-weight-semi-bold {
font-weight: $semi-bold-font-weight;
}
.u-text-weight-bold {
font-weight: $bold-font-weight;
}
.u-text-style-italic {
font-style: italic;
}
.u-text-quiet {
color: $neutral-50;
font-size: $small-font-size;
fill: $neutral-50;
}
// Size
// ---
.u-text-size-smaller {
font-size: $smaller-font-size;
}
.u-text-size-small {
font-size: $small-font-size;
}
.u-text-size-base {
font-size: $font-size;
}
.u-text-size-big {
font-size: $big-font-size;
}
.u-text-size-bigger {
font-size: $bigger-font-size;
}
.u-text-size-huge {
font-size: $huge-font-size;
}
// Line Height
// ---
.u-text-height-0 {
line-height: 0;
}
.u-text-height-tiny {
line-height: $tiny-line-height;
}
.u-text-height-smaller {
line-height: $smaller-line-height;
}
.u-text-height-small {
line-height: $small-line-height;
}
.u-text-height-base {
line-height: $line-height;
}
.u-text-height-big {
line-height: $big-line-height;
}
.u-text-height-bigger {
line-height: $bigger-line-height;
}
.u-text-height-huge {
line-height: $huge-line-height;
}
// Letter Spacing
// ---
.u-text-letter-spacing-small {
letter-spacing: 1px;
}
.u-text-letter-spacing-normal {
letter-spacing: normal;
}
// Text Alignment
// ---
.u-text-align-start {
text-align: left;
}
.u-text-align-center {
text-align: center;
}
.u-text-align-end {
text-align: right;
}
.u-text-align-middle {
vertical-align: middle;
}
.u-text-align-baseline {
vertical-align: baseline;
}
// All Caps
// ---
//
// Set text uppercase, letterspaced for legibility.
.u-text-uppercase {
text-transform: uppercase;
}
// Capitalize Text
// ---
//
// Capitalize first letter of string.
.u-text-capitalize {
text-transform: capitalize;
}
// Lowercase Text
// ---
//
// Lowercase all text in string.
.u-text-lowercase {
text-transform: lowercase;
}
// Strikethrough Text
// ---
//
// Strikethrough all text in string.
.u-text-strikethrough {
text-decoration: line-through;
}

View File

@@ -0,0 +1,8 @@
// Visibility Utils
// ===
//
// Remove from flow but leave available to screen readers.
.u-visually-hidden {
@include visually-hidden();
}

View File

@@ -0,0 +1,18 @@
// Z-Index
// ===
.u-z-index-1 {
z-index: $z1-depth;
}
.u-z-index-2 {
z-index: $z2-depth;
}
.u-z-index-3 {
z-index: $z3-depth;
}
.u-z-index-4 {
z-index: $z4-depth;
}

13
src/index.css Normal file
View File

@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

26
src/index.js Normal file
View File

@@ -0,0 +1,26 @@
import React from 'react';
import logo from './logo.svg';
import './index.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;

12
src/main.js Normal file
View File

@@ -0,0 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './index';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

47
src/router.jsx Normal file
View File

@@ -0,0 +1,47 @@
import React from 'react'
import PropTypes from 'prop-types'
import {Provider} from 'react-redux'
import { BrowserRouter, Route } from 'react-router-dom';
import PageLoader from './components/page-loader'
import Loadable from 'react-loadable'
// Containers
import App from './index'
// Use Webpacks' import() with react-loadable to do code-splitting on a
// per-component basis. We recommend doing this for pages in your app.
export const Home = Loadable({
loader: () => import('./pages/home' /* webpackChunkName: "home" */),
loading: PageLoader
})
export const Login = Loadable({
loader: () => import('./pages/cart' /* webpackChunkName: "cart" */),
loading: PageLoader
})
class Router extends React.Component {
render() {
const {store} = this.props
return (
<Provider store={store}>
<BrowserRouter>
<Route path="/" component={App}>
<Route path="home" component={Home} />
<Route path="login" component={Login} />
</Route>
</BrowserRouter>
</Provider>
)
}
}
Router.propTypes = {
store: PropTypes.object
}
export default Router

151
src/scripts/createComponent.sh Executable file
View File

@@ -0,0 +1,151 @@
#!/bin/bash
# function string_replace {
# echo "${1//\*/$2}"
# }
createStatelessComponent() {
COMPONENT_NAME=$1
# SCRIPT_PATH=`pwd`
cd ..
COMPONENT_PATH=`find -type d -name 'components'`
echo "Creating Stateless Component $COMPONENT_NAME"
cd $COMPONENT_PATH
mkdir $COMPONENT_NAME
cd $COMPONENT_NAME
touch test.js
touch _base.scss
touch index.jsx
cat <<-EOF > index.jsx
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
const $COMPONENT_NAME = ({
className,
text
}) => {
const classes = classNames('c-$COMPONENT_NAME', {
// 'c--modifier': bool ? true : false
}, className)
return (
<div className={classes}>
I am an example! {text}
</div>
)
}
$COMPONENT_NAME.propTypes = {
/**
* PropTypes comments are REQUIRED for components to be included
* in the styleguide
*/
text: PropTypes.string.isRequired,
/**
* Adds values to the `class` attribute of the root element
*/
className: PropTypes.string,
}
export default $COMPONENT_NAME
EOF
cat <<-EOF > _base.scss
.c-$COMPONENT_NAME {
// Root Class. Contains all core styles, typically for the component's
// wrapper element.
}
EOF
}
createStateFulComponent() {
COMPONENT_NAME=$1
echo "Creating Stateful Component $COMPONENT_NAME"
cd ..
COMPONENT_PATH=`find -type d -name 'components'`
cd $COMPONENT_PATH
mkdir $COMPONENT_NAME
cd $COMPONENT_NAME
touch test.js
touch _base.scss
touch index.jsx
cat <<-EOF > index.jsx
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
class $COMPONENT_NAME extends React.Component {
render() {
const {
className,
text
} = this.props
const classes = classNames('c-$COMPONENT_NAME', {
// 'c--modifier': bool ? true : false
}, className)
return (
<div className={classes}>
I am an example! {text}
</div>
)
}
}
$COMPONENT_NAME.propTypes = {
/**
* PropTypes comments are REQUIRED for components to be included
* in the styleguide
*/
text: PropTypes.string.isRequired,
/**
* Adds values to the `class` attribute of the root element
*/
className: PropTypes.string,
}
export default $COMPONENT_NAME
EOF
cat <<-EOF > _base.scss
.c-$COMPONENT_NAME {
// Root Class. Contains all core styles, typically for the component's
// wrapper element.
}
EOF
}
NO_ARGS='true'
read -p "Please Enter Component name: " COMPONENT_NAME
while getopts s option
do
NO_ARGS='false'
echo "Generating component now...."
case $option in
s)
createStateFulComponent $COMPONENT_NAME
;;
[?])
echo "Usage: $0 [-s]"
exit 1
;;
esac
done
if [ $NO_ARGS == 'true' ]; then
createStatelessComponent $COMPONENT_NAME
fi

View File

135
src/serviceWorker.js Normal file
View File

@@ -0,0 +1,135 @@
// This optional code is used to register a service worker.
// register() is not called by default.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to
// opt-in, read https://bit.ly/CRA-PWA
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://bit.ly/CRA-PWA'
);
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null && contentType.indexOf('javascript') === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}