mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-25 22:37:18 +10:00
Move documentation to Flex Docs
- customization checklist - styling - icons - translations - tos and privacy policy - static pages
This commit is contained in:
parent
86eb33674d
commit
f36bc32694
7 changed files with 31 additions and 853 deletions
|
|
@ -39,7 +39,6 @@ Docs:
|
|||
- [Introducing Flex](https://www.sharetribe.com/docs/background/introducing-flex/)
|
||||
- [What development skills are needed?](https://www.sharetribe.com/docs/background/development-skills/)
|
||||
- [Getting started with FTW](https://www.sharetribe.com/docs/tutorials/getting-started-with-ftw/)
|
||||
tutorial.
|
||||
|
||||
## Customization guide
|
||||
|
||||
|
|
@ -49,18 +48,27 @@ Docs.
|
|||
|
||||
## How to customize this template
|
||||
|
||||
After going through the customization guide, you probably should start with changing
|
||||
[translations](translations.md), [common styles](styling.md) in marketplace.css, and then create
|
||||
[static pages](static-pages.md) and modify
|
||||
[Terms of Service and Privacy Policy pages](terms-of-service-and-privacy-policy.md).
|
||||
After going through the customization guide, you should probably start with the following guides in
|
||||
Flex Docs:
|
||||
|
||||
Documentation for specific topics can be found in the following files:
|
||||
- [How to set up Mapbox for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-mapbox-for-ftw/)
|
||||
- [How to change FTW UI texts and translations](https://www.sharetribe.com/docs/guides/how-to-change-ftw-ui-texts-and-translations/)
|
||||
- [How to customize FTW styles](https://www.sharetribe.com/docs/guides/how-to-customize-ftw-styles/)
|
||||
- [How to change Terms of Service and Privacy Policy in FTW](https://www.sharetribe.com/docs/guides/how-to-change-tos-and-privacy-policy-in-ftw/)
|
||||
- [How to change FTW icons](https://www.sharetribe.com/docs/guides/how-to-change-ftw-icons/)
|
||||
- [FTW customization checklist](https://www.sharetribe.com/docs/guides/ftw-customization-checklist/)
|
||||
|
||||
See also the following articles:
|
||||
|
||||
- [How to add static pages in FTW](https://www.sharetribe.com/docs/guides/how-to-add-static-pages-in-ftw/)
|
||||
- [How to test FTW](https://www.sharetribe.com/docs/guides/how-to-test-ftw/)
|
||||
- [How to set up Sentry to log errors in FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-sentry-to-log-errors-in-ftw/)
|
||||
- [How to set up Analytics for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-analytics-for-ftw/)
|
||||
- [How to set up Content Security Policy (CSP) for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-csp-for-ftw/)
|
||||
|
||||
Extra documentation for specific topics can be found in the following files:
|
||||
|
||||
- [Folder structure](folder-structure.md)
|
||||
- [Translations](translations.md)
|
||||
- [Styling a marketplace](styling.md)
|
||||
- [Static pages](static-pages.md)
|
||||
- [Terms of Service and Privacy Policy](terms-of-service-and-privacy-policy.md)
|
||||
- [Routing](routing.md)
|
||||
- [Redux and duck files](redux.md)
|
||||
- [Extended data](extended-data.md)
|
||||
|
|
@ -70,19 +78,9 @@ Documentation for specific topics can be found in the following files:
|
|||
- [Extend the listing data model](extend-listing.md)
|
||||
- [Search filters](search-filters.md)
|
||||
- [Continuous Integration (CI)](ci.md)
|
||||
- [Original create-react-app documentation](https://github.com/sharetribe/create-react-app/blob/master/packages/react-scripts/template/README.md)
|
||||
- [Customization checklist](customization-checklist.md)
|
||||
- [Icons](icons.md)
|
||||
- [Improving performance](improving-performance.md)
|
||||
- [Deploying to production](deploying-to-production.md)
|
||||
|
||||
See also the following articles in the [Flex Docs](https://www.sharetribe.com/docs/) website:
|
||||
|
||||
- [How to set up Mapbox for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-mapbox-for-ftw/)
|
||||
- [How to test FTW](https://www.sharetribe.com/docs/guides/how-to-test-ftw/)
|
||||
- [How to set up Sentry to log errors in FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-sentry-to-log-errors-in-ftw/)
|
||||
- [How to set up Analytics for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-analytics-for-ftw/)
|
||||
- [How to set up Content Security Policy (CSP) for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-csp-for-ftw/)
|
||||
- [Original create-react-app documentation](https://github.com/sharetribe/create-react-app/blob/master/packages/react-scripts/template/README.md)
|
||||
|
||||
The application was bootstrapped with a forked version of
|
||||
[create-react-app](https://github.com/facebookincubator/create-react-app). While most of the
|
||||
|
|
|
|||
|
|
@ -1,43 +1,5 @@
|
|||
# Customization checklist
|
||||
|
||||
Some generic things to update and check when starting to customize the template.
|
||||
Documentation moved to the Flex Docs site:
|
||||
|
||||
- [Marketplace colors](styling.md)
|
||||
- [Generate app icons](icons.md)
|
||||
- [Update translations](../src/translations/en.json) or [change the language](translations.md)
|
||||
- [LandingPage](../src/containers/LandingPage/LandingPage.js): update and create branded sections
|
||||
- [Footer](../src/components/Footer/Footer.js)
|
||||
- [AboutPage](../src/containers/AboutPage/AboutPage.js)
|
||||
- [Terms of Service](terms-of-service-and-privacy-policy.md#terms-of-service)
|
||||
- [Privacy Policy](terms-of-service-and-privacy-policy.md#privacy-policy)
|
||||
- [Social media sharing graphics](../src/components/Page/Page.js);
|
||||
- [Logo](../src/components/Logo/Logo.js) Change and check that it works on Topbar, Footer, and
|
||||
CheckoutPage
|
||||
- [Default background image](../src/assets/background-1440.jpg)
|
||||
- [Maps Marker icon](../src/components/Map/images/marker-32x32.png)
|
||||
- [Config: update environment variables](../src/config.js)
|
||||
- [Config: siteTitle](../src/config.js) for page schema (SEO)
|
||||
- [Config: marketplace address](../src/config.js): contact details also improve SEO
|
||||
- [Config: social media pages](../src/config.js)
|
||||
- [Marketplace custom config](../src/marketplace-custom-config.js)
|
||||
- Update [ListingPage](../src/containers/ListingPage/ListingPage.js) to show extended data (aka
|
||||
publicData attribute)
|
||||
- Update [EditListingWizard](../src/components/EditListingWizard/EditListingWizard.js) and panels to
|
||||
add extended data
|
||||
- Update [SearchPage](../src/containers/SearchPage/SearchPage.js) to filter with extended data
|
||||
- Update [routeConfiguration](../src/routeConfiguration.js) if needed
|
||||
- Update [Email templates](../ext/default-mail-templates), all of them: .html, subject.txt, and
|
||||
text.txt
|
||||
- See the [Email template reference](https://www.sharetribe.com/docs/references/email-templates/)
|
||||
in Flex Docs for more information.
|
||||
- Update [config: bookingUnitType](../src/config.js) if needed
|
||||
- If `line-item/units` is used, add quantity handling to
|
||||
[BookingDatesForm](../src/forms/BookingDatesForm/BookingDatesForm.js),
|
||||
[ListingPage](../src/containers/ListingPage/ListingPage.js),
|
||||
[CheckoutPage](../src/containers/CheckoutPage/CheckoutPage.js)
|
||||
|
||||
## What else
|
||||
|
||||
- Do you need more [static pages](static-pages.md)?
|
||||
- Changes to existing pages
|
||||
- Changes to transaction process (API + Web app)
|
||||
https://www.sharetribe.com/docs/guides/ftw-customization-checklist/
|
||||
|
|
|
|||
|
|
@ -1,47 +1,5 @@
|
|||
# Icons
|
||||
|
||||
The default icons are generated with [RealFaviconGenerator](https://realfavicongenerator.net/). You
|
||||
can upload your original icon to the tool, customize the colors and themes, and download a generated
|
||||
set if icons and an HTML snippet to point to those images.
|
||||
Documentation moved to the Flex Docs site:
|
||||
|
||||
1. Open https://realfavicongenerator.net/
|
||||
|
||||
1. Upload your original icon image
|
||||
|
||||
1. Configure platform specific icons
|
||||
|
||||
**Note:** Remember to set the "Theme color" in the Android Chrome section
|
||||
|
||||
1. Configure the paths to use `/static/icons/` as the root path of the icons
|
||||
|
||||
1. Generate the icons
|
||||
|
||||
1. Unzip the favicons.zip archive and replace the default icons and files in
|
||||
[public/static/icons/](../public/static/icons/) with the new icons
|
||||
|
||||
1. Replace the default HTML snippet in [public/index.html](../public/index.html) with the snippet
|
||||
from the generator.
|
||||
|
||||
**Note:** Remove the manifest link from the snippet as we have a default manifest with extra
|
||||
data compared to the generated one. You can edit the default file as you wish.
|
||||
|
||||
**Example HTML snippet:**
|
||||
|
||||
```html
|
||||
<!-- Start Favicons from https://realfavicongenerator.net/ -->
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/icons/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/icons/favicon-16x16.png" />
|
||||
<link rel="mask-icon" href="/static/icons/safari-pinned-tab.svg" color="#c0392b" />
|
||||
<link rel="shortcut icon" href="/static/icons/favicon.ico" />
|
||||
<meta name="msapplication-config" content="/static/icons/browserconfig.xml" />
|
||||
<meta name="theme-color" content="#c0392b" />
|
||||
<!-- End Favicons -->
|
||||
```
|
||||
|
||||
## Map marker icon
|
||||
|
||||
The map marker icon in the listing can be found in
|
||||
[src/components/Map/images/marker-32x32.png](../src/components/Map/images/marker-32x32.png). The
|
||||
dimensions should be 32x32 pixels, so the `favicon-32x32.png` file can be used to replace the map
|
||||
icon.
|
||||
https://www.sharetribe.com/docs/guides/how-to-change-ftw-icons/
|
||||
|
|
|
|||
|
|
@ -1,258 +1,5 @@
|
|||
# Static pages
|
||||
|
||||
If you want to create simple pages that just show static content without need for data fetches, you
|
||||
can create a static page.
|
||||
Documentation moved to the Flex Docs site:
|
||||
|
||||
Steps for creating a static page:
|
||||
|
||||
1. [Create a new folder under `src/containers/`](#1-creating-a-new-folder)
|
||||
2. [Create a new JavaScript file using the same name.](#2-creating-a-javascript-file)
|
||||
3. [Create a new CSS file using the same name.](#3-creating-a-css-file)
|
||||
4. [Write the content to a JavaScript file (i.e. AboutPage.js in our example).](#4-creating-the-component)
|
||||
5. [Write the style rules to CSS file (i.e. AboutPage.css in our example).](#5-adding-some-styles-to-the-css-file)
|
||||
6. [Add the newly created page component to `src/containers/index.js`](#6-adding-the-component-to-the-component-directory)
|
||||
7. [Add the newly created page to `src/routeConfiguration.js`](#7-adding-a-route-to-the-page)
|
||||
|
||||
## 1. Creating a new folder
|
||||
|
||||
Create a new folder under `src/containers/` with the name of your static page. E.g. "about" page
|
||||
should be named as `AboutPage`.
|
||||
|
||||
## 2. Creating a JavaScript file
|
||||
|
||||
Create a new JavaScript file using the folder name. The path should look like
|
||||
`src/containers/AboutPage/AboutPage.js`.
|
||||
|
||||
## 3. Creating a CSS file
|
||||
|
||||
Create a new CSS file using the folder name. The path should look like
|
||||
`src/containers/AboutPage/AboutPage.css`.
|
||||
|
||||
## 4. Creating the component
|
||||
|
||||
Template for a single column static page (AboutPage.js): (We'll go through this line-by-line below.)
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
import { StaticPage, TopbarContainer } from '../../containers';
|
||||
import {
|
||||
LayoutSingleColumn,
|
||||
LayoutWrapperTopbar,
|
||||
LayoutWrapperMain,
|
||||
LayoutWrapperFooter,
|
||||
Footer,
|
||||
NamedLink,
|
||||
ExternalLink,
|
||||
} from '../../components';
|
||||
|
||||
import css from './AboutPage.css';
|
||||
import image from './path/to/image.png';
|
||||
|
||||
const AboutPage = () => {
|
||||
return (
|
||||
<StaticPage
|
||||
className={css.root}
|
||||
title="About"
|
||||
schema={{
|
||||
'@context': 'http://schema.org',
|
||||
'@type': 'AboutPage',
|
||||
description: 'Description of this page',
|
||||
name: 'About page',
|
||||
}}
|
||||
>
|
||||
<LayoutSingleColumn>
|
||||
<LayoutWrapperTopbar>
|
||||
<TopbarContainer />
|
||||
</LayoutWrapperTopbar>
|
||||
<LayoutWrapperMain>
|
||||
<h1>Some content</h1>
|
||||
<img src={image} alt="My first ice cream." />
|
||||
<div>
|
||||
<NamedLink name="LandingPage">Go to home page</NamedLink> or
|
||||
<ExternalLink href="https://google.com">Go to Google</ExternalLink>
|
||||
</div>
|
||||
</LayoutWrapperMain>
|
||||
<LayoutWrapperFooter>
|
||||
<Footer />
|
||||
</LayoutWrapperFooter>
|
||||
</LayoutSingleColumn>
|
||||
</StaticPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutPage;
|
||||
```
|
||||
|
||||
We are using [React](https://reactjs.org/) and [JSX](https://reactjs.org/docs/introducing-jsx.html)
|
||||
to create components and pages. Therefore, we need to import React to our new component which is
|
||||
done in the first line.
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
```
|
||||
|
||||
In the second line we are importing two containers:
|
||||
|
||||
- `StaticPage`: helps in creating static pages
|
||||
- `TopbarContainer`: creates our Topbar component and fetches the data it needs.
|
||||
|
||||
```jsx
|
||||
import { StaticPage, TopbarContainer } from '../../containers';
|
||||
```
|
||||
|
||||
After that we need to import some components:
|
||||
|
||||
- `LayoutSingleColumn` and wrappers that it needs to position content
|
||||
- `Footer` component (to be added inside LayoutWrapperFooter)
|
||||
- `NamedLink` makes it easier to point to different pages inside the application
|
||||
- `ExternalLink` can be used to link outside the application. It creates a normal `<a>`link with
|
||||
extra attributes `target="_blank" rel="noopener noreferrer"` that add some security to these
|
||||
outbound links.
|
||||
|
||||
`LayoutSingleColumn` (and other layouts like LayoutSideNavigation) need to understand what the
|
||||
content is about. Therefore, different parts of the page need to be wrapped with specific
|
||||
components - in this case: `LayoutWrapperTopbar`, `LayoutWrapperMain`, and `LayoutWrapperFooter`.
|
||||
|
||||
```jsx
|
||||
import {
|
||||
LayoutSingleColumn,
|
||||
LayoutWrapperTopbar,
|
||||
LayoutWrapperMain,
|
||||
LayoutWrapperFooter,
|
||||
Footer,
|
||||
NamedLink,
|
||||
ExternalLink,
|
||||
} from '../../components';
|
||||
```
|
||||
|
||||
Then we need to import styles and possible other files from current folder. With CSS we are using
|
||||
[CSS Modules](https://github.com/css-modules/css-modules) to tackle possible classhes of different
|
||||
class names. [Read more.](#5-creating-the-css-file)
|
||||
|
||||
```jsx
|
||||
import css from './AboutPage.css';
|
||||
```
|
||||
|
||||
Then we also import an image which is used later (`<img src={image} alt="My first ice cream." />`).
|
||||
|
||||
```jsx
|
||||
import image from './path/to/image.png';
|
||||
```
|
||||
|
||||
Then after all the imports we are finally getting into phase were we define the component.
|
||||
`const AboutPage = props => { return <div></div>}` defines a component called AboutPage with content
|
||||
defined in return part. This is a
|
||||
[functional component](https://reactjs.org/docs/components-and-props.html).
|
||||
|
||||
In the template above we are using StaticPage component with some attributes:
|
||||
|
||||
```jsx
|
||||
<StaticPage
|
||||
className={css.root}
|
||||
title="About"
|
||||
schema={{
|
||||
"@context": "http://schema.org",
|
||||
"@type": "AboutPage",
|
||||
"description": "Description of this page",
|
||||
"name": "About page",
|
||||
}}
|
||||
>
|
||||
```
|
||||
|
||||
- `className` is JSX name for `class` attribute used in plain HTML.
|
||||
- `title="About"` creates `<title>About</title>` element to `<head>` section of the page. (That
|
||||
title is also used in OpenGraph meta tags). You could also add
|
||||
`description="This is about page description"`
|
||||
- Then we have `schema` tag that defines some data for search engines in JSON-LD format. Check
|
||||
[schema.org](http://schema.org/docs/full.html) for more information.
|
||||
|
||||
Inside `StaticPage` component we define layout (`LayoutSingleColumn`) and add other components
|
||||
inside semantic content wrappers so that the layout is able to understand where to render those
|
||||
blocks.
|
||||
|
||||
```jsx
|
||||
<LayoutSingleColumn>
|
||||
<LayoutWrapperTopbar>
|
||||
<TopbarContainer />
|
||||
</LayoutWrapperTopbar>
|
||||
<LayoutWrapperMain>
|
||||
<h1>Some content</h1>
|
||||
<img src={image} alt="My first ice cream." />
|
||||
<div>
|
||||
<NamedLink name="LandingPage">Go to home page</NamedLink> or
|
||||
<ExternalLink href="https://google.com">Go to Google</ExternalLink>
|
||||
</div>
|
||||
</LayoutWrapperMain>
|
||||
<LayoutWrapperFooter>
|
||||
<Footer />
|
||||
</LayoutWrapperFooter>
|
||||
</LayoutSingleColumn>
|
||||
```
|
||||
|
||||
And as a final step we need to export the component. `export default AboutPage;`. See more from
|
||||
[babeljs.org](https://babeljs.io/learn-es2015/#ecmascript-2015-features-modules)
|
||||
|
||||
## 5. Adding some styles to the CSS file
|
||||
|
||||
Here's an example what your AboutPage.css file could look like:
|
||||
|
||||
```css
|
||||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
padding: 24px;
|
||||
|
||||
/* Use CSS variable imported from marketplace.css */
|
||||
background-color: var(--marketplaceColor);
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Adding the component to the component directory
|
||||
|
||||
New component needs to be added to `src/containers/index.js` file or if it's a presentational
|
||||
component (not page or form) it should be inside components folder and therefore added to
|
||||
`src/components/index.js`
|
||||
|
||||
Inside that index.js you need to add line
|
||||
`export { default as AboutPage } from './AboutPage/AboutPage';`. This helps other parts of the app
|
||||
to import new components easily with `import { AboutPage } from '../../components'`.
|
||||
|
||||
## 7. Adding a route to the page
|
||||
|
||||
As a last step you need to add the newly created static page to the routing. This can be done in
|
||||
`src/routeConfiguration.js`.
|
||||
|
||||
Inside routeConfiguration function you should add a URL path, a page name (it should not conflicting
|
||||
with other pages), and the component itself.
|
||||
|
||||
Add it as first to the list of imported pages in alphabetical order (2nd line):
|
||||
|
||||
```jsx
|
||||
import {
|
||||
AboutPage,
|
||||
AuthenticationPage,
|
||||
CheckoutPage,
|
||||
```
|
||||
|
||||
and after that add the route configuration to your newly created page: (In this example we created
|
||||
about page so '/about' would work well as a path.)
|
||||
|
||||
```javascript
|
||||
{
|
||||
path: '/about',
|
||||
name: 'AboutPage',
|
||||
component: AboutPage,
|
||||
},
|
||||
```
|
||||
|
||||
## Read more
|
||||
|
||||
We are using several libraries in this example. If you want to read more, here's some pointers:
|
||||
|
||||
- [ES2015](https://babeljs.io/learn-es2015/): imports, exports, arrow functions
|
||||
- [React](https://reactjs.org/): for creating components
|
||||
- [JSX](https://reactjs.org/docs/introducing-jsx.html): for getting HTML-like markup syntax for own
|
||||
components
|
||||
- [CSS Modules](https://github.com/css-modules/css-modules)
|
||||
- [React Router](https://reacttraining.com/react-router/web/guides/philosophy): routing inside the
|
||||
application.
|
||||
https://www.sharetribe.com/docs/guides/how-to-add-static-pages-in-ftw/
|
||||
|
|
|
|||
274
docs/styling.md
274
docs/styling.md
|
|
@ -1,275 +1,5 @@
|
|||
# Flex Template for Web: styling
|
||||
|
||||
The goal for creating styling for Flex template app was to keep styling as close as possible to
|
||||
plain CSS while still trying to avoid the mess that comes along with globally defined cascading
|
||||
behavior that CSS is all about.
|
||||
Documentation moved to the Flex Docs site:
|
||||
|
||||
To tackle this goal, we have split the styling into two levels in this template application:
|
||||
|
||||
- [Marketplace level styling](#marketplace-level-styling) through _marketplace.css_ (a kind of
|
||||
global theme)
|
||||
- [Component level styling](#styling-components) using
|
||||
[CSS Modules](https://github.com/css-modules/css-modules)
|
||||
|
||||
## Marketplace level styling
|
||||
|
||||
On top of functionalities provided by Create React App, we have
|
||||
[added a couple of extra libraries](https://www.npmjs.com/package/sharetribe-scripts#differences-to-react-scripts)
|
||||
to help to design consistent UIs faster. CSS Properties and CSS Property Sets are very useful for
|
||||
all kind of style sharing purposes, and we have created marketplace-level styling variables with
|
||||
them.
|
||||
|
||||
The concept behind CSS Properties is quite straightforward - they are variables that can be defined
|
||||
in root-element level and then used inside some CSS rule.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--marketplaceColor: #ffff00;
|
||||
}
|
||||
|
||||
.linkToHomePage {
|
||||
color: var(--marketplaceColor);
|
||||
}
|
||||
```
|
||||
|
||||
(Read more about CSS Properties from [cssnext](http://cssnext.io/))
|
||||
|
||||
We have used this concept to create a marketplace-level "theming" that's defined in three files:
|
||||
_src/marketplace.css_, _src/marketplaceFonts.css_, and _marketplaceIndex.css_.
|
||||
|
||||
### marketplace.css
|
||||
|
||||
This is a good place to start customizing marketplace styles. For example, we define our color
|
||||
scheme here using CSS Property variables:
|
||||
|
||||
```css
|
||||
/* ================ Colors ================ */
|
||||
|
||||
--marketplaceColor: #c0392b;
|
||||
--marketplaceColorLight: #ff4c38;
|
||||
--marketplaceColorDark: #8c291e;
|
||||
|
||||
/* Used with inline CSS SVGs */
|
||||
--marketplaceColorEncoded: %23c0392b;
|
||||
|
||||
--successColor: #2ecc71;
|
||||
--successColorDark: #239954;
|
||||
--failColor: #ff0000;
|
||||
--attentionColor: #ffaa00;
|
||||
|
||||
--matterColorDark: #000000;
|
||||
--matterColor: #4a4a4a;
|
||||
--matterColorAnti: #b2b2b2;
|
||||
--matterColorNegative: #e7e7e7;
|
||||
--matterColorBright: #fcfcfc;
|
||||
--matterColorLight: #ffffff;
|
||||
```
|
||||
|
||||
Changing `--marketplaceColor: #c0392b;` to `--marketplaceColor: tomato;` will change the default
|
||||
marketplace color to tomato color. (It's a certain kind of red color.)
|
||||
|
||||
The `--marketplaceColorEncoded` variable holds the same value as `--marketplaceColor` but with the
|
||||
_#_ URL encoded. This value can be used to maintain a consistent color scheme with inline SVG icons.
|
||||
|
||||
`--successColor` (green) is used in form inputs for showing that the input value is valid.
|
||||
Sometimes, submit buttons (`<PrimaryButton>`) are also using that color to highlight the fact that
|
||||
user has entered valid information to the form at hand.
|
||||
|
||||
Similarly `--failColor` is used to style errors and `--attentionColor` is used to draw user's
|
||||
attention to certain UI components (e.g. required form inputs, or important info in Inbox)
|
||||
|
||||
Our greyscale colors (for borders and background colors) are named with prefix _"matter"_.
|
||||
|
||||
Similar pattern is also used to create more consistent UI components by providing variables for
|
||||
box-shadows, border-radiuses, transitions, and so on. Our current plan is to parameterize styling
|
||||
even more using this concept.
|
||||
|
||||
Breakpoints for media queries are also defined in this file:
|
||||
|
||||
```css
|
||||
/* ================ Custom media queries ================ */
|
||||
|
||||
@custom-media --viewportMedium (min-width: 768px);
|
||||
@custom-media --viewportLarge (min-width: 1024px);
|
||||
@custom-media --viewportXLarge (min-width: 1921px);
|
||||
```
|
||||
|
||||
### marketplaceFonts.css
|
||||
|
||||
Fonts are specified in this files using CSS Property Sets. They provide us a solid way of creating a
|
||||
fixed set of CSS rules for a specific font.
|
||||
|
||||
For example, our default font is defined as:
|
||||
|
||||
```css
|
||||
--fontWeightMedium: 500;
|
||||
|
||||
--marketplaceDefaultFontStyles: {
|
||||
font-family: 'sofiapro', Helvetica, Arial, sans-serif;
|
||||
font-weight: var(--fontWeightMedium);
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
letter-spacing: -0.1px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And created property set can be used as:
|
||||
|
||||
```css
|
||||
p {
|
||||
@apply --marketplaceDefaultFontStyles;
|
||||
}
|
||||
```
|
||||
|
||||
_marketplaceFonts.css_ are included to _marketplace.css_, so you don't need to import this file on
|
||||
new components (importing _marketplace.css_ is enough).
|
||||
|
||||
⚠️ NOTE: template app is following a pattern where the height of an element should be divisible by
|
||||
`6px` on mobile layout and `8px` on bigger layouts. This affects line-heights of font styles too.
|
||||
|
||||
⚠️ NOTE: the `@apply` rule and custom property sets most likely won't get any more support from
|
||||
browser vendors as the spec is yet considered deprecated and alternative solutions are being
|
||||
discussed. However, template app will use these until a good enough alternative is available.
|
||||
|
||||
### marketplaceIndex.css
|
||||
|
||||
This file provides default styles for plain elements like `<body>`, `<a>`, `<p>`, `<input>`, `<h1>`,
|
||||
`<h2>`, and so on.
|
||||
|
||||
## Styling components
|
||||
|
||||
Styling a web UI is traditionally quite a messy business due to the global nature of stylesheets and
|
||||
especially their cascading specificity rule. `.card {/*...*/}` will affect every element on a web
|
||||
page that has a class `card` - even if the different UI context would like to use a different set of
|
||||
rules.
|
||||
|
||||
Our goal has been to create independent components that can be reused in the UI without paying too
|
||||
much attention to the global CSS context. To achieve this, we have used
|
||||
[CSS Modules](https://github.com/css-modules/css-modules), which keeps the syntax close to plain
|
||||
CSS, but it actually creates unique class names to remove the problems caused by the global nature
|
||||
of CSS. In practice, this means that a class with name `card` is actually renamed as
|
||||
`ComponentName__card__3kj4h5`.
|
||||
|
||||
To use styles defined in SectionHero.css, we need to import the .css file into the component:
|
||||
|
||||
```jsx
|
||||
import css from './SectionHero.css';
|
||||
```
|
||||
|
||||
and then select the correct class from imported style object (in this case `heroMainTitle`):
|
||||
|
||||
```jsx
|
||||
<h1 className={css.heroMainTitle}>Book saunas everywhere</h1>
|
||||
```
|
||||
|
||||
### Find the component to change its styles
|
||||
|
||||
Quite often one needs to find a component that is responsible for certain UI partial in order to
|
||||
change the styles. In this case, the easiest way to pinpoint a component is to open the inspector
|
||||
from browser's dev tools. (Right-click on top of the correct element, and select _Inspector_, or
|
||||
something of the sort depending on the browser, from the context menu.)
|
||||
|
||||

|
||||
|
||||
Here we have opened title on LandingPage and the styles for
|
||||
`<h1 class="SectionHero__heroMainTitle__3mVNg"><span>Book saunas everywhere.</span></h1>` are
|
||||
defined in a "class" called `SectionHero__heroMainTitle__3mVNg`. As stated before, the first part of
|
||||
a class name is actually giving us a hint about what component is defining that style - in this
|
||||
case, it's _SectionHero_ and its styles can be found from the file:
|
||||
`src/components/SectionHero/SectionHero.css`.
|
||||
|
||||
There's only two groups of components that break that rule:
|
||||
|
||||
- _src/containers_ (These components are connected to Redux store: Pages and TopbarContainer)
|
||||
- _src/forms_
|
||||
|
||||
### Styling guidelines and good practices
|
||||
|
||||
We have a practice of naming the outermost class of a component as `.root { /* styles */ }`. So, if
|
||||
the component is just rendering single element it only has `.root` class, and if there's more
|
||||
complex inner DOM structure needed, additional classes are named semantically.
|
||||
|
||||
`<SectionHero>` could contain classes named as `.root`, `.heroMainTitle`, `.heroSubtitle`.
|
||||
|
||||
Some guidelines we have tried to follow:
|
||||
|
||||
- **Use semantic class names** (They improve readability and decouples style changes from DOM
|
||||
changes.)
|
||||
- **Use CSS Properties defined in marketplace.css** and create new ones when it makes sense.
|
||||
- **Use classes**, don't style DOM elements directly. (Element styles are global even with CSS
|
||||
Modules.)
|
||||
- **Avoid nesting styles**. (CSS Modules makes specificity rules unnecessary.)
|
||||
- **Group and comment style rules** inside declaration block if that improves readability.
|
||||
- **Parent component is responsible for allocating space** for a child component (i.e. dimensions
|
||||
and margins).
|
||||
- **Define `@apply` rules early enough** inside declaration block (since rules inside those property
|
||||
sets might overwrite rules written above the line where the set is applied).
|
||||
- **Align text and components** to horizontal baselines. I.e. they should be a multiple of `6px` on
|
||||
mobile layout and `8px` on bigger screens.
|
||||
- **Component height should follow baselines too**. I.e. they should be a multiple of `6px` on
|
||||
mobile layout and `8px` on bigger screens. _(Unfortunately, we haven't been strict with this
|
||||
one.)_
|
||||
|
||||
### Styling responsibility: parent component and its children
|
||||
|
||||
One important aspect of a component-based UI is the fact that a component is usually only
|
||||
responsible for what happens inside its outermost element boundary. In parent-child context this
|
||||
means that the parent component is responsible for its own layout and therefore it usually needs to
|
||||
be able to give some dimensions to its child components (and naturally margins between them).
|
||||
|
||||
This creates a need for the parent to have means to pass `className` to its child as props. One
|
||||
example could be a component that shows a circle component inside itself and makes it 50px wide.
|
||||
|
||||
Style definitions of the (`<Circle />`) child component:
|
||||
|
||||
```css
|
||||
.root {
|
||||
background-color: tomato;
|
||||
border-radius: 50%;
|
||||
}
|
||||
```
|
||||
|
||||
Parent component renders
|
||||
(`<div className={css.root}><Circle className={css.circleDimensions} /></div>`):
|
||||
|
||||
```css
|
||||
.root {
|
||||
min-width: 60px;
|
||||
min-height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.circleDimensions {
|
||||
flex-grow: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: 5px;
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes the child component needs to be styled even further than just allocating space to it. If
|
||||
the parent component wants to change the theme of child component there are generally two concepts
|
||||
available:
|
||||
|
||||
- Create themed components (e.g. `<PrimaryButton>`, `<SecondaryButton>`, `<InlineButton>`)
|
||||
- Pass in a `class` property that is able to overwrite original styling rules.
|
||||
|
||||
For the latter option, we have created a prop type concept called `rootClassName`. If you pass
|
||||
`rootClassName` through props to a component, it will use that instead of component's own style
|
||||
rules defined in `.root`. This ensures that the order of style declarations inside final CSS bundle
|
||||
doesn't affect the final styles. (CSS bundle is generated in an import order, therefore we want to
|
||||
avoid situations where `<Component className="classA classB"/>` could end up overwriting each others
|
||||
depending on the order they are imported.)
|
||||
|
||||
In some complex cases, we have also created props for overwriting some inner classes of child
|
||||
components. In these cases, child component is also replacing its own styling class with the class
|
||||
passed-in through props. For example, `<LocationAutocompleteInput>` can take a prop called
|
||||
`iconClassName`, which (if given) replaces `.icon` class defined inside
|
||||
`LocationAutocompleteInput.css`.
|
||||
https://www.sharetribe.com/docs/guides/how-to-customize-ftw-styles/
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
# Terms of Service and Privacy Policy
|
||||
|
||||
The Terms of Service and Privacy Policy of a marketplace are static components that can be edited to
|
||||
suit the marketplace.
|
||||
Documentation moved to the Flex Docs site:
|
||||
|
||||
## Terms of Service
|
||||
|
||||
Edit
|
||||
[src/components/TermsOfService/TermsOfService.js](../src/components/TermsOfService/TermsOfService.js)
|
||||
file to customize the default dummy content.
|
||||
|
||||
## Privacy Policy
|
||||
|
||||
Edit
|
||||
[src/components/PrivacyPolicy/PrivacyPolicy.js](../src/components/PrivacyPolicy/PrivacyPolicy.js)
|
||||
file to customize the default dummy content.
|
||||
https://www.sharetribe.com/docs/guides/how-to-change-tos-and-privacy-policy-in-ftw/
|
||||
|
|
|
|||
|
|
@ -1,211 +1,5 @@
|
|||
# Translations
|
||||
|
||||
The Flex Template for Web supports having a single language for the UI. Supported languages are
|
||||
English, French and Spanish, English being used by default. For information about changing the
|
||||
language, see [here](#changing-the-language).
|
||||
Documentation moved to the Flex Docs site:
|
||||
|
||||
We are using the [React Intl](https://github.com/yahoo/react-intl) library to translate UI texts and
|
||||
to format dates, numbers, and money values.
|
||||
|
||||
## The translation file
|
||||
|
||||
All the text translations can be found in the
|
||||
[src/translations/en.json](../src/translations/en.json) file. The translation data is formatted as
|
||||
one JSON object with all the translations as properties.
|
||||
|
||||
The key - value syntax is as follows:
|
||||
|
||||
```
|
||||
"<component name>.<translation key>": "<translation>"
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
"ManageListingCard.viewListing": "View listing"
|
||||
```
|
||||
|
||||
The keys are namespaced to the corresponding component. This is aligned with the component driven
|
||||
paradigm that the application follows. It might introduce duplication with same translation texts
|
||||
occurring multiple times in the translation file but it also emphasizes how all the components are
|
||||
independent, how a component can be used anywhere and how modifications to a single component do not
|
||||
affect other components.
|
||||
|
||||
## Using the translations
|
||||
|
||||
React Intl provides multiple ways to access the translation data but the most commonly used are the
|
||||
`formatMessage` function and the `FormattedMessage` tag provided by React Intl.
|
||||
|
||||
To use the `formatMessage` function, component needs to be wrapped with the `injectIntl` function
|
||||
which provides a render prop called `intl`. `intl` then provides all the React Intl translation
|
||||
functions, like `formatMessage`:
|
||||
|
||||
```js
|
||||
import { intlShape, injectIntl } from 'react-intl';
|
||||
|
||||
const SomeComponent = props => {
|
||||
const { intl } = props;
|
||||
|
||||
const translation = intl.formatMessage({ id: 'SomeComponent.someKey' });
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
SomeComponent.propTypes = {
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(SomeComponent);
|
||||
```
|
||||
|
||||
As for the `FormattedMessage` it just needs to be imported from `react-intl` and it takes the id
|
||||
prop:
|
||||
|
||||
```
|
||||
<FormattedMessage id="SomeCompoennt.someKey" />
|
||||
```
|
||||
|
||||
Other functions and componets can be explored in the
|
||||
[React Intl documentation](https://github.com/yahoo/react-intl/wiki).
|
||||
|
||||
## Formatting
|
||||
|
||||
React Intl uses the [FormatJS](https://formatjs.io/) formatters for shaping the translation texts
|
||||
based on given arguments. Here are a few examples on how to use FormatJS.
|
||||
|
||||
### Arguments
|
||||
|
||||
Pass a named argument to the format function/component. For the following translation:
|
||||
|
||||
```js
|
||||
"EnquiryForm.messageLabel": "Message to {authorDisplayName}",
|
||||
```
|
||||
|
||||
Pass the author data in the `FormattedMessage` component:
|
||||
|
||||
```js
|
||||
<FormattedMessage id="EnquiryForm.messageLabel" values={{ authorDisplayName: 'Jane D' }} />
|
||||
```
|
||||
|
||||
Or the the `formatMessage` function:
|
||||
|
||||
```js
|
||||
intl.formatMessage({ id: 'EnquiryForm.messageLabel' }, { authorDisplayName: 'Jane D' });
|
||||
```
|
||||
|
||||
### Pluralization
|
||||
|
||||
With pluralization a translation can be formatted to adapt to a number argument.
|
||||
|
||||
```js
|
||||
"ManageListingsPage.youHaveListings": "You have {count} {count, plural, one {listing} other {listings}}",
|
||||
```
|
||||
|
||||
This translation takes the `count` argument and uses the `plural`, `one` and `other` keywords to
|
||||
format the last word of the translation to be _listing_ or _listings_ based on the `count`. The
|
||||
pluralized translation can be used with the `FormattedMessage` component:
|
||||
|
||||
```js
|
||||
<FormattedMessage id="ManageListingsPage.youHaveListings" values={{ count: 3 }} />
|
||||
```
|
||||
|
||||
Or with the `formatMessage` function:
|
||||
|
||||
```js
|
||||
intl.formatMessage({ id: 'ManageListingsPage.youHaveListings' }, { count: 1 });
|
||||
```
|
||||
|
||||
More formatting examples can be found from the
|
||||
[FormatJS message syntax documentation](https://formatjs.io/guides/message-syntax/).
|
||||
|
||||
## Texts outside the translation file
|
||||
|
||||
A few components in the template app contain texts that are not included in the `en.json` file,
|
||||
namely `AboutPage`, `PrivacyPolicy`, and `TermsOfService`. The reason behind this is that these
|
||||
components only contain static content that is laid out in more of a document format so the
|
||||
translations for these texts can easily be changed and maintained in the component files themselves.
|
||||
|
||||
More information about adding static content to the application can be found from
|
||||
[the static pages documentation](./static-pages.md).
|
||||
|
||||
## Changing the language
|
||||
|
||||
If you want the template to use a language that is not supported by default a new translation file
|
||||
needs to be added and the messages in it need to be translated:
|
||||
|
||||
### Creating a new translation file
|
||||
|
||||
1. Copy the default [src/translations/en.json](../src/translations/en.json) English translations
|
||||
file into some other file, for example `it.json` for Italian.
|
||||
|
||||
2. Change the messages in the new translations file to the desired language.
|
||||
|
||||
> Note: we already have a few other language files available in
|
||||
> [translations directory](../src/translations/) for you to start customizing translations.
|
||||
|
||||
### Changing the translations used in FTW
|
||||
|
||||
Once you have the translations file in place:
|
||||
|
||||
1. In [src/config.js](../src/config.js), change the `locale` variable value to match the new locale
|
||||
(the name of the new translations file, without the extension), for example:
|
||||
|
||||
```js
|
||||
const locale = 'it';
|
||||
```
|
||||
|
||||
2. In [src/app.js](../src/app.js), change the React Intl import to point to the correct `react-intl`
|
||||
locale, for example:
|
||||
|
||||
```js
|
||||
import localeData from 'react-intl/locale-data/it';
|
||||
```
|
||||
|
||||
3. If you are using a non-english locale with moment library, you should also import time specific
|
||||
formatting rules for that locale:
|
||||
|
||||
```js
|
||||
import 'moment/locale/it';
|
||||
```
|
||||
|
||||
4. Point `messagesInLocale` to correct .json file, for example:
|
||||
|
||||
```js
|
||||
import messagesInLocale from './translations/it.json';
|
||||
```
|
||||
|
||||
### Changing the translation used in tests
|
||||
|
||||
Also, in case you will translate the application and develop it forward it is wise to change the
|
||||
translations file that the tests use. Normally tests are language agnostic as they use translation
|
||||
keys as values. However, when adding new translations you can end up with missing translation keys
|
||||
in tests. To change the translation file used in tests change the `messages` variable in
|
||||
[src/util/test-helpers.js](../src/util/test-helpers.js) to match your language in use, for example:
|
||||
|
||||
```js
|
||||
import messages from '../translations/it.json';
|
||||
```
|
||||
|
||||
## Managing translations
|
||||
|
||||
In case you have added a new language translation file and are pulling translation updates to
|
||||
`en.json` from the upstream repo there is a command line tool to help keeping the translation files
|
||||
in sync. Running the following command in the project root
|
||||
|
||||
```
|
||||
yarn run translate
|
||||
```
|
||||
|
||||
will start a command line application:
|
||||
|
||||

|
||||
|
||||
The command line application can be used to match a translation file against the English
|
||||
translations. If your new translations file follows the `<LANG CODE>.json` naming, the CLI will pick
|
||||
it up automatically. In order to improve readability, you can add the language name to the
|
||||
`TARGET_LANG_NAMES` map in `scripts/translations.js` if it is not yet in there and the CLI will use
|
||||
the correct name for your language instead of the language code when prompting about translations.
|
||||
|
||||
In case you wish to use something else than English as the source language, modify the `SOURCE_LANG`
|
||||
object in `scripts/translations.js` to match your needs.
|
||||
https://www.sharetribe.com/docs/guides/how-to-change-ftw-ui-texts-and-translations/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue