Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
; top-most EditorConfig file
root = true

[*]
charset = utf-8

trim_trailing_whitespace = true

; Unix style line endings
end_of_line = lf

; Always end file on newline
insert_final_newline = true

; Indentation
indent_style = space
indent_size = 2
39 changes: 39 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"extends": [
"@zendeskgarden",
"@zendeskgarden/eslint-config/plugins/notice.js",
"plugin:react/recommended",
"plugin:jest/recommended",
"plugin:jsx-a11y/recommended",
"prettier"
],
"settings": {
"react": {
"version": "16.4.2"
}
},
"globals": {
"jest": true,
"BASE_PATH_NAME": true,
"PACKAGE_VERSION": true,
"COMPONENT_IDS": true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May not need this as containers don't expose component IDs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Austin94 plz weigh-in here, based on recent conversation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jzempel and I were discussing metrics this morning and came up with an interesting idea.

Would it be helpful to have a new data attribute specifically for the containers? i.e. data-garden-container-id and data-garden-version

This could help us identify areas where consumers have "ejected" into a container and help us identify new patterns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep I think that makes sense

},
"plugins": ["prettier", "react", "jest", "jsx-a11y"],
"env": {
"es6": true,
"browser": true,
"node": true
},
"rules": {
"prettier/prettier": "error",
"indent": ["error", 2],
"sort-imports": "off",
"valid-jsdoc": "off",
"no-invalid-this": "off",
"no-unused-expressions": ["error", { "allowShortCircuit": true }],
"react/jsx-key": "off",
"react/display-name": "off",
"jsx-a11y/label-has-for": "off",
"jest/no-disabled-tests": "off"
}
}
79 changes: 79 additions & 0 deletions .github/API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Garden Containers

A `Container` component is an abstraction of the state and accessibility logic of a composite component.

