Coder Social home page Coder Social logo

igeligel / react-in-out-textarea Goto Github PK

View Code? Open in Web Editor NEW
31.0 2.0 22.0 3.02 MB

A simple React.js User Interface Component that is like Google Translate with full TypeScript Support

License: MIT License

JavaScript 2.99% HTML 1.53% TypeScript 95.49%
react google-translate component typescript hacktoberfest ui library frontend textarea converter converter-app storybook yarn hacktoberfest2021

react-in-out-textarea's Introduction

react-in-out-textarea

A simple React.js component that is like Google Translate

Features

react-in-out-textarea is a highly customisable React component, for all of your input and output text needs.

Some of the unique features this component offers include:

  • Textarea fields for input and output
  • Customisable input and output labels
  • Selection of input and output types
  • Dropdown to show all your labels when they won't fit on one line
  • Fully controllable
  • Ability to copy the output text to your clipboard
  • Minimalistic, visually pleasing style
  • Variable content length

Used by

Mentioned In

Installation

Install via NPM
npm install --save react-in-out-textarea
# You might want to install react-tooltip if you activate the max length option
npm install --save react-tooltip
Install via yarn
yarn add react-in-out-textarea
# You might want to install react-tooltip if you activate the max length option
yarn add react-tooltip

Props

Name Type Required Description
inValue string ✔️ The value that is shown on the left-handed side.
outValue string ✔️ The value that is shown on the right-handed side.
inOptions array ✔️ An array of options filled with names marked true or false
onInInput function ✔️ Called to listen to when the text on the left-hand side changes
onInOptionsUpdate function ✔️ Updated with new options as the parameter when inOptions language clicked
outOptions array ✔️ An array of options filled with names marked true or false and an activeClicked boolean
onOutOptionsUpdate function ✔️ Updated with new options as the parameter when outOptions language clicked
maxContentLength number Value that defines the maximum number of characters allowed in the text area.
maxContentLengthIndicator Object An Object describing how the length indicator is shown.
onCopy function A function that is called when you have copied the content of InOutTextarea.
autoCloseMenuOnOptionSelection boolean Boolean that defines whether an option menu should self-close after selection.

Usage

React + TypeScript

CodeSandbox Example

Code Example:

import React, { useState } from 'react';
import { InOutTextarea, InOptions, OutOptions } from 'react-in-out-textarea';

export const ExampleComponent = () => {
  const [inValue, setInValue] = useState<string>('');
  const [outValue, setOutValue] = useState<string>('');
  const [inOptions, setInOptions] = useState<InOptions>([
    {
      name: 'English',
      active: true,
    },
    {
      name: 'German',
      active: false,
    },
  ]);
  const [outOptions, setOutOptions] = useState<OutOptions>([
    {
      name: 'Chinese',
      active: true,
      activeClicked: false,
    },
  ]);

  return (
    <InOutTextarea
      inValue={inValue}
      outValue={outValue}
      onInInput={(newValue) => {
        setInValue(newValue);
        setOutValue(newValue);
      }}
      inOptions={inOptions}
      onInOptionsUpdate={(newInOptions) => {
        setInOptions(newInOptions);
      }}
      outOptions={outOptions}
      onOutOptionsUpdate={(newOutOptions) => {
        setOutOptions(newOutOptions);
      }}
    />
  );
};
React + Javascript

CodeSandbox Example

Code Example:

import React, { useState } from "react";
import { InOutTextarea } from "react-in-out-textarea";

export const ExampleComponent = () => {
  const [inValue, setInValue] = useState("");
  const [outValue, setOutValue] = useState("");
  const [inOptions, setInOptions] = useState([
    {
      name: "English",
      active: true
    },
    {
      name: "German",
      active: false
    }
  ]);
  const [outOptions, setOutOptions] = useState([
    {
      name: "Chinese",
      active: true,
      activeClicked: false
    }
  ]);

  return (
    <InOutTextarea
      inValue={inValue}
      outValue={outValue}
      onInInput={(newValue) => {
        setInValue(newValue);
        setOutValue(newValue);
      }}
      inOptions={inOptions}
      onInOptionsUpdate={(newInOptions) => {
        setInOptions(newInOptions);
      }}
      outOptions={outOptions}
      onOutOptionsUpdate={(newOutOptions) => {
        setOutOptions(newOutOptions);
      }}
    />
  );
};

Development

To start developing you need the following tools installed:

After installing all the tools, you can install all dependencies by using in your terminal

yarn

After that just type:

yarn storybook

And open http://localhost:6006/. That should give you the storybook preview.

Storybook

Storybook is an open source tool for developing UI components in isolation for React, Vue, Angular, and more. It makes building stunning UIs organized and efficient.

Storybook is a tool used here for easy development of components for the web. Since this project uses React.js, the decision for storybook was kind of easy. It makes the development workflow seamless.

Our stories are saved under the ./stories directory. Feel free to have a look.

License

The code is licensed under MIT.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Kevin Peters

💼 💻 🎨 🚇 🚧 💬 👀

Amber

💻

Katie

💻

chorongbali

💻

Santosh Viswanatham

💻 🚇

xen0m29

💻

merelj

💻

Tom Scott

💻 📖

aman601

📖

dasshield

💻

Aashwin Vaish

💻

Thomas Siller

💻

Gabrijel Golubić

📖

Tom Shamp

💻

Bink

💻

Gabriel Paixão

💻

rohitgeddam

🔧 💻

G.H.B.Emalsha Rasad

🔧 📖

