# PseudoBox

This component is inspired by
[Tailwind CSS](https://tailwindcss.com/docs/pseudo-class-variants) Pseudo-Class
variants and [Glamorous Pseudo](https://github.com/tkh44/glamorous-pseudo/).

PseudoBox composes [Box](/box) component and provides props to style common CSS pseudo
selectors.

Styling elements on hover, focus, and more can be accomplished by prefixing `_`
with the appropriate pseudo selector.

For example, to style `&:hover`, use the `_hover` prop and pass the style props.
We use the underscore `_` notation to visually separate pseudo style props from
regular style props.

## Import

```js
import { PseudoBox } from "@blockstack/ui";
```

## Usage

```jsx
<Flex as="form">
  <PseudoBox
    as="input"
    placeholder="Your email"
    type="email"
    flex="1"
    py={2}
    px={4}
    rounded="md"
    bg="gray.100"
    borderWidth="1px"
    _hover={{ borderColor: "gray.200", bg: "gray.200" }}
    _focus={{
      outline: "none",
      bg: "white",
      boxShadow: "outline",
      borderColor: "gray.300"
    }}
  />
  <PseudoBox
    as="button"
    bg="teal.500"
    py={2}
    px={4}
    ml={3}
    rounded="md"
    fontWeight="semibold"
    color="white"
    _hover={{ bg: "teal.600" }}
    _focus={{ boxShadow: "outline" }}
  >
    Sign Up
  </PseudoBox>
</Flex>
```

PseudoBox includes first-class support for styling elements on hover, focus,
active, disabled, visited, first-child, last-child, odd-child, even-child,
focus-within, and more.

It was created to help reduce the need to pass `css` prop or use `styled(...)`
function to style common pseudo states.

### Hover

Add the `_hover` prop to only apply style props on hover.

```jsx
<PseudoBox
  as="button"
  color="blue.700"
  fontWeight="semibold"
  py={2}
  px={4}
  borderWidth="1px"
  borderColor="blue"
  rounded="md"
  _hover={{ bg: "blue", color: " white" }}
  _focus={{ boxShadow: "high" }}
>
  Hover me
</PseudoBox>
```

### Focus

Add the `_focus` prop to only apply a styles on focus.

```jsx
<PseudoBox
  as="input"
  placeholder="Focus me"
  py={2}
  px={4}
  bg="white"
  color="ink"
  borderColor="ink.100"
  borderWidth="2px"
  rounded="md"
  _focus={{ bg: "white", borderColor: "blue" }}
/>
```

### Active

Add the `_active` prop to only apply a styles on active.

```jsx
<PseudoBox
  as="button"
  fontWeight="semibold"
  py={2}
  px={4}
  rounded="md"
  color="white"
  bg="blue"
  _active={{ bg: "green" }}
  _focus={{ boxShadow: "outline" }}
>
  Click me
</PseudoBox>
```

### Disabled

Add the `_disabled` prop to style an element when it is disabled. This style
will apply when the `disabled` or `aria-disabled` attribute of an element is set
to `true`

```jsx
<Stack isInline>
  <PseudoBox
    as="button"
    fontWeight="semibold"
    py={2}
    px={4}
    rounded="md"
    color="white"
    bg="blue.500"
    _active={{ bg: "blue.700" }}
    _focus={{ boxShadow: "outline" }}
  >
    Click me
  </PseudoBox>

  <PseudoBox
    as="button"
    disabled
    fontWeight="semibold"
    py={2}
    px={4}
    rounded="md"
    color="white"
    bg="blue.500"
    _active={{ bg: "blue.700" }}
    _focus={{ boxShadow: "outline" }}
    _disabled={{ opacity: 0.6 }}
  >
    Click me
  </PseudoBox>
</Stack>
```

### Visited

Add the `_visited` props to style a link that has been visited.

```jsx
<Stack isInline>
  <PseudoBox
    as="a"
    href="/radio"
    color="blue.600"
    textDecoration="underline"
    fontWeight="semibold"
  >
    Unvisited Link
  </PseudoBox>
  <PseudoBox
    as="a"
    href="/pseudobox"
    color="blue.600"
    textDecoration="underline"
    fontWeight="semibold"
    _visited={{ color: "purple.600" }}
  >
    Visited Link
  </PseudoBox>
</Stack>
```

### First Child

Add the `_first` prefix to style an element when it is the first-child of its
parent. This is mostly useful when elements are being generated in some kind of
loop.

```jsx
<Box borderWidth="1px" rounded="md">
  {["One", "Two", "Three"].map(item => (
    <PseudoBox
      key={item}
      px={4}
      py={2}
      borderTopWidth="1px"
      _first={{ borderTopWidth: 0 }}
    >
      {item}
    </PseudoBox>
  ))}
</Box>
```

### Last Child

Add the `_last` prefix to style an element when it is the last-child of its
parent. This is mostly useful when elements are being generated in some kind of
loop.

```jsx
<Box borderWidth="1px" rounded="md">
  {["One", "Two", "Three"].map(item => (
    <PseudoBox
      key={item}
      px={4}
      py={2}
      borderBottomWidth="1px"
      _last={{ borderBottomWidth: 0 }}
    >
      {item}
    </PseudoBox>
  ))}
</Box>
```

### Odd Child

Add the `_odd` prop to style an element when it is the odd-child of its parent.
This is mostly useful when elements are being generated in some kind of loop.

```jsx
<Box borderWidth="1px" rounded="md" overflow="hidden">
  {["One", "Two", "Three"].map(item => (
    <PseudoBox key={item} px={4} py={2} bg="white" _odd={{ bg: "gray.100" }}>
      {item}
    </PseudoBox>
  ))}
</Box>
```

### Even Child

Add the `_even` prop to style an element when it is the even-child of its
parent. This is mostly useful when elements are being generated in some kind of
loop.

```jsx
<Box borderWidth="1px" rounded="md" overflow="hidden">
  {["One", "Two", "Three"].map(item => (
    <PseudoBox key={item} px={4} py={2} bg="white" _even={{ bg: "gray.100" }}>
      {item}
    </PseudoBox>
  ))}
</Box>
```

### Group Hover

If you need to style a child element when hovering over a specific parent
element, add the `role="group"` attribute to the parent element, then you can
use `_groupHover` prop to style the child element.

```jsx
<PseudoBox
  role="group"
  maxW="sm"
  overflow="hidden"
  rounded="md"
  p={5}
  cursor="pointer"
  bg="white"
  boxShadow="md"
  _hover={{ bg: "blue.500" }}
>
  <PseudoBox
    fontWeight="semibold"
    fontSize="lg"
    mb={1}
    color="gray.900"
    _groupHover={{ color: "white" }}
  >
    New Project
  </PseudoBox>
  <PseudoBox color="gray.700" mb={2} _groupHover={{ color: "white" }}>
    Create a new project from a variety of starting templates.
  </PseudoBox>
</PseudoBox>
```

## Selectors and Props

PseudoBox can be used to style any interactive component. You can apply styles
to the following selectors. The selectors are also ARIA-friendly to help you
naturally use `aria` attributes for better accessibility.

All PseudoBox props can use the style props.
[Learn more about Style props](/style-props)

| Selector                               | Prop           |
| -------------------------------------- | -------------- |
| `&:hover`                              | `_hover`       |
| `&:active`                             | `_active`      |
| `&:focus`                              | `_focus`       |
| `&:before`                             | `_before`      |
| `&:after`                              | `_after`       |
| `&::placeholder`                       | `_placeholder` |
| `&:first-of-type`                      | `_first`       |
| `&:last-of-type`                       | `_last`        |
| `[role=group]:hover &`                 | `_groupHover`  |
| `&:disabled`, `[aria-disabled=true]`   | `_disabled`    |
| `&[readonly]`, `&[aria-readonly=true]` | `_readonly`    |
| `&[aria-checked=true]`                 | `_checked`     |
| `&[aria-selected=true]`                | `_selected`    |
| `&[aria-expanded=true]`                | `_expanded`    |
| `&[aria-invalid=true]`                 | `_invalid`     |
| `&[aria-pressed=true]`                 | `_pressed`     |
| `&[aria-invalid=true]`                 | `_invalid`     |
| `&[aria-grabbed=true]`                 | `_grabbed`     |
