Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions components/input/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src
rollup.config.js
tsconfig.json
tsconfig.build.json
55 changes: 55 additions & 0 deletions components/input/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# `@byndyusoft-ui/input`

The `input` component is a React component designed to provide a flexible and customizable input field for your applications.

## Installation

```sh
npm i @byndyusoft-ui/input
# or
yarn add @byndyusoft-ui/input
```

### Customization with CSS Variables

You can customize the appearance of the input component by overriding the following CSS variables:

```css
:root {
--input-height-s: 1.5rem;
--input-height-m: 2rem;
--input-height-l: 2.5rem;
--input-height-xl: 3rem;

--input-font-size-s: 0.75rem;
--input-font-size-m: 0.875rem;
--input-font-size-l: 1rem;
--input-font-size-xl: 1.25rem;

--input-border-radius: 0.375rem;
--input-padding-x: 0.5rem;
--input-transition: box-shadow ease 200ms, border ease 200ms;
--input-disabled-opacity: 0.5;
--input-container-gap: 0.25rem;

--input-main-color: #343434;
--input-focus-color: #000000;
--input-invalid-color: #ff0000;

--input-line-border: 1px solid var(--input-main-color);
--input-line-focus-border: 1px solid var(--input-focus-color);
--input-line-focus-box-shadow: 0 -1px 0 0 var(--input-focus-color) inset;
--input-invalid-line-border: 1px solid var(--input-invalid-color);
--input-invalid-line-box-shadow: 0 -1px 0 0 var(--input-invalid-color) inset;

--input-outline-border: 1px solid var(--input-main-color);
--input-outline-focus-border: 1px solid var(--input-focus-color);
--input-outline-focus-box-shadow: 0 0 0 1px var(--input-focus-color) inset;
--input-invalid-outline-border: 1px solid var(--input-invalid-color);
--input-invalid-outline-box-shadow: 0 0 0 1px var(--input-invalid-color) inset;
}
```


## License
This project is licensed under the ISC License.
36 changes: 36 additions & 0 deletions components/input/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@byndyusoft-ui/input",
"version": "0.1.0",
"description": "Byndyusoft UI Input React Component",
"keywords": [
"byndyusoft",
"byndyusoft-ui",
"react",
"input"
],
"author": "Fomin Gleb <gleb.fom28@gmail.com>",
"homepage": "https://github.com/Byndyusoft/ui/tree/master/components/Input#readme",
"license": "ISC",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/Byndyusoft/ui.git"
},
"scripts": {
"build": "tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"lint": "eslint src --config ../../eslint.config.js",
"test": "jest --config ../../jest.config.js --roots components/input/src"
},
"bugs": {
"url": "https://github.com/Byndyusoft/ui/issues"
},
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"react": ">=17",
"classnames": "^2.3.1"
}
}
15 changes: 15 additions & 0 deletions components/input/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import typescript from '@rollup/plugin-typescript';
import baseConfig from '../../rollup.base.config';

export default {
...baseConfig,
input: ['src/index.ts'],
plugins: [
...baseConfig.plugins,
typescript({
tsconfig: './tsconfig.json',
module: 'ESNext',
exclude: ['src/*.stories.tsx', 'src/*.tests.tsx', 'node_modules']
})
]
};
121 changes: 121 additions & 0 deletions components/input/src/Input.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
:root {
Copy link
Contributor

@ancientbag ancientbag May 5, 2025

Choose a reason for hiding this comment

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

нужно ли эти переменные в рут тащить?

--input-height-s: 1.5rem;
--input-height-m: 2rem;
--input-height-l: 2.5rem;
--input-height-xl: 3rem;

--input-font-size-s: 0.75rem;
--input-font-size-m: 0.875rem;
--input-font-size-l: 1rem;
--input-font-size-xl: 1.25rem;

--input-border-radius: 0.375rem;
--input-padding-x: 0.5rem;
--input-transition: box-shadow ease 200ms, border ease 200ms;
--input-disabled-opacity: 0.5;
--input-container-gap: 0.25rem;

--input-main-color: #343434;
--input-focus-color: #000000;
--input-invalid-color: #ff0000;

--input-line-border: 1px solid var(--input-main-color);
--input-line-focus-border: 1px solid var(--input-focus-color);
--input-line-focus-box-shadow: 0 -1px 0 0 var(--input-focus-color) inset;
--input-invalid-line-border: 1px solid var(--input-invalid-color);
--input-invalid-line-box-shadow: 0 -1px 0 0 var(--input-invalid-color) inset;

--input-outline-border: 1px solid var(--input-main-color);
--input-outline-focus-border: 1px solid var(--input-focus-color);
--input-outline-focus-box-shadow: 0 0 0 1px var(--input-focus-color) inset;
--input-invalid-outline-border: 1px solid var(--input-invalid-color);
--input-invalid-outline-box-shadow: 0 0 0 1px var(--input-invalid-color) inset;
}