Emma Dawson

💻

Sameer Waskar

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

react-in-out-textarea's People

Contributors

allcontributors[bot] avatar aman601 avatar arkeologist avatar av-dx avatar binkpitch avatar deepsource-autofix[bot] avatar deepsourcebot avatar dependabot[bot] avatar devcer avatar emalsha avatar emmadawsondev avatar gabrielfalcom avatar ggolubic avatar hambali999 avatar igeligel avatar katieraby avatar rohitgeddam avatar shew0lf avatar silltho avatar silver292 avatar tshamp7 avatar warp avatar wsameer avatar xen0m29 avatar zorfling avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-in-out-textarea's Issues

Refactoring Root React Fragment

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

Currently, the main component is wrapped in a React fragment. It should not be wrapped.

Code Before

// ...

export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      <ConvertCard>{/* ... */}</ConvertCard>
    </>
  );
};

Code Expected after Refactoring

// ...

export const InOutTextarea: FC<Props> = (props) => {
  return <ConvertCard>{/* ... */}</ConvertCard>;
};

Files involved

  • ./src/index.tsx

Feature: Mobile Design Options Overlay

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

Before:

chrome_2020-10-13_23-22-05

After

chrome_2020-10-13_23-21-53

// src/OptionsOverlay.tsx
// This style has to be extended
const OverlayOption = styled.div`
  box-sizing: border-box;
  font-size: 14px;
  font-family: Roboto;
  line-height: 30px;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 10px;
  display: inline-block;
  min-width: 15%;
  cursor: pointer;

  @media screen and (max-width: 720px) {
    min-width: auto;
    padding-right: 10px;
  }

  :hover {
    border-radius: 3px;
    background-color: #f5f5f5;
  }
`;

Resources

Files involved

Refactoring MoreOptionsIconContainer out onClick Handler

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code
  • Extract Code

Description

No inline function handler for the MoreOptionsIconContainer onClick handler for the outOptions should be used. This issue is just dealing with the out handler.

By not inlining the function it improves performance because the function does not get registered as an anonymous function every time the component is rendered.

Code Before

// ./src/index.tsx
return () => {
  // ...
  return (
    <MoreOptionsIconContainer
      right
      ref={outOptionsMenuRef}
      onClick={() => {
        setShowAdditionalInOptions(false);
        setShowAdditionalOutOptions(!showAdditionalOutOptions);
      }}
    >
      {!showAdditionalOutOptions && <IconChevronDown />}
      {showAdditionalOutOptions && <IconChevronUp />}
    </MoreOptionsIconContainer>
  );
};

Code Expected after Refactoring

// ./src/index.tsx
return () => {
  // ...
  const onOutMoreOptionsClick = () => {
    setShowAdditionalInOptions(false);
    setShowAdditionalOutOptions(!showAdditionalOutOptions);
  };

  // ...
  return (
    <MoreOptionsIconContainer
      right
      ref={outOptionsMenuRef}
      onClick={onOutMoreOptionsClick}
    >
      {!showAdditionalOutOptions && <IconChevronDown />}
      {showAdditionalOutOptions && <IconChevronUp />}
    </MoreOptionsIconContainer>
  );
};

Files involved

  • ./src/index.tsx

Continuous Integration & Continuous Delivery: Workflow check for Pull Requests

Type of Change

  • Integration Pipeline
  • Delivery Pipeline
  • Other:

Description

Create a workflow that looks similar to the main workflow in this repository and checks Pull Requests for validity. A build and tests should get executed.

Code Before

