---
id: 67bf4350777ac6ffdc027745
title: Build a Color Picker App
challengeType: 25
dashedName: build-a-color-picker-app
demoType: onClick
---

# --description--

**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.

**User Stories:**

1. You should define and export a `ColorPicker` component.
1. You should use the `useState` hook.
1. You should have a `#color-picker-container` element with a white background.
1. You should have a `#color-input` element which should be a `color` input.
1. Your `#color-input` should be a child of `#color-picker-container`.
1. When `#color-input` is changed, `#color-picker-container` should have its background set to that new value.

# --hints--

You should define and export a `ColorPicker` component.

```js
  const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src ===  "index.jsx").innerText;

  const exports = {};
  const _a = eval(script);

  assert.property(exports, "ColorPicker");
```

You should use the `useState` hook.

```js
    const abuseState = __helpers.spyOn(React, "useState");
    const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText;
    const exports = {};
    const _a = eval(script);
    const _b = await __helpers.prepTestComponent(exports.ColorPicker);
    assert.isAtLeast(abuseState.calls.length, 1);
```

You should use the return value of the `useState` hook.

```js
assert.match(code, /=\s*(?:React\.)?useState\(/);
```

You should use array destructuring to assign the return value of `useState` to two variables.

```js
assert.match(code, /\[.*,.*\]\s*=\s*(?:React\.)?useState\(/);
```

You should pass `#ffffff` as the initial value to your `useState` call.

```js
    const abuseState = __helpers.spyOn(React, "useState");
    const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText;
    const exports = {};
    const _a = eval(script);
    const _b = await __helpers.prepTestComponent(exports.ColorPicker);
    assert.match(abuseState.calls[0], /#ffffff/i);
```

You should render an element with `color-picker-container` as the `id`.

```js
assert.exists(document.getElementById("color-picker-container"));
```

Your `#color-picker-container` should have a white background initially.

```js
const el = document.getElementById("color-picker-container");
const style = window.getComputedStyle(el);
assert.strictEqual(style.backgroundColor, "rgb(255, 255, 255)");
```

You should render an `input` element with an `id` of `color-input`.

```js
const inputMaybe = document.getElementById("color-input");
assert.exists(inputMaybe);
assert.strictEqual(inputMaybe?.tagName, "INPUT");
```

Your `#color-input` should be a child of `#color-picker-container`.

```js
const inputPossibly = document.getElementById("color-input");
const parent = inputPossibly.parentElement;
assert.exists(parent);
assert.strictEqual(parent.getAttribute("id"), "color-picker-container");
```

Your `#color-input` should be a `color` input.

```js
const inputDefinitely = document.getElementById("color-input");
assert.equal(inputDefinitely?.type, "color");
```

Your `#color-input` should have an `onChange` attribute.

```js
const definitelyAnInput = document.getElementById("color-input");
assert.exists(definitelyAnInput);
const key = Object.keys(definitelyAnInput).find(key => key.startsWith("__reactProps"));
const reactInstance = definitelyAnInput[key]
assert.exists(reactInstance);
assert.isFunction(reactInstance.onChange);
```

Your `#color-input` should have an initial value of `#ffffff`.

```js
const mostCertainlyAnInput = document.getElementById("color-input");
assert.exists(mostCertainlyAnInput);
assert.strictEqual(mostCertainlyAnInput.value, "#ffffff");
```

The initial value of your `#color-input` should be managed by your `useState` hook.

```js
const abuseState = __helpers.spyOn(React, "useState");
const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText;
const exports = {};
const _a = eval(script);

const rendered = await __helpers.prepTestComponent(exports.ColorPicker);
const inputElement = rendered.querySelector('#color-input');
assert.exists(inputElement, "Could not find #color-input element");

const initialValue = inputElement.value;

const stateIndex = abuseState.returns.findIndex(([stateValue]) => stateValue === initialValue);
assert.isAtLeast(stateIndex, 0, "The #color-input value must be managed by a useState hook");

const [, setterFunction] = abuseState.returns[stateIndex];

const newColor = '#123456';
await React.act(async () => {
  setterFunction(newColor);
});

assert.strictEqual(
  inputElement.value,
  newColor,
  "The #color-input value should update when the useState state changes"
);
```

When your `#color-input` value is changed, your `#color-picker-container` should change its background color to reflect that value.

```js
  const inputForSure = document.getElementById("color-input");
  assert.exists(inputForSure);
  const nativeValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
  await React.act(async () => {
    nativeValueSetter.call(inputForSure, "#000001");
    inputForSure.dispatchEvent(new Event("input", { bubbles: true}));
  });
  const container = document.getElementById("color-picker-container");
  assert.exists(container);
  const style = window.getComputedStyle(container);
  assert.equal(style?.backgroundColor, "rgb(0, 0, 1)");
```

# --seed--

## --seed-contents--

```html
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>Color Picker</title>
    <link rel="stylesheet" href="styles.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      src="index.jsx"
    ></script>
</head>

<body>
    <div id="root"></div>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
    >
      import { ColorPicker } from './index.jsx';
      ReactDOM.createRoot(document.getElementById('root')).render(<ColorPicker />);
    </script>
</body>

</html>
```

```css
body,
html {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: Arial, sans-serif;
}

#color-picker-container {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    background-color: #ffffff;
}

input[type="color"] {
    position: absolute;
    margin-top: 50px;
    height: 40px;
}
```

```jsx
const { useState } = React;

export const ColorPicker = () => {};
```

# --solutions--

```html
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>Color Picker</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      src="index.jsx"
    ></script>
    <link rel="stylesheet" href="styles.css" />
</head>

<body>
    <div id="root"></div>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
    >
      import { ColorPicker } from './index.jsx';
      ReactDOM.createRoot(document.getElementById('root')).render(<ColorPicker />);
    </script>
</body>

</html>
```

```css
body,
html {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: Arial, sans-serif;
}

#color-picker-container {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    background-color: #ffffff;
}

#pick-color-btn {
    padding: 15px 30px;
    font-size: 18px;
    color: white;
    background-color: #14183c;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-top: 20px;
}

#pick-color-btn:hover {
    background-color: #08131f;
}

input[type="color"] {
    position: absolute;
    margin-top: 50px;
    height: 40px;
}

.stylep{
    color: #14183c;
    font-size: 15px;
    font-weight: bold;
    margin-bottom: 50px;

}
```

```jsx
const { useState } = React;

export const ColorPicker = () => {
    const [bgColor, setBgColor] = useState('#ffffff');

    const handleColorChange = (event) => {
        setBgColor(event.target.value);
    };

    return (
            <div id="color-picker-container" style={{ backgroundColor: bgColor }}>
            <p className="stylep">
                Choose a color using the color input below:
            </p>

            <input
                id="color-input"
                type="color"
                value={bgColor}
                onChange={handleColorChange}
            />
        </div>
    );
}
```