.input_container {
box-sizing: border-box;
display: flex;
gap: var(--input-container-gap);
align-items: center;
overflow: hidden;
background: none;
outline: none;
transition: var(--input-transition);
}

.disabled {
pointer-events: none;
opacity: var(--input-disabled-opacity);
}

.input {
width: 100%;
border: none;
outline: none;
background: none;
}

.s, .s .input {
height: var(--input-height-s);
font-size: var(--input-font-size-s);
}


.m, .m .input {
height: var(--input-height-m);
font-size: var(--input-font-size-m);
}

.l, .l .input {
height: var(--input-height-l);
font-size: var(--input-font-size-l);
}

.xl, .xl .input {
height: var(--input-height-xl);
font-size: var(--input-font-size-xl);
}

.outline {
border: var(--input-outline-border);
border-radius: var(--input-border-radius);
padding-left: var(--input-padding-x);
padding-right: var(--input-padding-x);

}

.outline:focus-within {
border: var(--input-outline-focus-border);
box-shadow: var(--input-outline-focus-box-shadow);
}

.line {
border-bottom: var(--input-line-border);
}

.line:focus-within {
border-bottom: var(--input-line-focus-border);
box-shadow: var(--input-line-focus-box-shadow);
}

.unstyled {
border: none;
}

.invalid.outline {
border: var(--input-invalid-outline-border);
}

.invalid.outline:focus-within {
border: var(--input-invalid-outline-border);
box-shadow: var(--input-invalid-outline-box-shadow);
}

.invalid.line {
border-bottom: var(--input-invalid-line-border);
}

.invalid.line:focus-within {
border-bottom: var(--input-invalid-line-border);
box-shadow: var(--input-invalid-line-box-shadow);
}
51 changes: 51 additions & 0 deletions components/input/src/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { forwardRef } from 'react';
import cn from 'classnames';
import { IInputProps } from './input.types';
import styles from './Input.module.css';

const Input = forwardRef<HTMLInputElement, IInputProps>((props, ref) => {
const {
size = 'l',
type = 'text',
variant = 'unstyled',
Copy link
Contributor

Choose a reason for hiding this comment

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

Это свойство управляет бордером инпута, но называется так, будто можно стиль всего инпута поменять

rightComponent,
leftComponent,
disabled,
isInvalid,
className,
style,
inputClassName,
inputStyle,
...otherProps
} = props;

const inputContainerClasses = [
styles.input_container,
styles[variant],
styles[size],
{ [styles.disabled]: Boolean(disabled) },
{ [styles.invalid]: Boolean(isInvalid) },
className
];

const inputClasses = [styles.input, inputClassName];

return (
<div className={cn(inputContainerClasses)} style={style}>
{leftComponent}
<input
className={cn(inputClasses)}
style={inputStyle}
ref={ref}
type={type}
disabled={disabled}
{...otherProps}
/>
{rightComponent}
</div>
);
});

Input.displayName = 'Input';

export default Input;
55 changes: 55 additions & 0 deletions components/input/src/__stories__/Input.docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Meta, Markdown, Canvas, Source, ArgsTable } from '@storybook/blocks';
import Readme from '../../README.md';
import Input from '../Input';
import * as InputStories from './Input.stories';

<Meta title="components/Input" of={InputStories} />

<Markdown>{Readme}</Markdown>

## Usage

To use the component in your project you must:

1. Import the component where you need it:

<Source language="javascript" code="import Input from '@byndyusoft-ui/input';" />

2. **Input Sizes**: Customize the size of the input field. Available sizes are `s`, `m`, `l`, `xl`.

<Canvas
sourceState="shown"
of={InputStories.InputSizeStory}
story={{ height: '50px' }}
/>

3. **Input Variants**: Choose from different input variants such as `outline`, `line`, `unstyled`.

<Canvas
sourceState="shown"
of={InputStories.InputVariantStory}
story={{ height: '50px' }}
/>

4. **Side Components**: Add components to the left or right side of the input field.

<Canvas
sourceState="shown"
of={InputStories.InputSideComponentsStory}
story={{ height: '50px' }}
/>

5. **Invalid State**: Handle invalid input states by setting the `isInvalid` prop.

<Canvas
sourceState="shown"
of={InputStories.InputInvalidTemplateStory}
story={{ height: '50px' }}
/>


## Props

Inherited from `InputHTMLAttributes<HTMLInputElement>`

<ArgsTable of={Input} />
8 changes: 8 additions & 0 deletions components/input/src/__stories__/Input.stories.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.template_wrapper {
padding: 20px;
margin: auto;
width: 250px;
display: flex;
flex-direction: column;
gap: 16px;
}
Loading