No code regarding Pull Request checks exists :(

Code After

name: CI
on: [pull_request]
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Begin CI...
        uses: actions/checkout@v2

      - name: Use Node 12
        uses: actions/setup-node@v1
        with:
          node-version: 12.x

      - name: Use cached node_modules
        uses: actions/cache@v2
        with:
          path: node_modules
          key: nodeModules-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            nodeModules-
      - name: Install dependencies
        run: yarn install --frozen-lockfile
        env:
          CI: true

      - name: Lint
        run: yarn lint
        env:
          CI: true

      - name: Test
        run: yarn test --ci --coverage --maxWorkers=2
        env:
          CI: true

      - name: Build
        run: yarn build
        env:
          CI: true

This code should exist. It is super similar to what is included in ./.github/workflows/main.yml and should ideally be reused if possible. If not, also not too bad.

Files involved

  • ./.github/workflows/pull-request.yml - does not exist yet

Documentation: Add React + JavaScript Example

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

Create an example of this library being used similar to what is on this codesandbox: https://codesandbox.io/s/react-in-out-textarea-typescript-react-egi57?file=/src/ExampleComponent.tsx

  1. Create another codesandbox on a pure React template
  2. Add react-in-out-textarea as dependency
  3. Integrate it similar to the other example

Create another codesandbox without TypeScript support and add it to the README.

Files involved

  • README.md

Refactoring Unify LeftContent and RightContent

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

Currently, there are two styled-components called LeftContent and RightContent that are basically doing the same. A Pull Request should be created that unifies these two. The background-color for theming can be removed.

Code Before

// index.tsx

// ...

const LeftContent = styled.div`
  flex: 1;
`;

// ...

const RightContent = styled.div`
  flex: 1;
  background-color: ${(props) =>
    props.theme.main === "dark" ? "rgb(24, 37, 66)" : "rgb(249, 250, 250)"};
`;

// ...

export const InOutTextarea: FC<Props> = (props) => {
  // ...
  return (
    <>
      {/* ... */}
      <LeftContent>{/* ... */}</LeftContent>
      <RightContent>{/* ... */}</RightContent>
      {/* ... */}
    </>
  );
};

Code Expected after Refactoring

// Content.ts
export const Content = styled.div`
  flex: 1;
`;

// index
// ...
import { Content } from "./Content";
// ...

export const InOutTextarea: FC<Props> = (props) => {
  // ...
  return (
    <>
      {/* Insted of LeftContent and RightContent */}
      <Content>{/* ... */}</Content>
      <Content>{/* ... */}</Content>
      {/* ... */}
    </>
  );
};

Files involved

Create issue templates

Create Issue Templates for:

  • Feature (feat)
  • Fix (fix)
  • build (Build)
  • chore (Chore)
  • ci (Continous Integration)
  • docs (Documentation)
  • style (Style)
  • refactor (Refactor)
  • perf (Performance)
  • test (Testing)

Documentation: Add installation instructions to README

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

Under the Usage section in the README, an installation instruction should be given. Create a sub heading + a collapsible installation instruction for either yarn and npm, similar to cogo-toast (yarn / npm).

The collapsible area can be done similar to:

<details>
 <summary>npm</summary>

```bash
npm command
\```

</details>

Files involved

Refactoring ConvertCard

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract styled component
  • Remove duplicate code

Description

Currently, ConvertCard is a styled component and should be in its own file.

Code Before

const ConvertCard = styled.div`
  font-family: Roboto, sans-serif;
  min-height: 50px;
  background-color: #white;
  box-shadow: ${props =>
    props.theme.main === 'dark'
      ? '0 1px 4px 0 rgb(41, 57, 93)'
      : '0 1px 4px 0 rgba(0, 0, 0, 0.37)'};
  border-radius: 8px;
  ${props => {
    if (props.theme.main === 'dark') {
      return 'border: 1px solid hsl(221, 25%, 65%)';
    }
    return null;
  }}
`;

Code Expected after Refactoring

export const ConvertCard = styled.div`
  font-family: Roboto, sans-serif;
  min-height: 50px;
  background-color: #white;
  box-shadow: ${props =>
    props.theme.main === 'dark'
      ? '0 1px 4px 0 rgb(41, 57, 93)'
      : '0 1px 4px 0 rgba(0, 0, 0, 0.37)'};
  border-radius: 8px;
  ${props => {
    if (props.theme.main === 'dark') {
      return 'border: 1px solid hsl(221, 25%, 65%)';
    }
    return null;
  }}
`;

This component should then be imported by the main file and used there.

Files involved

  • index.tsx
  • ./src/styled/ConvertCard.ts - This folder/file might not exist and needs to created

Feature: Use Storybook Addon

Type of Feature

  • API Extension
  • UI Feature
  • other: Storybook extension

Currently the code looks like:

const fonts = ['monospace', 'Roboto', 'Arial', 'Comic Sans']
export const CustomFont = (props?: Partial<Props>) => {
  const [font, setFont] = React.useState(fonts[0]);
  return (
    <ThemeProvider theme={{ font }}>
      select font:{' '}
      <select onChange={(v) => setFont(v.target.value)}>
        {fonts.map(f => <option value={f}>{f}</option>)}
      </select>
      <hr/>
      <Default/>
    </ThemeProvider>
  );
}

But instead, an add-on could be used to use storybook as a selector for the font.

How would it look like

First of all the configuration of storybook has to be changed.

// ././storybook/main.js
module.exports = {
  // ...
  addons: [
    // This needs to be added
    "@storybook/addon-controls",
    // ...
  ],
  // ...
};

In the stories we can use the addon then:

// Thing.stories.ts
export default {
  // ...
  argTypes: {
    font: {
      control: {
        type: 'select',
        options: ['monospace', 'Roboto', 'Arial', 'Comic Sans'],
      },
    },
  },
};

// ...
type CustomFontProps = Partial<Props> & { font: string };

const _CustomFont = ({ font, ...args }: CustomFontProps) => {
  return (
    <ThemeProvider theme={{ font: font }}>
      <Default {...args} />
    </ThemeProvider>
  );
};

export const CustomFont = _CustomFont.bind({});

CustomFont.args = { font: 'Roboto' };

Resources

Files involved

Feature: Variable content length

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

Currently, when using the component, the textarea is limited to 100 characters. Make this configurable and unlimited by default.

The following should have unlimited characters.

<InOutTextarea
  inValue={inValue}
  outValue={outValue}
  onInInput={(newValue) => {
    setInValue(newValue);
    setOutValue(newValue);
  }}
  inOptions={inOptions}
  onInOptionsUpdate={(newInOptions) => {
    setInOptions(newInOptions);
  }}
  outOptions={outOptions}
  onOutOptionsUpdate={(newOutOptions) => {
    setOutOptions(newOutOptions);
  }}
/>;

The following should have the left textarea limited to 100 characters:

<InOutTextarea
  inValue={inValue}
  outValue={outValue}
  onInInput={(newValue) => {
    setInValue(newValue);
    setOutValue(newValue);
  }}
  inOptions={inOptions}
  onInOptionsUpdate={(newInOptions) => {
    setInOptions(newInOptions);
  }}
  outOptions={outOptions}
  onOutOptionsUpdate={(newOutOptions) => {
    setOutOptions(newOutOptions);
  }}
  maxContentLength={100}
/>;

These values should set the maxlength property of the left textarea.

Resources

  • -/-

Files involved

Documentation: Create a Props Section in the README

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

The README.md currently has examples, but the props can be explained in the README.md. The section should be shown after the Usage section and should have Props as heading.

The table should look like the following:

Name Type Description
inValue string The value that is shown on the left-handed side.
... ... ...

The table should include all values of the exported interface here.

Files involved

Refactoring Use Storybook addon

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code
  • Storybook Update

Description

Currently, the storybook example includes a static max length for the component. But a storybook add-on can be used to have a variable max content length.

Code Before

// ./stories/Thing.stories.tsx
export const WithLengthLimit = () => {
  const [inValue, setInValue] = useState<string>('Has a limit = to 20!');

  return (
    <div style={{ maxWidth: '1100px' }}>
      <InOutTextarea
        inValue={inValue}
        outValue={inValue.split('').reverse().join('')}
        inOptions={[{ active: true, name: 'English' }]}
        outOptions={[{ active: true, name: 'German', activeClicked: true }]}
        onInInput={setInValue}
        onInOptionsUpdate={() => true}
        onOutOptionsUpdate={() => true}
        maxContentLength={20}
      />
    </div>
  );
};

Code Expected after Refactoring

// ./stories/Thing.stories.tsx
export default {
  title: "Welcome",
  argTypes: {
    font: {
      control: {
        type: "select",
        options: ["monospace", "Roboto", "Arial", "Comic Sans"],
      },
    },
    maxContentLength: {
      control: {
        type: "range",
        options: {
          min: 1,
          max: 100,
          step: 1,
        },
      },
    },
  },
};

// ...

type CustomMaxContentLengthProps = Partial<Props> & {
  maxContentLength: number;
};

const _WithLengthLimit = ({
  maxContentLength,
  ...args
}: CustomMaxContentLengthProps) => {
  const [inValue, setInValue] = useState<string>(
    `Has a limit = to ${maxContentLength}!`
  );

  return (
    <div style={{ maxWidth: "1100px" }}>
      <InOutTextarea
        inValue={inValue}
        outValue={inValue.split("").reverse().join("")}
        inOptions={[{ active: true, name: "English" }]}
        outOptions={[{ active: true, name: "German", activeClicked: true }]}
        onInInput={setInValue}
        onInOptionsUpdate={() => true}
        onOutOptionsUpdate={() => true}
        maxContentLength={maxContentLength}
      />
    </div>
  );
};

export const WithLengthLimit = _WithLengthLimit.bind({});

Files involved

  • ./stories/Thing.stories.tsx

Documentation: Add JSDoc to types.ts

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below: JSDoc documentation is missing.

Description

For better usage of our props we can document them a bit more. This issue is quite easy and just involves documentation but also some understanding of how our components work.

A pull request for this issue should just add JSDoc comments for the src\types.ts file.

To explain from my own words what the things are used for:

  • IInOption: an option that will be shown on the left side of the selector in the component
  • IInOption.name: The name/label to show the option for. Could be "English", "German" or similar in the case of Google Translate
  • IInOption.active: Shows if the current option is active
  • IInOption.key: the key, mostly used because of: https://reactjs.org/docs/lists-and-keys.html
  • InOptions: An array of IInOption
  • IOutOption: The same as IInOption. An option that will be shown on the left side of the selector in the component. You can mention that another parameter was added to the interface.
  • IOutOption.activeClicked: Is a bit different than active because it shows a different color.
  • OutOptions: An array of IOutOption

Please rephrase these sentences so they makes sense. Resources that helped me to understand JSDoc comments:

Files involved

  • src\types.ts

Refactoring ConvertCard file format

Type of Change

  • Name variables, files and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

Rename src/styled/ConvertCard.tsx to src/styled/ConvertCard.ts

Code Before

-/-

Code Expected after Refactoring

-/-

Files involved

  • src/styled/ConvertCard.tsx

Feature: Keys

Type of Feature

  • API Extension
  • UI Feature
  • other:

The in and out options should both have the option to receive a key as a prop.

How would it look like

Give an example how it could look like

const a = "";

Resources

  • List any other resource
  • Resource 1

Files involved

Bug: Too many options should be hidden

Your Environment

  • System: Mac, Windows or Linux
  • Node Version: 10, 12, 14
  • TypeScript Version: 4

Reproduction (required)

When not having overlapped items, do not display the arrow down menu or in the menu give a notice that there are not more items.

CodeSandbox URL (optional): Insert URL if reproduced on CodeSandbox

Files involved (optional)

  • ./src/test1.tsx
  • ./src/test2.tsx

Feature: Custom Font

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

A flag exists that makes it possible to pass a custom font. For example monospace.

import React, { useState } from "react";
import { InOutTextarea, InOptions, OutOptions } from "react-in-out-textarea";
import { ThemeProvider } from "styled-components";

const theme = {
  font: "monospace"
};

export const ExampleComponent = () => {
  const [inValue, setInValue] = useState<string>("");
  const [outValue, setOutValue] = useState<string>("");
  const [inOptions, setInOptions] = useState<InOptions>([
    {
      name: "English",
      active: true
    },
    {
      name: "German",
      active: false
    }
  ]);
  const [outOptions, setOutOptions] = useState<OutOptions>([
    {
      name: "Chinese",
      active: true,
      activeClicked: false
    }
  ]);

  return (
    <ThemeProvider theme={theme}>
      <InOutTextarea
        inValue={inValue}
        outValue={outValue}
        onInInput={(newValue) => {
          setInValue(newValue);
          setOutValue(newValue);
        }}
        inOptions={inOptions}
        onInOptionsUpdate={(newInOptions) => {
          setInOptions(newInOptions);
        }}
        outOptions={outOptions}
        onOutOptionsUpdate={(newOutOptions) => {
          setOutOptions(newOutOptions);
        }}
      />
    </ThemeProvider>
  );
};
  • Check the font={"monospace"} in the props of the component above.
  • A storybook component is created for this case
  • Another example in codesandbox will be created

Resources

-/-

Files involved

  • ./src/index.ts
  • This can be implemented with the Theme functionality. Documentation can be found here.

Documentation: Update README

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

README Update

Description

The README should include a features section similar to the one in ag-grid.

Include features like:

  • Selection of input and output type
  • Textarea for input and output
  • Fully controllable
  • Additional like styling and so on

Files involved

Refactoring CaseBar

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React/JavaScript/TypeScript component
  • Remove duplicate code

Description

Refactor the CaseBar into an own file called CaseBar.ts.

Code Before

const CaseBar = styled.div`
  border-bottom: ${props =>
    props.theme.main === 'dark'
      ? '1px solid rgba(229, 229, 229, 0.2)'
      : '1px solid rgba(20, 33, 61, 0.2)'};
  display: flex;
  @media (max-width: 576px) {
    flex-direction: column;
  }
`;

Code Expected after Refactoring

export const CaseBar = styled.div`
  border-bottom: ${props =>
    props.theme.main === 'dark'
      ? '1px solid rgba(229, 229, 229, 0.2)'
      : '1px solid rgba(20, 33, 61, 0.2)'};
  display: flex;
  @media (max-width: 576px) {
    flex-direction: column;
  }
`;

Files involved

  • ./src/index.tsx
  • ./src/CaseBar.ts (need to be created)

Documentation: Add documentation for onCopy parameter

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

The onCopy method you can pass to the component is not documented and should be documented in the README.md. It is an optional field and is simply a function you can pass to the component similar to:

import { InOutTextarea } from 'react-in-out-textarea'

import { InOutTextarea } from "react-in-out-textarea";

export const LoremIpsum = () => {
  return (
    <InOutTextarea
      // wadwadwad
      onCopy={() => {
        alert("You have copied something");
      }}
    />
  );
};

The ticket expects that this table is extended:

chrome_GrGbQWBvFC

Files involved

  • README.md

Documentation: maxContentLength

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

In #45 the feature for variable content length was merged but was not documented. Let us document that.

Add it to the props section in the README.md (link). Also, add another column to the table that is called required and has the values ✔️ for everything except maxContentLength, that is added, and should have the value ❌ since it is not required.

Also, under the Feature section the Variable content length should be shown as fully ready now.

Files involved

  • README.md

Refactoring MoreOptionsIconContainer in onClick Handler

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code
  • Extract Code

Description

No inline function handler for the MoreOptionsIconContainer onClick handler for the inOptions should be used. This issue is just dealing with the in handler.

By not inlining the function it improves performance because the function does not get registered as anonymous function every time the component is rendered.

Code Before

// ./src/index.tsx
return () => {
  // ...
  return (
    <MoreOptionsIconContainer
      ref={inOptionsMenuRef}
      onClick={() => {
        setShowAdditionalOutOptions(false);
        setShowAdditionalInOptions(!showAdditionalInOptions);
      }}
    >
      {!showAdditionalInOptions && <IconChevronDown />}
      {showAdditionalInOptions && <IconChevronUp />}
    </MoreOptionsIconContainer>
  );
};

Code Expected after Refactoring

// ./src/index.tsx
return () => {
  // ...
  const onInMoreOptionsClick = useCallback(() => {    
    setShowAdditionalOutOptions(false);
    setShowAdditionalInOptions(!showAdditionalInOptions);
  }, [showAdditionalInOptions]);

  // ...
  return (
    <MoreOptionsIconContainer
      ref={inOptionsMenuRef}
      onClick={onInMoreOptionsClick}
    >
      {!showAdditionalInOptions && <IconChevronDown />}
      {showAdditionalInOptions && <IconChevronUp />}
    </MoreOptionsIconContainer>
  );
};

Files involved

  • ./src/index.tsx

Documentation: Create contributing.md

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

Create a contributing.md file to show new contributors how to contribute. This file should be similar to the SendGrid one.

  • Mention the linting setup that was mentioned in the Pull Request here.

Files involved

Create a file.

  • contribute.md

Feature: Mobile Textareas

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

The current state looks like this:

chrome_2020-10-13_22-41-21

The wanted state is something like this:

chrome_2020-10-13_22-43-30

For this, you need to change the flex-direction from flex-direction: row; of ConvertCardContent to flex-direction: column when the content goes into a mobile layout. Mobile Layout here means below 720px. Please use media-queries to achieve this.

Otherwise the output/translated content wrapper (TextAreaContent) should have a background color of light gray (background-color: hsl(0 0% 98% / 1);).

// src/TextAreaContent.tsx
import styled from "styled-components";

export const TextAreaContent = styled.div`
  flex: 1;
  padding-left: 28px;
  padding-top: 20px;
  padding-bottom: 42px;
  padding-right: 14px;
  width: 100%;
  box-sizing: border-box;
  display: flex;

  @media (max-width: 720px) {
    background-color: hsl(0 0% 98% / 1);
  }
`;

```tsx
// src/index.tsx
const ConvertCardContent = styled.div`
  width: 100%;
  display: flex;
  position: relative;

  @media (max-width: 720px) {
    flex-direction: column;
  }
`;

export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      {/* ... */}
      <ConvertCardContent ref={convertCardRef}>
        {/* ... */}
        <TextAreaContent>{/* ... */}</TextAreaContent>
        <TextAreaContent>
          {/* ... */}
        </TextAreaContent>
      </ConvertCardContent>
    </>
  );
};

