title: React.js & styled-components - Styled Input with (the illusion of ) Element inside it
body: <p>so what i'm trying to do is to create an styled input that seem to have a fixed text (div / children / etc...) inside it.</p>
  <p>one image can be self explenatory so this is how it looks like right now:</p>
  <p><a href="https://i.stack.imgur.com/wcF1H.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wcF1H.png" alt="what i did so far" /></a></p>
  <p>it seems simple, and the basic idea i quite is:
  i got some Wrapper component that has 2 children - the input itself &amp; some element.
  like so:</p>
  <pre><code>const Input = (props: InputProps) =&gt; {
    return (
      &lt;Wrapper&gt;
        &lt;InputStyled {...props} /&gt;
        &lt;InnerElement&gt;cm&lt;/InnerElement&gt;
      &lt;/Wrapper&gt;
    );
  };
  
  export default Input;
  </code></pre>
  <p>So where is the problem?
  The problem is when i'm trying to set <strong>width</strong> to this component.
  It destroys everything.</p>
  <p>is looks like so:
  <a href="https://i.stack.imgur.com/wUjGU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wUjGU.png" alt="everything messed up" /></a></p>
  <p>so the wrapper should get a <strong>width</strong> prop and keep the input and the text element inside of it.
  here is a codesandbox i created:
  <a href="https://codesandbox.io/s/reactjs-input-with-element-inside-forked-2kr6s?file=/src/App.tsx:0-1795" rel="nofollow noreferrer">https://codesandbox.io/s/reactjs-input-with-element-inside-forked-2kr6s?file=/src/App.tsx:0-1795</a></p>
  <p>it'll be nice if someone understand what i'm doing wrong.</p>
  <p>here are some files:</p>
  <p><strong>Input.tsx</strong></p>
  <pre><code>import React, { InputHTMLAttributes, CSSProperties } from &quot;react&quot;;
  import styled from &quot;styled-components&quot;;
  
  export interface InputProps extends InputHTMLAttributes&lt;HTMLInputElement&gt; {
    style?: CSSProperties;
    label?: string;
    value: string | number;
    onChange: (e: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; void;
    text?: string;
    isDisabled?: boolean;
    hasError?: boolean;
    errorLabel?: string | Function;
    placeholder?: string;
    width?: string;
  }
  
  const defaultProps: InputProps = {
    text: &quot;&quot;,
    onChange: () =&gt; null,
    value: &quot;&quot;
  };
  
  const Wrapper = styled.div&lt;Partial&lt;InputProps&gt;&gt;`
    outline: 1px dashed red;
    box-sizing: border-box;
    justify-self: flex-start; // This is what prevent the child item strech inside grid column
    border: 2px solid lightblue;
    background: lightblue;
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    width: ${({ width }) =&gt; width};
  `;
  
  const InputStyled = styled.input&lt;Partial&lt;InputProps&gt;&gt;`
    box-sizing: border-box;
    flex: 1;
    outline: 1px dashed blue;
    padding: 8px;
    border: none;
    border-radius: 8px;
    max-width: 100%;
  
    :focus {
      outline: none;
    }
  `;
  
  const InnerElement = styled.div`
    outline: 1px dashed green;
    box-sizing: border-box;
    ${({ children }) =&gt;
      children &amp;&amp;
      `
      padding: 0 8px;
      font-size: 13px;
    `};
  `;
  
  const Input = (props: InputProps) =&gt; {
    return (
      &lt;Wrapper width={props.width}&gt;
        &lt;InputStyled {...props} /&gt;
        &lt;InnerElement&gt;{props.text}&lt;/InnerElement&gt;
      &lt;/Wrapper&gt;
    );
  };
  
  Input.defaultProps = defaultProps;
  
  export default Input;
  
  
  </code></pre>
  <p><strong>App.tsx</strong></p>
  <pre><code>import * as React from &quot;react&quot;;
  import &quot;./styles.css&quot;;
  import Input from &quot;./Input&quot;;
  import styled from &quot;styled-components&quot;;
  
  const ContainerGrid = styled.div`
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-gap: 50px;
  `;
  
  export default function App() {
    const [value, setValue] = React.useState(&quot;&quot;);
  
    const handleChange = (e: any) =&gt; {
      setValue(e.target.value);
    };
  
    const renderInputWithElement = () =&gt; {
      return (
        &lt;ContainerGrid&gt;
          &lt;Input
            placeholder=&quot;input with element inside&quot;
            value={value}
            onChange={handleChange}
            width={&quot;60px&quot;} // Play with this
            text=&quot;inch&quot;
          /&gt;
          &lt;Input
            placeholder=&quot;input with element inside&quot;
            value={value}
            onChange={handleChange}
            width={&quot;110px&quot;} // Play with this
            text=&quot;cm&quot;
          /&gt;
          &lt;Input
            placeholder=&quot;input with element inside&quot;
            value={value}
            onChange={handleChange}
            width={&quot;200px&quot;} // Play with this
            text=&quot;mm&quot;
          /&gt;
          &lt;Input
            placeholder=&quot;input with element inside&quot;
            value={value}
            onChange={handleChange}
            width={&quot;100%&quot;} // Play with this
            text=&quot;El&quot;
          /&gt;
          &lt;Input
            placeholder=&quot;input with element inside&quot;
            value={value}
            onChange={handleChange}
            width={&quot;100%&quot;} // Play with this
          /&gt;
        &lt;/ContainerGrid&gt;
      );
    };
  
    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;h1&gt;StyledCode&lt;/h1&gt;
        &lt;h3&gt;Input with an element inside&lt;/h3&gt;
        &lt;p&gt;
          This is kind of an illusion since input cannot have child element inside
          of it really.
        &lt;/p&gt;
        &lt;hr style={{ marginBottom: &quot;32px&quot; }} /&gt;
        {renderInputWithElement()}
      &lt;/div&gt;
    );
  }
  
  
  </code></pre>