... | ... | @@ -2,6 +2,8 @@ |
|
|
* [Client components](#client-components)
|
|
|
* [Creating components](#creating-components)
|
|
|
* [Using Components](#using-components)
|
|
|
* [Components Library](Components:-Components-Library)
|
|
|
* [Pubsweet UI and UI Toolkit](Components:-Pubsweet-UI-and-UI-Toolkit)
|
|
|
|
|
|
A PubSweet component is a JavaScript module that can extend or change the functionality of a PubSweet application. Developers and designers can use any combination of components they can imagine to build the publishing platform they need.
|
|
|
|
... | ... | @@ -9,9 +11,11 @@ PubSweet components are broadly divided into two categories: server components a |
|
|
|
|
|
PubSweet components export certain keys from their main file. This export makes them loadable by PubSweet applications and tooling.
|
|
|
|
|
|
All changes to components are documented using [Conventional Commits](h ttps://conventionalcommits.org/). A good example of how this might look like in practice is our [commit log](https://gitlab.coko.foundation/pubsweet/pubsweet/commits/master). All contributions to our libraries are required to follow this particular commit structure.
|
|
|
|
|
|
# Server components
|
|
|
A server component can export the following keys:
|
|
|
* `server`: This key allows Express.js routes and/or middleware to extend the server. The value for this key is a function that returns another function that accepts an Express.js app as its first argument. This function can do whatever it wants with the app (eg. add new routes, apply middleware functions). Take a look at the [password reset component(https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/components/PasswordReset-server) for a starting point.
|
|
|
* `server`: This key allows Express.js routes and/or middleware to extend the server. The value for this key is a function that returns another function that accepts an Express.js app as its first argument. This function can do whatever it wants with the app (eg. add new routes, apply middleware functions). Take a look at the [password reset component](https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/components/PasswordReset-server) for a starting point.
|
|
|
* `typeDefs`: GraphQL type definitions
|
|
|
* `resolvers`: GraphQL resolvers
|
|
|
## Example
|
... | ... | @@ -43,21 +47,6 @@ The [login component](https://gitlab.coko.foundation/pubsweet/pubsweet/tree/mast |
|
|
|
|
|
You can install the login component and instantly have login functionality in your app. You can also pick and choose which parts of the component you use.
|
|
|
|
|
|
# Components Library
|
|
|
As mentioned already, PubSweet components follow the naming convention of starting with `pubsweet‐component‐` or `@pubsweet/component‐` to make them easily discoverable on the npm registry. However, this is not a requirement. In fact, components don't have to be published at all—they can live in a directory or a git repository.
|
|
|
|
|
|
A number of PubSweet components are already available for developers. Some of them exist in the [PubSweet repository](https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/components) and are ready to use.
|
|
|
|
|
|
# PubSweet UI
|
|
|
Most of the components in the Components Library use a number of small- er, highly reusable components. From small components like input fields and buttons to a configurable form, there are a lot of small components that can be useful to any number of larger components.
|
|
|
|
|
|
[PubSweet UI](https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/ui) (@pubsweet/ui) is an important PubSweet package intended to house these small components. It makes an ever-expanding list of these components available for developers, and plays a central role in the development of a front-end component. UI elements are categorized based on a loose adherence to the principles of atomic design (http://bradfrost.com/blog/post/atomic-web-design/).
|
|
|
|
|
|
PubSweet also provides a [complementary library](https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/ui-toolkit), `@pubsweet/ui‐toolkit` that provides some helper functions, as well as bits of reusable CSS (eg. rotation keyframes, animations, fade-ins, etc.).
|
|
|
|
|
|
## Conventional Commits
|
|
|
All changes to components are documented using [Conventional Commits](h ttps://conventionalcommits.org/). A good example of how this might look like in practice is our [commit log](https://gitlab.coko.foundation/pubsweet/pubsweet/commits/master). All contributions to these libraries are required to follow this particular commit structure.
|
|
|
|
|
|
# Creating components
|
|
|
The component library is a resource that makes PubSweet better for everyone. The more components in the library, and the more people helping maintain them, the better the PubSweet ecosystem becomes for all of us.
|
|
|
|
... | ... | @@ -82,7 +71,7 @@ Things to keep in mind when creating a new component: |
|
|
* Start with reusability in mind;
|
|
|
* Follow the principles of DRY ("[Don't repeat yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)"), KISS, YAGNI;
|
|
|
* Use variables, theme variables for styling, React props, etc., instead of hardcoded values;
|
|
|
* Follow [Conventional Commits](https://www.conventionalcommits.o rg/en/v1.0.0-beta.2/) or keep a healthy changelog;
|
|
|
* Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.2/) or keep a healthy changelog;
|
|
|
* Write documentation;
|
|
|
* Write tests.
|
|
|
|
... | ... | @@ -108,10 +97,17 @@ Let’s take the example of a series of radio buttons. In a group of two ("yes" |
|
|
### Theming-ready components
|
|
|
As PubSweet provides a set of tools to easily change the look and feel of any UI element, your atom or molecule should be developed using the set of variables as the minimum-required CSS.
|
|
|
For example, the primary button atom is set to use the primary color for its background color:
|
|
|
`const Button = styled.button`background: ${props => props.theme.colorPrimary};``
|
|
|
```javascript
|
|
|
const Button = styled.button`background: ${props => props.theme.colorPrimary};`
|
|
|
```
|
|
|
|
|
|
For a complete list of variables, you can check the `pubsweet/design` [repo regarding variables](https://gitlab.coko.foundation/pubsweet/design/blob/master/OnTheming.md#variables).
|
|
|
|
|
|
#### Setting the vertical rhythm
|
|
|
A vertical rhythm is a way to bring consistency in spacing, so each UI component fits into place and none seems awkward (unless you design it that way). Therefore each component should use the same vertical grid for its internal layout. Setting the line-height of your body text as a `gridUnit` variable is a good way to keep a coherent relationship between your text and your non-textual elements.
|
|
|
|
|
|
In HTML, the height of an element is always the result of this formula: `border‐top + padding‐top + content + padding‐bottom + border‐bottom`. Be sure that the result of the calculation is always a multiple of your `gridUnit`.
|
|
|
|
|
|
### Accessibility
|
|
|
Accessibility must be an important consideration in the choices of design and UI/UX made for PubSweet. As a minimum, all PubSweet components must comply with the Web Content Accessibility Guidelines (WCAG) version 2.0 at level AA. There is no simple checklist or automated test for this but here are some things to keep in mind:
|
|
|
* Ensure that all forms and controls can be operated using the keyboard only. This includes having a recognisable style on the currently-focused element.
|
... | ... | @@ -125,11 +121,6 @@ Accessibility must be an important consideration in the choices of design and UI |
|
|
* [Authoring Tool Accessibility Guidelines (ATAG)](https://www.w3.org/WAI/standards-guidelines/atag/)
|
|
|
* [The A11Y project](https://a11yproject.com)
|
|
|
* [Inclusive Components](https://inclusive-components.design)
|
|
|
|
|
|
## Setting the vertical rhythm
|
|
|
A vertical rhythm is a way to bring consistency in spacing, so each UI component fits into place and none seems awkward (unless you design it that way). Therefore each component should use the same vertical grid for its internal layout. Setting the line-height of your body text as a `gridUnit` variable is a good way to keep a coherent relationship between your text and your non-textual elements.
|
|
|
|
|
|
In HTML, the height of an element is always the result of this formula: `border‐top + padding‐top + content + padding‐bottom + border‐bottom`. Be sure that the result of the calculation is always a multiple of your `gridUnit`.
|
|
|
|
|
|
# Using components
|
|
|
Using a component is as simple as installing it, configuring it, and then including the functionality it exports in your own app's code.
|
... | ... | @@ -166,52 +157,64 @@ Each component's README.md should specify which configuration options can be use |
|
|
|
|
|
### Example snippets from AppBar component.
|
|
|
The app bar appears at the top of every page of the application. It displays the name of the application (as a link to the home page), the //username of the current user, and a link to sign out.
|
|
|
|
|
|
Functionality customization:
|
|
|
```
|
|
|
```javascript
|
|
|
<AppBar brand="xpub" user={{ username: 'user', admin: true }} />
|
|
|
//When the user is not signed in, only the login link is displayed. <AppBar brand="xpub" />
|
|
|
//Can optionally pass navigation links. <AppBar
|
|
|
brand="xpub" navLinkComponents={[
|
|
|
<Action active to="/home"> Home
|
|
|
</Action>,
|
|
|
<Action to="/about">About</Action>, ]}
|
|
|
user={{ username: 'user', admin: true,
|
|
|
}} />
|
|
|
//Can use a custom component as right element.
|
|
|
//Right component props - the right component will be passed the following props: // - user - the current logged in user; null if no user is logged in
|
|
|
|
|
|
// When the user is not signed in, only the login link is displayed. <AppBar brand="xpub" />
|
|
|
// Can optionally pass navigation links.
|
|
|
<AppBar
|
|
|
brand="xpub"
|
|
|
navLinkComponents={[
|
|
|
<Action active to="/home">Home</Action>,
|
|
|
<Action to="/about">About</Action>,
|
|
|
]}
|
|
|
user={{ username: 'user', admin: true }}
|
|
|
/>
|
|
|
|
|
|
// Can use a custom component as right element.
|
|
|
// Right component props - the right component will be passed the following props:
|
|
|
// - user - the current logged in user; null if no user is logged in
|
|
|
// - onLogoutClick - the logout function
|
|
|
// - loginLink - link to redirect users to login
|
|
|
const RightComponent = ({ user, loginLink, onLogoutClick }) => (
|
|
|
<div style={{
|
|
|
display: 'flex',
|
|
|
width: 200,
|
|
|
justifyContent: 'space-between',
|
|
|
}} >
|
|
|
<span>{user ? user.username : 'admin'}</span>
|
|
|
<button onClick={onLogoutClick}>logout</button> </div>
|
|
|
<div style={{
|
|
|
display: 'flex',
|
|
|
width: 200,
|
|
|
justifyContent: 'space-between',
|
|
|
}}>
|
|
|
<span>{user ? user.username : 'admin'}</span>
|
|
|
<button onClick={onLogoutClick}>logout</button>
|
|
|
</div>
|
|
|
)
|
|
|
<AppBar
|
|
|
brand="xpub"
|
|
|
user={{ username: 'userName', admin: true }} rightComponent={RightComponent} onLogoutClick={() => console.log('Logout clicked')}
|
|
|
brand="xpub"
|
|
|
onLogoutClick={() => console.log('Logout clicked')}
|
|
|
rightComponent={RightComponent}
|
|
|
user={{ username: 'userName', admin: true }}
|
|
|
/>
|
|
|
```
|
|
|
Style customization:
|
|
|
|
|
|
PubSweet 83
|
|
|
|
|
|
Edit your theme.js file under cssOverrides to override desired properties:
|
|
|
const cokoTheme = { //....
|
|
|
cssOverrides: { AppBar: {
|
|
|
Root: css`
|
|
|
box-shadow: 0 0 1px ${th('colorPrimary')}; margin-bottom: 1px;
|
|
|
`,
|
|
|
LogoLink: css`
|
|
|
&:hover:before {
|
|
|
visibility: hidden; }
|
|
|
`, }
|
|
|
} }
|
|
|
```javascript
|
|
|
const cokoTheme = {
|
|
|
// ...
|
|
|
cssOverrides: {
|
|
|
AppBar: {
|
|
|
Root: css`
|
|
|
box-shadow: 0 0 1px ${th('colorPrimary')};
|
|
|
margin-bottom: 1px;
|
|
|
`,
|
|
|
LogoLink: css`
|
|
|
&:hover:before {
|
|
|
visibility: hidden;
|
|
|
}
|
|
|
`,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
export const cokoTheme
|
|
|
``` |
|
|
# Next steps
|
|
|
* Learn how to use components in your app.
|
|
|
* Take a look at the component library to see what existing components can do
|
|
|
* See our component developer guide to learn how to create your components. |