Resources

Files involved

Refactoring Textarea styled component

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

The <Textarea> component should live in their own file.

Code Before

./index.tsx
const Textarea = styled(TextareaAutosize)<ExampleTextProps>`
  // ...
`;

Code Expected after Refactoring

./styled/textarea.ts
type ExampleTextProps = {
  // ...
};

export const Textarea = styled(TextareaAutosize)<ExampleTextProps>`
  // ...
`;
./index.tsx
import { Textarea } from './styled/Textarea';

// Same usage in React code

Files involved

  • src\index.tsx
  • and you need to create a new file

Refactoring Default textarea size

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

Currently, the left textarea has rows set to 2. This is done so it looks nice on desktop but because we are moving to mobile this behavior should change a bit. See how the size of the red arrows is different in the picture below.

chrome_2020-10-13_23-07-05

The problem with the screenshot above is that the lower box would be 1 row high when the upper one would be 2 rows high. For desktop, the minimum row should be 2 though. Otherwise, that looks weird.

After a bit of investigating I could not find a CSS-Native solution with the rows attribute of <textarea>, so we are forced to use min-height and media queries.

Code Before

const Textarea = styled(TextareaAutosize)<ExampleTextProps>`
  box-sizing: border-box;
  border: 0;
  resize: none;
  flex-grow: 1;
  color: ${(props) => (props.theme.main === "dark" ? "#fff" : "#14213d")};
  background-color: transparent;
  font-family: ${(props) =>
    props.theme && props.theme.font ? props.theme.font : "Roboto"};
  font-size: ${(props) => (props.smallerFont ? "1.2em" : "1.61em")};
  ${(props) => (props.showCopyCursor ? "cursor: text;" : "")};
  width: 100%;

  ::placeholder {
    color: ${(props) =>
      props.theme.main === "dark"
        ? "hsl(221, 51%, 64%)"
        : "rgba(20, 33, 61, 0.4)"};
  }

  :focus {
    outline: none;
  }
`;

