Move documentation to Flex Docs

- customization checklist
- styling
- icons
- translations
- tos and privacy policy
- static pages
This commit is contained in:
Kimmo Puputti 2019-01-28 16:45:52 +02:00
parent 86eb33674d
commit f36bc32694
7 changed files with 31 additions and 853 deletions

View file

@ -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

View file

@ -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/

View file

@ -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/

View file

@ -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/

View file

@ -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.)
![Mobile LandingPage hero title](./assets/styling/styling-find-component.png)
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/

View file

@ -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/

View file

@ -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:
![Translations CLI](./assets/translations/translations_cli.gif)
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/