From a78ea59762f2638cbfecfe1dc7dc4040c48c9db6 Mon Sep 17 00:00:00 2001 From: Arina Gazhina Date: Mon, 1 Jun 2026 21:04:24 +0300 Subject: [PATCH 1/3] feat(input): expose appearance and shape styles --- ui-parts/input/src/index.ts | 4 ++ ui-parts/input/src/input.component.tsx | 52 +++++++++++++-------- ui-parts/input/src/input.interfaces.ts | 4 ++ ui-parts/input/src/styles/appearance.css.ts | 13 ++++++ ui-parts/input/src/styles/index.ts | 4 ++ ui-parts/input/src/styles/interfaces.ts | 6 +++ ui-parts/input/src/styles/shape.css.ts | 4 ++ ui-parts/input/stories/input.stories.tsx | 36 +++++++++----- 8 files changed, 92 insertions(+), 31 deletions(-) create mode 100644 ui-parts/input/src/styles/interfaces.ts diff --git a/ui-parts/input/src/index.ts b/ui-parts/input/src/index.ts index 818841d64..da599b522 100644 --- a/ui-parts/input/src/index.ts +++ b/ui-parts/input/src/index.ts @@ -3,6 +3,10 @@ export * from './attachment/index.js' export * from './divided-fields/index.js' export * from './hidden-input/index.js' export * from './input.component.js' +export type { InputAppearance } from './styles/index.js' +export type { InputShape } from './styles/index.js' +export { inputAppearances } from './styles/index.js' +export { inputShapes } from './styles/index.js' export * from './input/index.js' export * from './raw-input/index.js' export * from './textarea/index.js' diff --git a/ui-parts/input/src/input.component.tsx b/ui-parts/input/src/input.component.tsx index b279b62f0..886e01fa1 100644 --- a/ui-parts/input/src/input.component.tsx +++ b/ui-parts/input/src/input.component.tsx @@ -1,13 +1,20 @@ 'use client' -import type { ReactNode } from 'react' +import type { ReactNode } from 'react' -import type { InputProps } from './input.interfaces.js' +import type { InputProps } from './input.interfaces.js' -import { inputStyles } from './styles/index.js' +import { clsx } from 'clsx' + +import { baseStyles } from './styles/index.js' +import { inputAppearances } from './styles/index.js' +import { inputShapes } from './styles/index.js' export const Input = ({ - size, + appearance, + className, + size = 'normal', + shape, value, type = 'text', variant = 'blue', @@ -15,18 +22,25 @@ export const Input = ({ onChange, ref, ...props -}: InputProps): ReactNode => ( - -) +}: InputProps): ReactNode => { + const inputAppearance = appearance || inputAppearances[variant] + const inputShape = shape || inputShapes[size] + + return ( + + ) +} diff --git a/ui-parts/input/src/input.interfaces.ts b/ui-parts/input/src/input.interfaces.ts index 68060f536..78fb952f4 100644 --- a/ui-parts/input/src/input.interfaces.ts +++ b/ui-parts/input/src/input.interfaces.ts @@ -3,6 +3,8 @@ import type { InputHTMLAttributes } from 'react' import type { Ref } from 'react' import type { JSX } from 'react' +import type { InputAppearance } from './styles/index.js' +import type { InputShape } from './styles/index.js' import type { inputStyles } from './styles/index.js' type InputHTMLAttributesWithoutSize = Omit, 'size'> @@ -13,6 +15,8 @@ export type InputVariants = Pick< > export interface InputProps extends InputHTMLAttributesWithoutSize, InputVariants { + appearance?: InputAppearance icon?: JSX.Element ref?: Ref + shape?: InputShape } diff --git a/ui-parts/input/src/styles/appearance.css.ts b/ui-parts/input/src/styles/appearance.css.ts index a7e115895..150899e91 100644 --- a/ui-parts/input/src/styles/appearance.css.ts +++ b/ui-parts/input/src/styles/appearance.css.ts @@ -1,3 +1,5 @@ +import type { InputAppearance } from './interfaces.js' + import { vars } from '@atls-ui-parts/theme' import { createAppearanceStyles } from '../utils/index.js' @@ -86,3 +88,14 @@ export const appearanceDisabled = { blueDisabled: appearanceBlueDisabledStyles, whiteDisabled: appearanceWhiteDisabledStyles, } + +export const inputAppearances: Record<'blue' | 'white', InputAppearance> = { + blue: { + default: appearanceVariant.blue, + disabled: appearanceDisabled.blueDisabled, + }, + white: { + default: appearanceVariant.white, + disabled: appearanceDisabled.whiteDisabled, + }, +} diff --git a/ui-parts/input/src/styles/index.ts b/ui-parts/input/src/styles/index.ts index b85edb221..ea685db11 100644 --- a/ui-parts/input/src/styles/index.ts +++ b/ui-parts/input/src/styles/index.ts @@ -1 +1,5 @@ +export * from './appearance.css.js' +export * from './base.css.js' +export type * from './interfaces.js' +export * from './shape.css.js' export * from './styles.css.js' diff --git a/ui-parts/input/src/styles/interfaces.ts b/ui-parts/input/src/styles/interfaces.ts new file mode 100644 index 000000000..0a62633ea --- /dev/null +++ b/ui-parts/input/src/styles/interfaces.ts @@ -0,0 +1,6 @@ +export interface InputAppearance { + default: string + disabled: string +} + +export type InputShape = string diff --git a/ui-parts/input/src/styles/shape.css.ts b/ui-parts/input/src/styles/shape.css.ts index 508b0c72a..910863271 100644 --- a/ui-parts/input/src/styles/shape.css.ts +++ b/ui-parts/input/src/styles/shape.css.ts @@ -1,3 +1,5 @@ +import type { InputShape } from './interfaces.js' + import { vars } from '@atls-ui-parts/theme' import { createShapeStyles } from '../utils/index.js' @@ -24,3 +26,5 @@ export const shapeStyles = { normal: normalSizeStyles, big: bigSizeStyles, } + +export const inputShapes: Record<'big' | 'normal', InputShape> = shapeStyles diff --git a/ui-parts/input/stories/input.stories.tsx b/ui-parts/input/stories/input.stories.tsx index 3413eb519..975f1bdca 100644 --- a/ui-parts/input/stories/input.stories.tsx +++ b/ui-parts/input/stories/input.stories.tsx @@ -1,26 +1,38 @@ -import type { Meta } from '@storybook/react' -import type { StoryObj } from '@storybook/react' +import type { Meta } from '@storybook/react' +import type { StoryObj } from '@storybook/react' -import { Input } from '../src/input.component.js' +import { Input } from '../src/input.component.js' +import { inputAppearances } from '../src/index.js' +import { inputShapes } from '../src/index.js' -const meta: Meta = { +type InputAppearanceName = keyof typeof inputAppearances +type InputShapeName = keyof typeof inputShapes + +interface InputStoryProps { + appearance: InputAppearanceName + shape: InputShapeName +} + +const meta: Meta = { title: 'Components/Input', - component: Input, tags: ['autodocs'], + render: ({ appearance, shape, ...props }) => ( + + ), argTypes: { - variant: { + appearance: { description: 'Вариант инпута', control: { type: 'inline-radio' }, - options: ['blue'], + options: Object.keys(inputAppearances), table: { type: { summary: 'string' }, defaultValue: { summary: 'blue' }, }, }, - size: { + shape: { description: 'Размер инпута', control: { type: 'inline-radio' }, - options: ['normal', 'big'], + options: Object.keys(inputShapes), table: { type: { summary: 'string' }, defaultValue: { summary: 'normal' }, @@ -31,11 +43,11 @@ const meta: Meta = { export default meta -type Story = StoryObj +type Story = StoryObj export const Variants: Story = { args: { - variant: 'white', - size: 'normal', + appearance: 'white', + shape: 'normal', }, } From 4cf33e00b01b0da470aeb36c0b5edf7911d0211f Mon Sep 17 00:00:00 2001 From: Arina Gazhina Date: Mon, 1 Jun 2026 21:53:09 +0300 Subject: [PATCH 2/3] refactor(input): remove recipes usage --- .../src/autocomplete.component.tsx | 9 +++- ui-parts/input/package.json | 1 - ui-parts/input/src/input.component.tsx | 45 +++++++--------- ui-parts/input/src/input.interfaces.ts | 9 +--- ui-parts/input/src/styles/appearance.css.ts | 51 ------------------- ui-parts/input/src/styles/index.ts | 1 - ui-parts/input/src/styles/styles.css.ts | 27 ---------- yarn.lock | 1 - 8 files changed, 28 insertions(+), 116 deletions(-) delete mode 100644 ui-parts/input/src/styles/styles.css.ts diff --git a/ui-parts/autocomplete/src/autocomplete.component.tsx b/ui-parts/autocomplete/src/autocomplete.component.tsx index 37dcce1f2..68b10e96f 100644 --- a/ui-parts/autocomplete/src/autocomplete.component.tsx +++ b/ui-parts/autocomplete/src/autocomplete.component.tsx @@ -13,6 +13,8 @@ import { useState } from 'react' import { Input } from '@atls-ui-parts/input' import { Row } from '@atls-ui-parts/layout' import { Box } from '@atls-ui-parts/layout' +import { inputAppearances } from '@atls-ui-parts/input' +import { inputShapes } from '@atls-ui-parts/input' import { useFloat } from '@atls-utils/use-float' import { Arrow } from './arrow/index.js' @@ -85,7 +87,12 @@ export const Autocomplete = ({ return ( - + {suffix} diff --git a/ui-parts/input/package.json b/ui-parts/input/package.json index 816d7cf19..398b49e9c 100644 --- a/ui-parts/input/package.json +++ b/ui-parts/input/package.json @@ -14,7 +14,6 @@ }, "dependencies": { "@atls-ui-parts/theme": "workspace:*", - "@vanilla-extract/recipes": "0.5.5", "clsx": "2.1.1", "rainbow-sprinkles": "1.0.0" }, diff --git a/ui-parts/input/src/input.component.tsx b/ui-parts/input/src/input.component.tsx index 886e01fa1..93d2a0bd6 100644 --- a/ui-parts/input/src/input.component.tsx +++ b/ui-parts/input/src/input.component.tsx @@ -11,36 +11,29 @@ import { inputAppearances } from './styles/index.js' import { inputShapes } from './styles/index.js' export const Input = ({ - appearance, + appearance = inputAppearances.blue, className, - size = 'normal', - shape, + shape = inputShapes.normal, value, type = 'text', - variant = 'blue', disabled, onChange, ref, ...props -}: InputProps): ReactNode => { - const inputAppearance = appearance || inputAppearances[variant] - const inputShape = shape || inputShapes[size] - - return ( - - ) -} +}: InputProps): ReactNode => ( + +) diff --git a/ui-parts/input/src/input.interfaces.ts b/ui-parts/input/src/input.interfaces.ts index 78fb952f4..26fd23c28 100644 --- a/ui-parts/input/src/input.interfaces.ts +++ b/ui-parts/input/src/input.interfaces.ts @@ -1,20 +1,13 @@ -import type { RecipeVariants } from '@vanilla-extract/recipes' import type { InputHTMLAttributes } from 'react' import type { Ref } from 'react' import type { JSX } from 'react' import type { InputAppearance } from './styles/index.js' import type { InputShape } from './styles/index.js' -import type { inputStyles } from './styles/index.js' type InputHTMLAttributesWithoutSize = Omit, 'size'> -export type InputVariants = Pick< - NonNullable>, - 'size' | 'variant' -> - -export interface InputProps extends InputHTMLAttributesWithoutSize, InputVariants { +export interface InputProps extends InputHTMLAttributesWithoutSize { appearance?: InputAppearance icon?: JSX.Element ref?: Ref diff --git a/ui-parts/input/src/styles/appearance.css.ts b/ui-parts/input/src/styles/appearance.css.ts index 150899e91..719959490 100644 --- a/ui-parts/input/src/styles/appearance.css.ts +++ b/ui-parts/input/src/styles/appearance.css.ts @@ -10,24 +10,6 @@ const appearanceBlueDefaultStyles = createAppearanceStyles({ borderColor: vars.colors['input.blue.default.border'], }) -const appearanceBlueHoverStyles = createAppearanceStyles({ - fontColor: vars.colors['input.blue.hover.font'], - backgroundColor: vars.colors['input.blue.hover.background'], - borderColor: vars.colors['input.blue.hover.border'], -}) - -const appearanceBlueFocusStyles = createAppearanceStyles({ - fontColor: vars.colors['input.blue.focus.font'], - backgroundColor: vars.colors['input.blue.focus.background'], - borderColor: vars.colors['input.blue.focus.border'], -}) - -const appearanceBlueActiveStyles = createAppearanceStyles({ - fontColor: vars.colors['input.blue.active.font'], - backgroundColor: vars.colors['input.blue.active.background'], - borderColor: vars.colors['input.blue.active.border'], -}) - const appearanceBlueDisabledStyles = createAppearanceStyles({ fontColor: vars.colors['input.blue.disabled.font'], backgroundColor: vars.colors['input.blue.disabled.background'], @@ -40,24 +22,6 @@ const appearanceWhiteDefaultStyles = createAppearanceStyles({ borderColor: vars.colors['input.white.default.border'], }) -const appearanceWhiteHoverStyles = createAppearanceStyles({ - fontColor: vars.colors['input.white.hover.font'], - backgroundColor: vars.colors['input.white.hover.background'], - borderColor: vars.colors['input.white.hover.border'], -}) - -const appearanceWhiteFocusStyles = createAppearanceStyles({ - fontColor: vars.colors['input.white.focus.font'], - backgroundColor: vars.colors['input.white.focus.background'], - borderColor: vars.colors['input.white.focus.border'], -}) - -const appearanceWhiteActiveStyles = createAppearanceStyles({ - fontColor: vars.colors['input.white.active.font'], - backgroundColor: vars.colors['input.white.active.background'], - borderColor: vars.colors['input.white.active.border'], -}) - const appearanceWhiteDisabledStyles = createAppearanceStyles({ fontColor: vars.colors['input.white.disabled.font'], backgroundColor: vars.colors['input.white.disabled.background'], @@ -69,21 +33,6 @@ export const appearanceVariant = { white: appearanceWhiteDefaultStyles, } -export const appearanceHover = { - blueHover: appearanceBlueHoverStyles, - whiteHover: appearanceWhiteHoverStyles, -} - -export const appearanceFocus = { - blueFocus: appearanceBlueFocusStyles, - whiteFocus: appearanceWhiteFocusStyles, -} - -export const appearanceActive = { - blueActive: appearanceBlueActiveStyles, - whiteActive: appearanceWhiteActiveStyles, -} - export const appearanceDisabled = { blueDisabled: appearanceBlueDisabledStyles, whiteDisabled: appearanceWhiteDisabledStyles, diff --git a/ui-parts/input/src/styles/index.ts b/ui-parts/input/src/styles/index.ts index ea685db11..dc15673ed 100644 --- a/ui-parts/input/src/styles/index.ts +++ b/ui-parts/input/src/styles/index.ts @@ -2,4 +2,3 @@ export * from './appearance.css.js' export * from './base.css.js' export type * from './interfaces.js' export * from './shape.css.js' -export * from './styles.css.js' diff --git a/ui-parts/input/src/styles/styles.css.ts b/ui-parts/input/src/styles/styles.css.ts deleted file mode 100644 index aaf3c48e5..000000000 --- a/ui-parts/input/src/styles/styles.css.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { recipe } from '@vanilla-extract/recipes' - -import { appearanceActive } from './appearance.css.js' -import { appearanceDisabled } from './appearance.css.js' -import { appearanceFocus } from './appearance.css.js' -import { appearanceHover } from './appearance.css.js' -import { appearanceVariant } from './appearance.css.js' -import { baseStyles } from './base.css.js' -import { shapeStyles } from './shape.css.js' - -export const inputStyles = recipe({ - base: baseStyles, - - variants: { - variant: appearanceVariant, - hover: appearanceHover, - focus: appearanceFocus, - active: appearanceActive, - disabled: appearanceDisabled, - size: shapeStyles, - }, - - defaultVariants: { - variant: 'white', - size: 'normal', - }, -}) diff --git a/yarn.lock b/yarn.lock index 8a8e0ebf7..28f232145 100644 --- a/yarn.lock +++ b/yarn.lock @@ -649,7 +649,6 @@ __metadata: "@types/react": "npm:19.1.2" "@vanilla-extract/css": "npm:1.17.1" "@vanilla-extract/dynamic": "npm:2.1.2" - "@vanilla-extract/recipes": "npm:0.5.5" clsx: "npm:2.1.1" rainbow-sprinkles: "npm:1.0.0" react: "npm:19.1.0" From ea1a21e06989f70304653f74b99d2d0d2059ebca Mon Sep 17 00:00:00 2001 From: Arina Gazhina Date: Mon, 1 Jun 2026 22:23:21 +0300 Subject: [PATCH 3/3] fix(input): stories --- ui-parts/input/stories/input.stories.tsx | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/ui-parts/input/stories/input.stories.tsx b/ui-parts/input/stories/input.stories.tsx index 975f1bdca..74c509e9b 100644 --- a/ui-parts/input/stories/input.stories.tsx +++ b/ui-parts/input/stories/input.stories.tsx @@ -5,25 +5,16 @@ import { Input } from '../src/input.component.js' import { inputAppearances } from '../src/index.js' import { inputShapes } from '../src/index.js' -type InputAppearanceName = keyof typeof inputAppearances -type InputShapeName = keyof typeof inputShapes - -interface InputStoryProps { - appearance: InputAppearanceName - shape: InputShapeName -} - -const meta: Meta = { +const meta: Meta = { title: 'Components/Input', + component: Input, tags: ['autodocs'], - render: ({ appearance, shape, ...props }) => ( - - ), argTypes: { appearance: { description: 'Вариант инпута', control: { type: 'inline-radio' }, options: Object.keys(inputAppearances), + mapping: inputAppearances, table: { type: { summary: 'string' }, defaultValue: { summary: 'blue' }, @@ -33,6 +24,7 @@ const meta: Meta = { description: 'Размер инпута', control: { type: 'inline-radio' }, options: Object.keys(inputShapes), + mapping: inputShapes, table: { type: { summary: 'string' }, defaultValue: { summary: 'normal' }, @@ -43,11 +35,11 @@ const meta: Meta = { export default meta -type Story = StoryObj +type Story = StoryObj export const Variants: Story = { args: { - appearance: 'white', - shape: 'normal', + appearance: inputAppearances.white, + shape: inputShapes.normal, }, }