Skip to content

Commit

Permalink
docs(Shorthand|Theming): rework docs to be more actual (#3564)
Browse files Browse the repository at this point in the history
* docs(Shorthand|Theming): rework docs to be more actual

* remove extension
  • Loading branch information
layershifter authored Apr 15, 2019
1 parent c532f72 commit 3067f5a
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 58 deletions.
11 changes: 11 additions & 0 deletions docs/public/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ body {
opacity: 0;
}

blockquote {
border-left: 3px solid rgba(34, 36, 38, .15);
margin-left: 0;
padding-left: 10px;
font-style: italic;
}

h1:hover > .anchorjs-link:not(:hover),
h2:hover > .anchorjs-link:not(:hover),
h3:hover > .anchorjs-link:not(:hover),
Expand Down Expand Up @@ -59,9 +66,11 @@ code:not(.hljs)::after {
background: #fff;
box-shadow: 0 1px 2px #ccc;
}

.docs-example:hover {
box-shadow: 0 2px 8px #bbb;
}

.docs-example.active {
box-shadow: 0 8px 32px #aaa;
}
Expand Down Expand Up @@ -109,6 +118,7 @@ code:not(.hljs)::after {
font-size: 13px;
color: #aaa;
}

.carbon-text:hover {
color: #ddd;
}
Expand All @@ -120,6 +130,7 @@ code:not(.hljs)::after {
opacity: 0.5;
white-space: nowrap;
}

.carbon-poweredby:hover {
color: #ddd;
}
3 changes: 2 additions & 1 deletion docs/src/components/CodeEditor/CodeEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Ace from 'react-ace'
import 'brace'
import 'brace/ext/language_tools'
import 'brace/mode/jsx'
import 'brace/mode/json'
import 'brace/mode/html'
import 'brace/mode/sh'
import 'brace/theme/tomorrow_night'
Expand Down Expand Up @@ -95,7 +96,7 @@ const semanticUIReactCompleter = {
},
}