These Containers are implemented with the [render prop pattern](https://reactjs.org/docs/render-props.html) and **do not provide any UI**. They simply provide attributes, events, and internal state to a function which applies the information to any elements of its choosing.

* **Keyboard Navigable**
* Consistent navigation and component interaction strategy
* **Accessible**
* Built-in accessibility for standard and custom visualizations
* **Localizable**
* Built-in RTL aware and localizable components

If we wish to create a tab like interface, we would use `TabsContainer`:

```jsx
<TabsContainer>
{({ getTabListProps, getTabProps, getTabPanelProps, selectedKey, focusedKey }) => (
<div>
<div {...getTabListProps()}>
<div {...getTabProps({ key: 'tab-1' })}>
Tab 1
{'tab-1' === selectedKey && 'SELECTED'}
{'tab-1' === focusedKey && 'FOCUSED'}
</div>
<div {...getTabProps({ key: 'tab-2' })}>
Tab 2
{'tab-2' === selectedKey && 'SELECTED'}
{'tab-2' === focusedKey && 'FOCUSED'}
</div>
</div>
<div {...getTabPanelProps({ key: 'tab-1' })}>Tab 1 content</div>
<div {...getTabPanelProps({ key: 'tab-2' })}>Tab 2 content</div>
</div>
)}
</TabsContainer>
```

The `Container` implementation has the following requirements

* Accepts both the `render` and `children` props as valid render-props
* All collections of props that are meant to be spread to an element have the signature `getFooProps()`
* These props include all events necessary for component interaction as well as required accessibility roles and information
* To allow chaining of props and events, apply all props within the method. This allows the container to still apply any events if needed in the interaction model.
* Example implementation
```jsx
<div
{...getFooProps({
onClick: event => alert('clicked!'),
'data-clicked': true,
selected: 'all props are proxied through'
})}
/>
```
* You are able to prevent an event from being handled within the container by calling `event.preventDefault()`
* All internal state is provided within the render prop
* All `Container` components allow [uncontrolled](https://reactjs.org/docs/uncontrolled-components.html) and [controlled](https://reactjs.org/docs/forms.html#controlled-components) state management using the `onStateChanged` prop.
* An example `controlled` usage would be
```jsx
<TabsContainer
selectedKey={state.selectedKey}
focusedKey={state.focusedKey}
onStateChange={setState}
>
...
</TabsContainer>
```

`Container` components ensure that **ANY UI** is able to provide a consistent keyboard navigation and accessibility experience.

The render prop pattern is incredibly flexible in that it only enforces accessibility. If you find that the Containers are not flexible enough for your implementation, take a hard look at any negative accessiblity side-effects you would be introducing... then use the container :smile:

## Supporting Architecture

### Selection

All keyboard navigation is provided by the `<SelectionContainer />` component within the [@zendeskgarden/container-selection](../packages/selection) package.

This abstraction provides a base level of accessible keyboard navigation that is consumed within the other packages, but can also be used for custom components that require keyboard integration.
78 changes: 78 additions & 0 deletions .github/CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our
project and our community a harassment-free experience for everyone,
regardless of age, body size, disability, ethnicity, gender identity and
expression, level of experience, nationality, personal appearance, race,
religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual
attention or advances
* Trolling, insulting/derogatory comments, and personal or political
attacks
* Public or private harassment
* Publishing others' private information, such as a physical or
electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of
acceptable behavior and are expected to take appropriate and fair
corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct, or to ban
temporarily or permanently any contributor for other behaviors that they
deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public
spaces when an individual is representing the project or its community.
Examples of representing a project or community include using an
official project e-mail address, posting via an official social media
account, or acting as an appointed representative at an online or
offline event. Representation of a project may be further defined and
clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may
be reported by contacting the project team at garden@zendesk.com. The
project team will review and investigate all complaints, and will
respond in a way that it deems appropriate to the circumstances. The
project team is obligated to maintain confidentiality with regard to the
reporter of an incident. Further details of specific enforcement
policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in
good faith may face temporary or permanent repercussions as determined
by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor
Covenant][homepage], version 1.4, available at
[http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org [version]:
http://contributor-covenant.org/version/1/4/
92 changes: 92 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Contributing to Garden

Keen to contribute to Garden? We're stoked to have you join us. You may
find that opening an
[issue](https://github.com/zendeskgarden/react-containers/issues) is the
best way to get a conversation started. When you're ready to submit a
pull request, follow the [steps](#pull-request-workflow) below. We
follow a [code of conduct](CODE_OF_CONDUCT.md) as our guide for
community behavior.

This is a multi-package repo which uses [Lerna](https://lernajs.io/) to
manage shared and cross-package dependencies. The basic repo layout
includes:

* `├── package.json` – the top-level "project" package that contains
the dependencies and scripts needed to manage the multi-package repo.
_This package will never be published to the registry._
* `└─── packages/` – the folder that contains individual `@zendeskgarden`
packages which are published to the registry.

For an overview of our container architecture, view our [API
documentation](API.md).

## Versioning Workflow

Garden follows [semantic versioning](https://semver.org/). We release
patch versions for bugfixes, minor versions for new features, and major
versions for any breaking changes.

The [pull request workflow](#pull-request-workflow) along with the [PR
template](PULL_REQUEST_TEMPLATE.md) will help us determine how to
version your contributions.

All changes are recorded in applicable package CHANGELOG files after
your PR is merged.

## Development Workflow

Before you start, be sure [yarn](https://yarnpkg.com/en/) is installed
on your system. After you clone this repo, run `yarn` to install
dependencies needed for development. After installation, the following
commands are available:

- `yarn start` to launch Styleguidist with live reload.
- `yarn test` to run Jest testing.
- `yarn lint` to enforce consistent JavaScript and
markdown code conventions across all container packages. Note this is
run as a git `pre-commit` hook.
- `yarn format` to enforce code style with opinionated
formats across all container packages. Note this is run as a git
`pre-commit` hook.
- `yarn build` to rebuild distributions across all packages.
The build runs as part of the initial install. Operates as a facade
over a Lerna command; operation may be modified using option
[flags](https://github.com/lerna/lerna#flags) (i.e. `scope`, `since`,
or `ignore`).
- `yarn new` to generate a new React container based on a package
template.

See our [development documentation](DEVELOPMENT.md) for package
implementation requirements.

## Pull Request Workflow

1. Fork the repo and create a branch. Format your branch name as
`username/verb-noun`.
1. If you haven't yet, get comfortable with the [development
environment](#development-workflow).
1. Regularly `git commit` locally and `git push` to the remote branch.
Use whatever casual commit messaging you find suitable. We'll help
you apply an appropriate squashed [conventional
commit](https://conventionalcommits.org/) message when it's time to
merge to master.
1. If your changes result in a major modification, be sure all
documentation is up-to-date.
1. When your branch is ready, open a new pull request via GitHub.
The repo [PR template](PULL_REQUEST_TEMPLATE.md) will guide you
toward describing your contribution in a format that is ultimately
suitable for a structured conventional commit (used to automatically
advance published package versions).
1. Every PR must pass CI checks and receive at least one :+1: to be
considered for merge.
1. Garden
[maintainers](https://github.com/orgs/zendeskgarden/teams/maintainers)
will manage the squashed merge to master, using your PR title and
description as the scope, description, and body for a conventional
commit.

## License

By contributing to Garden, you agree that your contributions will be
licensed under the [Apache License, Version 2.0](LICENSE.md).
71 changes: 71 additions & 0 deletions .github/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Garden React Development

This is a multi-package repo which uses [Lerna](https://lernajs.io/) to
manage shared and cross-package dependencies.

For further contribution guidelines view our [contribution documentation](CONTRIBUTING.md).

All packages must be implemented following the requirements listed below.

## Creating New Packages

We have abstracted the creation of packages into the `yarn new` command. When prompted, provide a base name for your package (i.e. if provided "example" the command will create the `@zendeskgarden/container-example` package in the `packages/example` path).

### Dependencies

All dependencies required by a package must be kept in its specific `package.json`. The `lerna add` command can help automate this.

### Documentation

Documentation is generated for each package using [react-styleguidist](https://react-styleguidist.js.org/).

A shared, global config (including webpack modifications) can be found at [utils/styleguide/styleguide.base.config.js](utils/styleguide/styleguide.base.config.js).

Each package can override the global config with its local `styleguide.config.js` file. The most common use case for this is creating a sidebar layout custom to the packages directory structure.

To include examples with your code include a markdown file. `FooContainer.js` would be documented with `FooContainer.example.md`.

To start the documentation in development mode use the `yarn start` command.

```sh
# Prompts for an individual package
yarn start

# Starts the individual package immediately
yarn start --scope @zendeskgarden/container-tabs
```

## Component Requirements

### Containers

All containers must

* Be implemented using the [render prop pattern](https://reactjs.org/docs/render-props.html)
* Provide `uncontrolled` and `controlled` state management if necessary
* Be implemented with the `ControlledComponent` state abstractions if necessary
* Provide the minimum number of events and attributes to implement the appropriate [W3C WAI-ARIA Design Pattern](https://www.w3.org/TR/wai-aria-practices/#aria_ex)
* Only use events and attributes that work with **ANY** DOM element (within reason)

## Building Containers

The packages are built using webpack which creates several artifacts:

* `commonjs` bundle
* Used by the majority of consumers
* All dependencies are `external` and not included in the bundle
* `umd` bundle
* Can be consumed in browser with a standard `<script>` tag
* All dependencies are bundled to allow easy consumption

## Testing Components

All `Container` components must only test the surface area that they are implementing. (i.e. Since `TabsContainer` is implemented with the `SelectionContainer` it does not need to test all keyboard navigation).

These tests should be implemented with standard assertions using the Enzyme shallow renderer when possible.

## Linting and Formatting Components

All JS and Markdown files are linted respectively with eslint, and markdownlint.

Additionally, prettier is used to format all JS, Markdown, and package.json files.
Loading