// ...

export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      {/* ... */}
      <TextAreaContent>
        <TextAreaWrapper>
          <Textarea
            data-test="from-textarea"
            placeholder="..."
            rows={2}
            smallerFont={false}
            value={inValue}
            maxLength={maxContentLength}
            onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
              if (
                event.target.value === null ||
                event.target.value === undefined
              )
                return;
              onInInput(event.target.value);
            }}
          />
        </TextAreaWrapper>
        {/* ... */}
      </TextAreaContent>
      <TextAreaContent>
        <TextAreaWrapper>
          <Textarea
            disabled
            smallerFont={false}
            showCopyCursor={true}
            value={outValue}
          />
        </TextAreaWrapper>
        {/* ... */}
      </TextAreaContent>
    </>
  );
};

Code Expected after Refactoring

const Textarea = styled(TextareaAutosize)<ExampleTextProps>`
  box-sizing: border-box;
  border: 0;
  resize: none;
  flex-grow: 1;
  color: ${(props) => (props.theme.main === "dark" ? "#fff" : "#14213d")};
  background-color: transparent;
  font-family: ${(props) =>
    props.theme && props.theme.font ? props.theme.font : "Roboto"};
  font-size: ${(props) => (props.smallerFont ? "1.2em" : "1.61em")};
  ${(props) => (props.showCopyCursor ? "cursor: text;" : "")};
  width: 100%;
  min-height: 64px;

  @media (max-width: 720px) {
    min-height: auto;
  }

  ::placeholder {
    color: ${(props) =>
      props.theme.main === "dark"
        ? "hsl(221, 51%, 64%)"
        : "rgba(20, 33, 61, 0.4)"};
  }

  :focus {
    outline: none;
  }
`;

