import { Meta, Story, Preview, Source } from '@storybook/addon-docs/blocks';
import {
  Button,
  sx,
  Monterey,
  useTheme,
  View,
  Text,
  theme,
} from '@tedconf/monterey';
import { Link } from '../.storybook/preview';
import { providerSource } from './index.story.tsx';

<Meta title="Readme|Emotion User" />

<Story name="intro">
  <Monterey />
</Story>

# Emotion / Styled-components Users

<br />
<br />
<br />

## Montery uses `emotion` at its core.

Emotion provides a stable and performant base upon which components can be built. For these reasons, Monterey leverages it as the core of its CSS generation. Familiarity with emotion is important, but that's not the only knowledge that will help you to be effective.

#### Meet styled-system

[`styled-system`](https://styled-system.com/) builds upon the success of `emotion`, but weaves in the power of [design tokens](https://css-tricks.com/what-are-design-tokens/). The result is a design system that makes it easy to do the right thing. If you're interested in diving deeper, check out [The Three Tenets of Styled System](https://jxnblk.com/blog/the-three-tenets-of-styled-system/).

## The most important concepts in Monterey

Monterey is built on a [theme](https://system-ui.com/theme/). In a normal `emotion` project, you access that theme like this:

<Source
  code={`
<Text
  as="h1"
  css={theme => ({
    ...theme.textStyles.bigAndBold,
    color: theme.colors.grayDarker,
  })}
>Manual Labor</Text>
`}
/>

_note: we're using a `Text` component here, and using the [`as` prop](https://emotion.sh/docs/styled#as-prop) to assign a tag. This is a common pattern in `emotion`, and we also put it to use in Monterey._

That _works_, but for Monterey, we wanted to make our design tokens the _default choices_ rather than opt-in.

## Essential Components

Take note of 3 things.

1. The `<Text>` component, as mentioned above.
2. The `variant` prop.
3. The `color` prop.

#### Text

<Preview withSource="open">
  <Story name="Text Component">
    <Text as="h1" variant="5" color="gray.1">
      How motivation can fix public systems
    </Text>
  </Story>
</Preview>

The text component is an opinionated building block which lets you choose from any of Monterey's prescriptive text styles. This should be used in place of _all_ `spans`, headings, and any other places that you're rendering text on a page.

You select which option you'd like to apply via the `variant` prop. These are simple and concise prescriptions for consistent and beautiful text styles. See the <Link kind="primitives-text" story="kitchen-sink">`Text` Docs</Link> for a run-down of these variants.

You can also assign a color from Monterey’s <Link kind="tokens" story="colors">Color Tokens</Link>. Colors are numbered where closer to `0` means closer to black.

#### View

<Preview withSource="open">
  <Story name="View Component">
    <View
      sx={{
        padding: 5,
        backgroundColor: 'TEDRed.0',
        color: 'white',
      }}
    >
      How motivation can fix public systems
    </View>
  </Story>
</Preview>

Monterey provides another type of component, speicifically an opinionated but flexible layout component called `<View>`.

## The sx prop

If you show the code on the example above, you’ll notice that unlike the `Text` component, it has as _single_ `sx` prop. Think of the `sx` prop as emotion's `css` prop, but aware of Monterey's design tokens. ["sx" is an abbreviation for "system"](https://github.com/styled-system/styled-system/issues/553#issuecomment-505198162), as authored by styled-system.

When Should you use `sx`? When should you use `css`? Always use sx. Use it the same way you'd use `css`, but know that it will use Monterey's design tokens as values. For example, `color: 'black'` will result in Monterey's black, not CSS black.

The `<View>` component is intended for layout. As such, it comes with some constraints. The `sx` prop will only allow properties related to layout, specifically [those listed here](https://github.com/tedconf/monterey/blob/master/src/components/view/index.tsx#L15-L27). If your editor supports referencing typescript type definitions, these constraints will be very easy to reference. Think of it as "anything that impacts the position of my elements", plus colors, borders, and shadows.

`<View>` should replace `<div>`s just about everywhere. It also supports the `as` prop so you can give it semantic meaning (or not).

## Example

What can we do with these two components? Lets code up a "Tweet" component:

<Preview withSource="open">
  <Story name="Tweet Sample">
    <View
      sx={{
        padding: 2,
        backgroundColor: 'black',
        maxWidth: 150,
      }}
    >
      <View
        sx={{
          padding: 5,
          backgroundColor: 'white',
          color: 'black',
          borderRadius: 2,
        }}
      >
        <View
          sx={{
            width: '100%',
            flexDirection: 'row',
            alignItems: 'center',
            justifyContent: 'space-between',
            flexWrap: 'wrap',
            marginBottom: 2,
          }}
        >
          <View
            sx={{ flexDirection: 'row', marginY: [1, 0], alignItems: 'center' }}
          >
            <View
              as="img"
              width="50"
              height="50"
              src="https://api.adorable.io/avatars/100/1"
              sx={{
                borderRadius: 'round',
                marginRight: 3,
              }}
            />
            <View>
              <Text
                variant="1b"
                sx={{
                  '&:hover': { color: 'TEDRed.0', textDecoration: 'underline' },
                }}
              >
                Jacob Barrieault
              </Text>
              <View sx={{ marginTop: 1 }}>
                <Text color="gray.0" variant="-1r">
                  @jbarrieault
                </Text>
              </View>
            </View>
          </View>
          <View sx={{ alignItems: 'flex-end', marginY: [1, 0] }}>
            <Button variant="ghost" size="sm">
              Follow
            </Button>
          </View>
        </View>
        <View>
          <Text variant="3">
            Mark Zuckerberg is the ultimate proof that money cannot buy a good
            haircut.
          </Text>
        </View>
        <View sx={{ marginY: 2 }}>
          <Text variant="-1r" color="gray.0">
            12:44 PM – 23 Oct 2019
          </Text>
        </View>
        <View
          sx={{
            flexDirection: 'row',
            justifyContent: 'spaceBetween',
            alignItems: 'center',
            width: '100%',
          }}
        >
          <View
            as="button"
            sx={{
              width: 'auto',
              flexGrow: 0,
              flexDirection: 'row',
              paddingY: '14px',
              alignItems: 'center',
              paddingRight: 2,
              borderWidth: 1,
              borderLeftWidth: 0,
              borderStyle: 'solid',
              borderColor: 'gray.6',
              color: 'gray.1',
              '&:hover': {
                color: 'TEDRed.0',
              },
            }}
          >
            <Text variant="-1u">2</Text> {'\u00A0'}
            <Text variant="-1u">Likes</Text>
          </View>
          <View
            sx={{
              flexDirection: 'row',
              borderWidth: 0,
              borderTopWidth: 1,
              borderBottomWidth: 1,
              borderStyle: 'solid',
              borderColor: 'gray.6',
              paddingY: 3,
              paddingLeft: 2,
              width: '100%',
            }}
          >
            <View
              as="img"
              width="22"
              height="22"
              src="https://api.adorable.io/avatars/50/2"
              sx={{
                borderRadius: 'round',
                marginRight: 3,
              }}
            />
            <View
              as="img"
              width="22"
              height="22"
              src="https://api.adorable.io/avatars/50/3"
              sx={{
                borderRadius: 'round',
                marginRight: 3,
              }}
            />
            <View
              as="img"
              width="22"
              height="22"
              src="https://api.adorable.io/avatars/50/4"
              sx={{
                borderRadius: 'round',
                marginRight: 3,
              }}
            />
          </View>
        </View>
      </View>
    </View>
  </Story>
</Preview>

There are a few things to make note of here.

- This is construced _entirely_ of monterey components, meaning all of our unique values are from _design tokens_. That gives us uniform spacing, harmonious color, and consistent textual hierarchy.
- The `View` component, by default, is set to `display: flex` and `flexDirection: column`, as done [in `react-native-web`](https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/View/index.js#L84-L86).
- [Responsive styles](https://styled-system.com/responsive-styles) are handled differently than in typical `emotion` apps. They're passed as an array, the first value being the "base", the second being at the smallest breakpoint, and the following increasing in size. this is a convenience that drastically shortens the expression of responsive styles.
- The use of a few shorthands such as `marginY`. [See all available shorthands](https://styled-system.com/table).

#### Outliers

Sometimes (if you come across one of these scenarios, please [open an issue](https://github.com/tedconf/monterey/issues/new) and tell us about it), you might not be able to use a Monterey component In these cases, you can use the `sx` function. It behaves just like the `sx` prop, but returns instead a value that can be passed to emotion's `css` prop OR a plain old style prop.

<Preview withSource="open">
  <Story name="Sx Function Sample">
    <div
      style={sx({
        padding: 3,
        backgroundColor: 'TEDRed.0',
        color: 'white',
      })(theme)}
    >
      All in a style prop
    </div>
  </Story>
</Preview>

Notice we're passing "theme" argument here explicitly. If you're using `emotion` and the `css` prop, this is done automatically.

In other instances, you might need direct access to the `theme` object. for that, you can use the `useTheme` hook, exported from `@tedconf/monterey`.

## Close

You've come a long way and learned how Monterey can help you to write consistent and accurate experiences.

[Leave us some feedback](https://github.com/tedconf/monterey/issues/new) on how this document was. Any issues? Improvements? Did it help?
