Skip to content

Commit 527bdc3

Browse files
committed
feat: add input
1 parent 7065761 commit 527bdc3

File tree

6 files changed

+228
-0
lines changed

6 files changed

+228
-0
lines changed

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"build-storybook": "storybook build"
2626
},
2727
"dependencies": {
28+
"clsx": "^2.1.1",
2829
"react": "^18.3.1"
2930
},
3031
"peerDependencies": {

src/input/index.scss

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
@import '../theme/variables';
2+
3+
.fui-input {
4+
position: relative;
5+
}
6+
7+
.fui-input__inner {
8+
display: flex;
9+
align-items: center;
10+
flex-wrap: nowrap;
11+
border: 1px solid $colorNeutralStroke1;
12+
background-color: $colorNeutralBackground1;
13+
border-bottom-color: $colorNeutralStrokeAccessible;
14+
gap: $spacingHorizontalXXS;
15+
border-radius: $borderRadiusMedium;
16+
}
17+
18+
.fui-input__line {
19+
box-sizing: border-box;
20+
position: absolute;
21+
left: -1px;
22+
bottom: -1px;
23+
right: -1px;
24+
height: $borderRadiusMedium;
25+
border-bottom-left-radius: $borderRadiusMedium;
26+
border-bottom-right-radius: $borderRadiusMedium;
27+
border-bottom: 2px solid $colorCompoundBrandStroke;
28+
opacity: 0;
29+
}
30+
31+
.fui-input:focus-within .fui-input__line {
32+
opacity: 1;
33+
}
34+
35+
.fui-input__input {
36+
box-sizing: border-box;
37+
min-height: 32px;
38+
min-width: 0px;
39+
padding: 0 $spacingHorizontalM;
40+
color: $colorNeutralForeground1;
41+
font-family: $fontFamilyBase;
42+
font-size: $fontSizeBase300;
43+
font-weight: $fontWeightRegular;
44+
line-height: $lineHeightBase300;
45+
background-color: transparent;
46+
outline: none;
47+
border: none;
48+
flex: auto;
49+
}
50+
51+
.fui-input--underline .fui-input__inner {
52+
background-color: transparent;
53+
border-top-style: none;
54+
border-left-style: none;
55+
border-right-style: none;
56+
}
57+
58+
.fui-input--small .fui-input__input {
59+
min-height: 24px;
60+
font-size: $fontSizeBase200;
61+
line-height: $lineHeightBase200;
62+
padding-right: $spacingHorizontalS;
63+
padding-left: $spacingHorizontalS;
64+
}
65+
66+
.fui-input--large .fui-input__input {
67+
min-height: 40px;
68+
font-size: $fontSizeBase400;
69+
line-height: $lineHeightBase400;
70+
padding-right: calc($spacingHorizontalM + $spacingHorizontalSNudge);
71+
padding-left: calc($spacingHorizontalM + $spacingHorizontalSNudge);
72+
}
73+
74+
.fui-input--disabled {
75+
border-color: $colorNeutralStrokeDisabled;
76+
pointer-events: none;
77+
78+
.fui-input__input {
79+
color: $colorNeutralForegroundDisabled;
80+
background-color: $colorTransparentBackground;
81+
}
82+
}

src/input/index.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import clsx from "clsx";
2+
import { ReactNode, useRef } from "react";
3+
import './index.scss';
4+
5+
export interface InputProps {
6+
className?: string;
7+
contentBefore?: ReactNode;
8+
contentAfter?: ReactNode;
9+
placeholder?: string;
10+
disabled?: boolean;
11+
appearance?: "outline" | "underline";
12+
size?: "small" | "medium" | "large";
13+
value?: string;
14+
}
15+
16+
export default function Input({
17+
className,
18+
contentBefore,
19+
contentAfter,
20+
placeholder,
21+
appearance = "outline",
22+
disabled = false,
23+
size = "medium",
24+
value
25+
}: InputProps) {
26+
const inputRef = useRef<HTMLInputElement>(null);
27+
return (
28+
<div
29+
className={clsx(
30+
"fui-input",
31+
`fui-input--${appearance}`,
32+
`fui-input--${size}`,
33+
disabled && "fui-input--disabled",
34+
className
35+
)}
36+
>
37+
<div className="fui-input__inner">
38+
{contentBefore}
39+
<input
40+
ref={inputRef}
41+
className="fui-input__input"
42+
placeholder={placeholder}
43+
value={value}
44+
/>
45+
{contentAfter}
46+
</div>
47+
<div className="fui-input__line" />
48+
</div>
49+
);
50+
}

src/stories/input.stories.module.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.root {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 20px;
5+
max-width: 400px;
6+
7+
label {
8+
display: block;
9+
margin-bottom: 2px;
10+
}
11+
}

src/stories/input.stories.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import Input, { InputProps } from "../input";
3+
import styles from "./input.stories.module.css";
4+
5+
const meta: Meta<InputProps> = {
6+
title: "Components/Input",
7+
component: Input,
8+
tags: ["autodocs"],
9+
render: (props) => <Input {...props} />,
10+
};
11+
12+
type Story = StoryObj<InputProps>;
13+
14+
export const Default: Story = {
15+
render: (props) => (
16+
<div className={styles.root}>
17+
<div>
18+
<label>Sample input</label>
19+
<Input {...props} />
20+
</div>
21+
</div>
22+
),
23+
};
24+
25+
export const Disabled: Story = {
26+
parameters: {
27+
docs: {
28+
description: {
29+
story: "An input can be disabled.",
30+
},
31+
},
32+
},
33+
render: () => (
34+
<div className={styles.root}>
35+
<div>
36+
<label>Disabled input</label>
37+
<Input disabled value="disabled value" />
38+
</div>
39+
</div>
40+
),
41+
};
42+
43+
export const Size: Story = {
44+
parameters: {
45+
docs: {
46+
description: {
47+
story: "An input can have different sizes.",
48+
},
49+
},
50+
},
51+
render: () => (
52+
<div className={styles.root}>
53+
<div>
54+
<label>Small input</label>
55+
<Input size="small" />
56+
</div>
57+
<div>
58+
<label>Medium input</label>
59+
<Input size="medium" />
60+
</div>
61+
<div>
62+
<label>Large input</label>
63+
<Input size="large" />
64+
</div>
65+
</div>
66+
),
67+
};
68+
69+
export default meta;

0 commit comments

Comments
 (0)