// ...

export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      {/* ... */}
      <TextAreaContent>
        <TextAreaWrapper>
          <Textarea
            data-test="from-textarea"
            placeholder="..."
            smallerFont={false}
            value={inValue}
            maxLength={maxContentLength}
            onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
              if (
                event.target.value === null ||
                event.target.value === undefined
              )
                return;
              onInInput(event.target.value);
            }}
          />
        </TextAreaWrapper>
        {/* ... */}
      </TextAreaContent>
      <TextAreaContent>
        <TextAreaWrapper>
          <Textarea
            disabled
            smallerFont={false}
            showCopyCursor={true}
            value={outValue}
          />
        </TextAreaWrapper>
        {/* ... */}
      </TextAreaContent>
    </>
  );
};

Files involved

Refactoring MidCaseBar

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code
  • Other

Description

Currently MidCaseBar is used in ./src/index.tsx but actually a <Spacer /> component should exist to handle that.

Code Before

// ...
const MidCaseBar = styled.div``;
// ...

export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      {/* ... */}
      <LeftCaseBar>{/* ... */}</LeftCaseBar>
      <MidCaseBar>
        <div style={{ width: "40px" }}>{/* <IconRefreshCw /> */}</div>
      </MidCaseBar>
      <RightCaseBar>{/* ... */}</RightCaseBar>
      {/* ... */}
    </>
  );
};

Code Expected after Refactoring

// ...
import { Spacer } from "./Spacer";

