Skip to content

Commit

Permalink
feat(textarea): first implementation the textarea component (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
derek-heycar authored Oct 19, 2022
1 parent ea15b04 commit 9ad5d31
Show file tree
Hide file tree
Showing 30 changed files with 2,236 additions and 0 deletions.
14 changes: 14 additions & 0 deletions packages/form-control/src/styles/default.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,21 @@
/* Sizes */
--form-control-min-height: 48px;
--from-control-legend-height: 11px;
--form-control-input-padding: 0;
--form-control-hint-fint-size: 10px;
}

.component {
font-family: var(--font-family-system);
width: max-content;
color: var(--form-control-icon-color);

&:after {
content: '';
display: block;
clear: both;
}

& .inner {
min-height: var(--form-control-min-height);
}
Expand Down Expand Up @@ -154,6 +162,8 @@
display: flex;
align-items: center;
position: relative;
box-sizing: border-box;
padding: var(--form-control-input-padding);
}

/*
Expand All @@ -173,6 +183,8 @@

@mixin typography-subheading-4;

line-height: 23px;

& .labelInner {
width: 100%;

Expand Down Expand Up @@ -226,6 +238,8 @@
padding-left: var(--gap-m);

@mixin typography-caption-5;

font-size: var(--form-control-hint-fint-size);
}

/*
Expand Down
4 changes: 4 additions & 0 deletions packages/textarea/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
30 changes: 30 additions & 0 deletions packages/textarea/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# HeyCar-UIKit - Textarea

[![Tests](https://github.com/hey-car/heycar-uikit/actions/workflows/build.yml/badge.svg)](https://github.com/hey-car/heycar-uikit/actions/workflows/build.yml)
[![Coverage Status](https://coveralls.io/repos/github/hey-car/heycar-uikit/badge.svg)](https://coveralls.io/github/hey-car/heycar-uikit)
[![Demo build](https://github.com/hey-car/heycar-uikit/actions/workflows/main.yml/badge.svg)](https://github.com/hey-car/heycar-uikit/actions/workflows/main.yml)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)

The Button component is used to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation.

## Installation

To install and save in your package.json dependencies, run the command below using npm:

```bash
npm install @heycar-uikit/textarea
```

## Usage

```tsx
import Textarea from '@heycar-uikit/textarea';

function App() {
return <Textarea value="text" />;
}
```

## Documentation and sandbox

[Storybook](https://hey-car.github.io/heycar-uikit/main/?path=/docs/components-textarea--textarea) documentation and sandbox
38 changes: 38 additions & 0 deletions packages/textarea/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@heycar-uikit/textarea",
"version": "0.0.1",
"description": "HeyCar-UIKit Textarea",
"main": "dist/index.js",
"module": "./dist/esm/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"ui",
"uikit",
"react",
"components",
"heycar",
"typescript",
"ui-components",
"design-systems",
"textarea"
],
"repository": {
"type": "git",
"url": "git+https://github.com/hey-car/heycar-uikit.git"
},
"homepage": "https://github.com/hey-car/heycar-uikit/tree/main/packages/textarea#readme",
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"react": "^17.0.1"
},
"dependencies": {
"@heycar-uikit/form-control": "^1.0.0",
"classnames": "^2.3.1"
},
"author": "HeyCar Team",
"license": "UNLICENSED"
}
106 changes: 106 additions & 0 deletions packages/textarea/src/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { ChangeEvent, FocusEvent, useCallback, useState } from 'react';
import cn from 'classnames';

import FormControl from '@heycar-uikit/form-control';

import TextareaCounter from './components/TextareaCounter';
import { TextareaProps } from './Textarea.types';

import styles from './styles/default.module.css';

const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
(
{
value,
defaultValue,
hint,
error,
label,
maxLength,
fullWidth = false,
resize = 'none',
disabled,
readOnly,
onFocus,
onBlur,
onChange,
className,
dataTestId,
...restProps
},
ref,
) => {
const textareaClassNames = cn(styles.textarea, className, {
[styles.resizeVertical]: resize === 'vertical',
});
const isUncontrolled = value === undefined;
const ariaLabel = typeof label === 'string' ? label : undefined;
const [isFocused, setFocused] = useState(restProps.autoFocus);
const [stateValue, setStateValue] = useState(defaultValue || '');
const isFilled = Boolean(isUncontrolled ? stateValue : value);
const handleTextareaFocus = useCallback(
(event: FocusEvent<HTMLTextAreaElement>) => {
if (!readOnly) setFocused(true);
if (onFocus) onFocus(event);
},
[onFocus, readOnly],
);
const handleTextareaBlur = useCallback(
(event: FocusEvent<HTMLTextAreaElement>) => {
setFocused(false);

if (onBlur) onBlur(event);
},
[onBlur],
);
const handleTextareaChange = useCallback(
(event: ChangeEvent<HTMLTextAreaElement>) => {
if (onChange) onChange(event, { value: event.target.value });
if (isUncontrolled) setStateValue(event.target.value);
},
[onChange, isUncontrolled],
);
const getValueLength = (): number => {
if (isUncontrolled) return stateValue.length;

return value.length;
};

return (
<FormControl
bottomAddons={
!!maxLength && (
<TextareaCounter length={getValueLength()} maxLength={maxLength} />
)
}
className={styles.formControl}
disabled={disabled}
error={error}
filled={isFilled || isFocused}
focused={isFocused}
fullWidth={fullWidth}
hint={hint}
label={label}
>
<textarea
{...restProps}
aria-label={ariaLabel}
className={textareaClassNames}
data-test-id={dataTestId}
disabled={disabled}
maxLength={maxLength}
onBlur={handleTextareaBlur}
onChange={handleTextareaChange}
onFocus={handleTextareaFocus}
readOnly={readOnly}
ref={ref}
value={value}
/>
</FormControl>
);
},
);

Textarea.displayName = 'Textarea';

export default Textarea;
50 changes: 50 additions & 0 deletions packages/textarea/src/Textarea.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { ReactNode, TextareaHTMLAttributes } from 'react';

export type TextareaProps = Omit<
TextareaHTMLAttributes<HTMLTextAreaElement>,
'style' | 'value' | 'defaultValue' | 'onChange'
> & {
/**
* The value of the `input` element, required for a controlled component
*/
value?: string;
/**
* The default value. Use when the component is not controlled
*/
defaultValue?: string;
/**
* If `true`, the `input` will take up the full width of its container
*/
fullWidth?: boolean;
/**
* The hint for the error state
*/
error?: ReactNode | boolean;
/**
* The short `hint` displayed under the input
*/
hint?: ReactNode;
/**
* The label of the input component
*/
label?: React.ReactNode;
/**
* Controlling the ability to resize a component
*/
resize?: 'vertical' | 'none';
/**
* Additional `class` names to be added
*/
className?: string;
/**
* Callback fired when the value is changed
*/
onChange?: (
event: React.ChangeEvent<HTMLTextAreaElement>,
payload: { value: string },
) => void;
/**
* The id for testing
*/
dataTestId?: string;
};
Loading

1 comment on commit 9ad5d31

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 99.79% 946/948
🟢 Branches 92.73% 153/165
🟢 Functions 100% 50/50
🟢 Lines 100% 871/871

Test suite run success

228 tests passing in 32 suites.

Report generated by 🧪jest coverage report action from 9ad5d31

Please sign in to comment.