const CodeEditor = props => (
const CodeEditor = (props) => (
<Ace
{...props}
name={`docs-editor-${_.uniqueId()}`}
Expand Down
14 changes: 9 additions & 5 deletions docs/src/components/CodeSnippet/CodeSnippet.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ const labelStyle = {
zIndex: 100,
}

const formatters = {
html: (val) => formatCode(val, 'html'),
json: (val) => val,
jsx: (val) => formatCode(val, 'babel').replace(/^;</m, '<'), // will replace ";" from the beginning of line
sh: (val) => val.replace(/^/g, '$ '),
}

const CodeSnippet = ({ fitted, label, mode, value, ...rest }) => (
<div style={{ ...containerStyle, margin: fitted ? 0 : '1rem 0' }}>
<div style={labelStyle}>{label || mode}</div>
Expand All @@ -34,10 +41,7 @@ const CodeSnippet = ({ fitted, label, mode, value, ...rest }) => (
readOnly
showGutter={false}
showCursor={false}
value={(mode === 'sh'
? value.replace(/^/g, '$ ')
: formatCode(value, mode === 'html' ? 'html' : 'babel')
).trim()}
value={formatters[mode](value).trim()}
{...rest}
/>
</div>
Expand All @@ -46,7 +50,7 @@ const CodeSnippet = ({ fitted, label, mode, value, ...rest }) => (
CodeSnippet.propTypes = {
fitted: PropTypes.bool,
label: PropTypes.string,
mode: PropTypes.oneOf(['html', 'jsx', 'sh']),
mode: PropTypes.oneOf(['html', 'json', 'jsx', 'sh']),
value: PropTypes.string.isRequired,
}

Expand Down
13 changes: 8 additions & 5 deletions docs/src/components/DocumentationPage/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import CodeSnippet from 'docs/src/components/CodeSnippet'

export const a = ({ children, href }) => <Link to={href}>{children}</Link>

export const code = ({ className, children }) => {
const mode = className.replace('language-', '')

return <CodeSnippet mode={mode} value={children} />
}
export const code = ({ className, children, fitted, label }) => (
<CodeSnippet
fitted={fitted}
mode={className.replace('language-', '')}
label={label}
value={children}
/>
)

export const h1 = ({ children }) => <Header as='h1' content={children} textAlign='center' />

Expand Down
14 changes: 10 additions & 4 deletions docs/src/components/Sidebar/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Sidebar extends Component {
menuItemsByType = _.map((nextType) => {
const items = _.flow(
_.filter(({ type }) => type === nextType),
_.map(info => (
_.map((info) => (
<Menu.Item
key={info.displayName}
name={info.displayName}
Expand Down Expand Up @@ -220,13 +220,19 @@ class Sidebar extends Component {
Introduction
</Menu.Item>
<Menu.Item as={Link} exact to='/usage' activeClassName='active'>
Usage
Get Started
</Menu.Item>
<Menu.Item as={Link} exact to='/augmentation' activeClassName='active'>
Augmentation
</Menu.Item>
<Menu.Item as={Link} exact to='/shorthand-props' activeClassName='active'>
Shorthand Props
</Menu.Item>
<Menu.Item as={Link} exact to='/theming' activeClassName='active'>
Theming
</Menu.Item>
<Menu.Item as={Link} exact to='/layouts' activeClassName='active'>
Layouts
Layout examples
</Menu.Item>
<Menu.Item as={Link} exact to='/prototypes' activeClassName='active'>
Prototypes
Expand All @@ -238,7 +244,7 @@ class Sidebar extends Component {
<Input
fluid
icon={{ name: 'filter', color: 'teal', inverted: true, bordered: true }}
placeholder='Press &quot;/&quot; to filter components'
placeholder='Press "/" to filter components'
value={query}
onChange={this.handleSearchChange}
onKeyDown={this.handleSearchKeyDown}
Expand Down
35 changes: 35 additions & 0 deletions docs/src/pages/Augmentation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Header, Message } from 'semantic-ui-react'

export const meta = {
title: 'Augmentation',
}

<Header as='h1' content='Augmentation' textAlign='center' />

React components are inherently composable. Semantic UI React makes them even more so with the `as` prop feature: you can control the rendered HTML tag, or render one component as another component.

```jsx
<>
// will produce <button class='ui button' />
<Button />
// 🔨 will produce <a class='ui button' />
<Button as='a' />
</>
```

Augmentation is powerful. You can compose component features and props without adding extra nested components. This is essential for working with `MenuLink`s and `react-router`.

<Message info size='mini'>
Unhandled props by a component are passed to the component you are rendering <code>as</code>.
</Message>

```jsx
import { Link } from 'react-router-dom'

;<Menu>
// 💡 `to` does not belong to `Menu.Item` props and will be passed to `Link`
<Menu.Item as={Link} to='/home'>
Home
</Menu.Item>
</Menu>
```
4 changes: 2 additions & 2 deletions docs/src/pages/Layouts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { Link } from 'react-static'
import { Card, Header } from 'semantic-ui-react'

export const meta = {
title: 'Layouts',
title: 'Layout examples',
}

<Header as='h1' content='Layouts' textAlign='center' />
<Header as='h1' content='Layout examples' textAlign='center' />

<Header as='h2' content='Starter' subheader='Examples to introduce components and their function' />

Expand Down
109 changes: 109 additions & 0 deletions docs/src/pages/ShorthandProps.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { Header, Icon, Message } from 'semantic-ui-react'

export const meta = {
title: 'Shorthand Props',
}

<Header as='h1' content='Shorthand Props' textAlign='center' />

It is quite common for Semantic UI React component to have "shorthands" which accept shorthand values. For example, `Button` component has an `icon` shorthand which value defines the icon that will be rendered.

```jsx
<Button icon='like' />
```

There are several forms of shorthand values that can be provided, but all of them share one common thing - each is eventually evaluated to React Element. Thus, you can think of shorthand values as a recipe to customize rendered React Element at corresponding shorthand.

## Object as value

Each component's shorthand has associated default element type. For example, by default there is `<Icon />` element rendered for `Button`'s icon shorthand. It is possible to customize props of this default element by providing props object as shorthand value:

```jsx
// 💡 'color' and 'name' will be used as <Icon /> element's props
<Button content='Like' icon={{ color: 'red', name: 'like' }} />
```

## String as value

There is even shorter way to define default element's props - by using a primitive value. In that case provided shorthand value will be taken as a value for "default prop" of this element.

This could be much easier seen with an example. Here, again, we have a `Button` element with its icon being defined with shorthand - where provided `string` value will be used as icon's `name`:

```jsx
<>
<Button content='Like' icon='like' />
// 💡 has identical effect to the previous one
<Button content='Like' icon={{ name: 'like' }} />
</>
```

This works because name is the default prop of shorthand's `<Icon />` element.

```jsx
<>
<Modal trigger={<Button>Show</Button>} content='Content' />
// 💡 has identical effect to the previous one
<Modal trigger={<Button>Show</Button>} content={{ content: 'Content' }} />
// ⛔ example below has broken styling, see section about React Element
<Modal trigger={<Button>Show</Button>} content={<div>Content</div>} />
</>
```

## Disable shorthand's rendering

It is also possible to pass falsy values (`false`, `null` or `undefined`) to shorthand prop - in that case there will be nothing rendered for the component's shorthand.

```jsx
<Dropdown icon={null} />
```

## React Element as value

There are cases where it might be necessary to customize element tree that will be rendered as a shorthand's value. Returning to `Button` example, we might want to render `<i />` instead of default `<Icon />` element. In that case necessary element might be directly provided as shorthand value:

```jsx
<Button icon={<i className='my-icon' />} />
```

<Message icon size='small' warning>
<Icon name='warning' />
<Message.Content>
There is a very important caveat here, though: whenever React Element is directly used as a
shorthand value, all props that Semantic UI React has created for the shorthand's Component will
be spread on the passed element. This means that provided element should be able to handle props
- while this requirement is satisfied for all SUIR components, you should be aware of that when
either HTML or any third-party elements are provided.
</Message.Content>
</Message>

Due to this limitation, you should strive to use other options for shorthand values whenever is possible - for instance, this is how previous example can be rewritten:

```jsx
<Button icon={{ as: 'i', className: 'my-icon' }} />
```

However, there still might be cases where it would be impossible to use object form of the shorthand value - for example, you might want to render some custom elements tree for the shorthand. In that case function value should be used.

## Function as value

Providing function as a shorthand value is the most involving but, at the same time, the most powerful option for customizing component's shorthand. The only requirements for this function are:

- it should finish syncronously
- it should return React Element as a result

Thus, in its simplest form, it could be used the following way:

```jsx
<Button
content='Like'
icon={(Component, componentProps) => <Component {...componentProps} color='red' name='like' />}
/>
```

## Customizing rendered shorthand

There is another use case when render function is very useful for - this is the case where custom element's tree should be rendered for the shorthand. As you might recall, there is a problem that might happen when React Element is provided directly as shorthand value - in that case props are not propagated to rendered. In order to avoid that the following strategy should be considered:

```jsx
<Button content='Like' icon={(Component, componentProps) => <Label basic>+1</Label>} />
```
Loading

0 comments on commit 3067f5a

Please sign in to comment.