export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      {/* ... */}
      <LeftCaseBar>{/* ... */}</LeftCaseBar>
      <Spacer vertical />
      <RightCaseBar>{/* ... */}</RightCaseBar>
      {/* ... */}
    </>
  );
};

Files involved

  • ./src/index.tsx
  • ./src/Spacer.tsx - needs to be created

Documentation: Add contributors section

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below:

Description

It is unclear for new contributors to add them as contributors to the README. Explain how all-contributors bot works. Add a section in the README.md that it includes the Contribute heading and a description.

The description should look like:

After the merge, add a comment:

@all-contributors please add @yourGitHubUsername for code, business, and infra

The tags that are comma-separated can be found here. Use emoji/type shortcut.

Files involved

Feature: Mobile Design Setup

Type of Feature

  • API Extension
  • UI Feature
  • other

Add story on storybook for mobile support

How would it look like

chrome_2020-10-13_22-33-24

Use the Storybook Viewport plugin: https://storybook.js.org/docs/react/essentials/viewport. The maxWidth example below is suboptimal.

export const Mobile = (props?: Partial<Props>) => {
  const [inValue, setInValue] = useState<string>("Hello");
  const [inOptions, setInOptions] = useState<InOptions>([
    {
      name: "English",
      active: false,
    },
    // Add more options
  ]);

  const [outOptions, setOutOptions] = useState<OutOptions>([
    {
      name: "English",
      active: true,
      activeClicked: false,
    },
    // Add more options
  ]);

  return (
    // This might change depending if you want to use the storybook plugin
    <div style={{ maxWidth: "350px" }}>
      <InOutTextarea
        {...props}
        inValue={inValue}
        onInInput={(newValue) => setInValue(newValue)}
        inOptions={inOptions}
        onInOptionsUpdate={(newInOptions) => {
          setInOptions(newInOptions);
        }}
        outOptions={outOptions}
        onOutOptionsUpdate={(newOutOptions) => {
          setOutOptions(newOutOptions);
        }}
        outValue={"Hello"}
      />
    </div>
  );
};

Resources

Files involved

Refactoring <Content><LeftContentContent><TextareaContainer> structure

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

Currently, we have a styled component section that could be refactored quite easily into one styled-component. These sections consist of three components:

  • <Content>
  • <LeftContentContent>
  • <TextareaContainer>

These should be ideally refactored to one styled-component.

Code Before

// index.tsx
export default () => {
  return (
    <>
      {/* ... */}
      <Content>
        <LeftContentContent>
          <TextareaContainer>
            <Textarea
              disabled
              smallerFont={false}
              showCopyCursor={true}
              value={outValue}
            />
            <CopyToClipboard text={outValue} onCopy={() => {}}>
              <IconContainer>
                <IconCopy size={24} />
              </IconContainer>
            </CopyToClipboard>
          </TextareaContainer>
        </LeftContentContent>
      </Content>
      {/* ... */}
    </>
  );
};

Code Expected after Refactoring

// ./src/TextareaContent.ts
import styled from "styled-components";

export const TextareaContent = styled.div`
  flex: 1;
  padding-left: 28px;
  padding-top: 20px;
  padding-bottom: 42px;
  padding-right: 14px;
  width: 100%;
  box-sizing: border-box;
  display: flex;
`;

And the change should be used in two places of the main component.

// ./src/index.tsx
export default () => {
  return (
    <>
      {/* ... */}
      <TextareaContent>
        <Textarea
          disabled
          smallerFont={false}
          showCopyCursor={true}
          value={outValue}
        />
        <CopyToClipboard text={outValue} onCopy={() => {}}>
          <IconContainer>
            <IconCopy size={24} />
          </IconContainer>
        </CopyToClipboard>
      </TextareaContent>
      {/* ... */}
    </>
  );
};

The leftover <Content>, <LeftContentContent>, <TextareaContainer> should be removed.

Files involved

  • ./src/index.tsx
  • ./src/TextareaContent.ts

Feature: Auto Close Menu

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

When selecting an input or output option the menu should self-close by default.

Alternatively, an option can be passed to the component that enables or disables this option. This option should be called autoCloseMenuOnOptionSelection.

Resources

  • -/-

Files involved

  • N/A

Refactoring LeftCaseBar & RightCaseBar

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

Currently, in the code there is a LeftCaseBar and RightCaseBar. These should be unified to a standalone styled-component called CaseBar. Actually the code is not so different. Just including a justify-content: space-between; and a media-query that can be removed.

Code Before

const LeftCaseBar = styled.div`
  flex: 1;
  display: flex;
  color: #14213d;
  justify-content: space-between;
  overflow: hidden;
  position: relative;
`;

// ...

const RightCaseBar = styled.div`
  flex: 1;
  display: flex;
  color: #14213d;
  overflow: hidden;
  position: relative;
  @media (max-width: 576px) {
    flex-direction: column;
  }
`;

export const InOutTextarea: FC<Props> = (props) => {
  // ...
  return (
    <>
      {/* ... */}
      <LeftCaseBar>{/* ... */}</LeftCaseBar>
      <RightCaseBar>{/* ... */}</RightCaseBar>
      {/* ... */}
    </>
  );
};

Code Expected after Refactoring

// SideBar.ts
const SideBar = styled.div`
  flex: 1;
  display: flex;
  color: #14213d;
  overflow: hidden;
  position: relative;
`;

// index.ts
import { SideBar } from "./SideBar";

export const InOutTextarea: FC<Props> = (props) => {
  // ...
  return (
    <>
      {/* ... */}
      <SideBar>{/* ... */}</SideBar>
      <SideBar>{/* ... */}</SideBar>
      {/* ... */}
    </>
  );
};

Files involved

  • ./src/SideBar.ts
  • ./src/index.tsx

Feature: Let users adjust copy click

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

A user can provide an option to the component to extend the behavior of copy functionality, but also completely replace it.

const a = "";

Resources

  • List any other resource
  • Resource 1

Files involved

Feature: Hover and Tooltip for length indicator

Type of Feature

  • API Extension
  • UI Feature
  • other:

How would it look like

Just show the current length and the maximum length below the left input textarea.

Resources

  • N/A

Files involved

Many

Refactoring OptionsOverlay

Type of Change

  • Name variables and functions well
  • Remove magic numbers
  • Extract each step of logic into a function
  • Extract React component
  • Remove duplicate code

Description

The OptionsOverlay and the children components should be refactored into an own component called OptionsOverlay.tsx.

Code Before

// src/index.tsx
const OptionsOverlay = styled.div<OptionsOverlay>`
  position: absolute;
  width: 100%;
  min-height: ${(props) => props.minHeight || "initial"};
  max-height: ${(props) => props.maxHeight || "initial"};
  background-color: white;
  opacity: 0.99;
  box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.05);
  border-bottom-right-radius: 8px;
  border-bottom-left-radius: 8px;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: flex-start;
  padding-left: 10px;
  padding-right: 20px;
  box-sizing: border-box;
  padding-top: 8px;
  padding-bottom: 8px;
`;

// ...
export const InOutTextarea: FC<Props> = (props) => {
  return (
    <>
      {/* */}
      {showAdditionalOutOptions && (
        <OptionsOverlay
          minHeight={`${convertCardSizes.height}px`}
          maxHeight={`${convertCardSizes.height}px`}
        >
          {menuOutOptions.map((option) => {
            return (
              <OverlayOption
                onClick={() => {
                  const updatedOptions = [
                    ...outOptions.map((outOption) => ({
                      ...outOption,
                      active: outOption.name === option.name,
                    })),
                  ];
                  onOutOptionsUpdate(updatedOptions);
                }}
              >
                {option.name}
              </OverlayOption>
            );
          })}
        </OptionsOverlay>
      )}
      {/* */}
      {showAdditionalInOptions && (
        <OptionsOverlay
          minHeight={`${convertCardSizes.height}px`}
          maxHeight={`${convertCardSizes.height}px`}
        >
          {menuOptions.map((option) => {
            return (
              <OverlayOption
                onClick={() => {
                  const updatedOptions = [
                    ...inOptions.map((inOption) => ({
                      ...inOption,
                      active: inOption.name === option.name,
                    })),
                  ];
                  onInOptionsUpdate(updatedOptions);
                }}
              >
                {option.name}
              </OverlayOption>
            );
          })}
        </OptionsOverlay>
      )}
      {/* */}
    </>
  );
};

Code Expected after Refactoring

// ./src/OptionsOverlay.tsx
const Container = styled.div<OptionsOverlay>`
  position: absolute;
  width: 100%;
  min-height: ${(props) => props.minHeight || "initial"};
  max-height: ${(props) => props.maxHeight || "initial"};
  background-color: white;
  opacity: 0.99;
  box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.05);
  border-bottom-right-radius: 8px;
  border-bottom-left-radius: 8px;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: flex-start;
  padding-left: 10px;
  padding-right: 20px;
  box-sizing: border-box;
  padding-top: 8px;
  padding-bottom: 8px;
`;

export const OptionsOverlay = (props) => {
  const {
    convertCardSizes,
    shownMenuOptions,
    allMenuOptions,
    onAllMenuOptionsUpdate,
  } = props;
  const { convertCardSizes, menuOptions, inOptions, onInOptionsUpdate } = props;
  return (
    <Container
      minHeight={`${convertCardSizes.height}px`}
      maxHeight={`${convertCardSizes.height}px`}
    >
      {shownMenuOptions.map((option) => {
        return (
          <OverlayOption
            onClick={() => {
              const updatedOptions = [
                ...allMenuOptions.map((outOption) => ({
                  ...outOption,
                  active: outOption.name === option.name,
                })),
              ];
              onAllMenuOptionsUpdate(updatedOptions);
            }}
          >
            {option.name}
          </OverlayOption>
        );
      })}
    </Container>
  );
};

Then use the component inside the ./src/index.tsx component

Files involved

  • ./src/index.tsx
  • ./src/OptionsOverlay.tsx (needs to be created)

Documentation: Add "Mentioned In" section

What should be changed?

  • An example is missing
  • Existing documentation needs to be extended
  • Something else, state below: The README.md is extended

Description

I wrote a blog article about this component that can be listed as material in the README. Create a new section in the README called "Mentioned in". It should be listed below "Used by" in the README and include a list. The first and only item should have the title of the blog article that I wrote and should link it.

Files involved

  • README.md

Bug: Set Textarea to 100%

Your Environment

  • System: All
  • Node Version: 12
  • TypeScript Version: 4

Reproduction (required)

Technical Bug regarding the Textarea.

Try setting the width of the Textarea to 100%.

This should be extended in the ./src/index.tsx:

const Textarea = styled(TextareaAutosize)<ExampleTextProps>`
  // ...
  width: 100%; // needs to be added
`;

1. Just start the project

CodeSandbox URL (optional): -/-

## Files involved (optional)

- `./src/index.tsx`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.