Skip to content

Commit 1701337

Browse files
committed
✨ Add Input component
1 parent 8dd8a5b commit 1701337

File tree

15 files changed

+544
-45
lines changed

15 files changed

+544
-45
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ import { Accordion } from 'webcoreui/react'
144144
- [Checkbox](https://github.com/Frontendland/webcoreui/tree/main/src/components/Checkbox)
145145
- [ConditionalWrapper](https://github.com/Frontendland/webcoreui/tree/main/src/components/ConditionalWrapper)
146146
- [Icon](https://github.com/Frontendland/webcoreui/tree/main/src/components/Icon)
147+
- [Input](https://github.com/Frontendland/webcoreui/tree/main/src/components/Input)
147148
- [Progress](https://github.com/Frontendland/webcoreui/tree/main/src/components/Progress)
148149
- [Radio](https://github.com/Frontendland/webcoreui/tree/main/src/components/Radio)
149150
- [Rating](https://github.com/Frontendland/webcoreui/tree/main/src/components/Rating)

scripts/createComponent.js

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,12 @@ const templates = {
9191
import Svelte${component} from '@components/${component}/${component}.svelte'
9292
import React${component} from '@components/${component}/${component}.tsx'
9393
94-
const sections = [
95-
{
96-
title: 'Astro ${lowerCaseComponent}s',
97-
component: Astro${component}
98-
},
99-
{
100-
title: 'Svelte ${lowerCaseComponent}s',
101-
component: Svelte${component}
102-
},
103-
{
104-
title: 'React ${lowerCaseComponent}s',
105-
component: React${component}
106-
}
107-
]
94+
import { getSections } from '@helpers'
95+
96+
const sections = getSections({
97+
title: '${lowerCaseComponent}s',
98+
components: [Astro${component}, Svelte${component}, React${component}]
99+
})
108100
---
109101
110102
<Layout>

src/components/Input/Input.astro

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
import type { InputProps } from './input'
3+
import ConditionalWrapper from '@components/ConditionalWrapper/ConditionalWrapper.astro'
4+
5+
import './input.scss'
6+
7+
interface Props extends InputProps {}
8+
9+
const {
10+
type = 'text',
11+
theme,
12+
label,
13+
subText,
14+
fill,
15+
className,
16+
...rest
17+
} = Astro.props
18+
19+
const classes = [
20+
'w-input',
21+
theme,
22+
fill && 'fill',
23+
className
24+
]
25+
26+
const useLabel = !!(label || subText || Astro.slots.has('icon'))
27+
---
28+
29+
<ConditionalWrapper condition={useLabel}>
30+
<label slot="wrapper" class="w-input-label">
31+
{label && (
32+
<div class="label">{label}</div>
33+
)}
34+
<ConditionalWrapper condition={Astro.slots.has('icon')}>
35+
<div class="input-wrapper" slot="wrapper">
36+
children
37+
</div>
38+
<slot name="icon" />
39+
children
40+
</ConditionalWrapper>
41+
{subText && (
42+
<div class="subtext">
43+
<Fragment set:html={subText} />
44+
</div>
45+
)}
46+
</label>
47+
<input
48+
type={type}
49+
class:list={classes}
50+
{...rest}
51+
/>
52+
</ConditionalWrapper>

src/components/Input/Input.svelte

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script lang="ts">
2+
import type { InputProps } from './input'
3+
import ConditionalWrapper from '@components/ConditionalWrapper/ConditionalWrapper.svelte'
4+
import './input.scss'
5+
6+
export let type: InputProps['type'] = 'text'
7+
export let theme: InputProps['theme'] = null
8+
export let label: InputProps['label'] = ''
9+
export let subText: InputProps['subText'] = ''
10+
export let fill: InputProps['fill'] = false
11+
export let className: InputProps['className'] = ''
12+
export let onChange: (e: any) => any = () => {}
13+
export let onKeyUp: (e: any) => any = () => {}
14+
15+
const classes = [
16+
'w-input',
17+
theme,
18+
fill && 'fill',
19+
className
20+
].filter(Boolean).join(' ')
21+
22+
const useLabel = !!(label || subText || $$slots.icon)
23+
</script>
24+
25+
<ConditionalWrapper
26+
condition={useLabel}
27+
element="label"
28+
class="w-input-label"
29+
>
30+
{#if label}
31+
<div class="label">{label}</div>
32+
{/if}
33+
<ConditionalWrapper
34+
condition={$$slots.icon}
35+
element="div"
36+
class="input-wrapper"
37+
>
38+
<slot name="icon" />
39+
<input
40+
type={type}
41+
class={classes}
42+
on:change={onChange}
43+
on:keyup={onKeyUp}
44+
{...$$restProps}
45+
/>
46+
</ConditionalWrapper>
47+
{#if label}
48+
<div class="subtext">
49+
{@html subText}
50+
</div>
51+
{/if}
52+
</ConditionalWrapper>

src/components/Input/Input.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from 'react'
2+
import type { ReactInputProps } from './input'
3+
import ConditionalWrapper from '@components/ConditionalWrapper/ConditionalWrapper.tsx'
4+
5+
import './input.scss'
6+
7+
const Input = ({
8+
type = 'text',
9+
theme,
10+
label,
11+
subText,
12+
fill,
13+
icon,
14+
value,
15+
className,
16+
...rest
17+
}: ReactInputProps) => {
18+
const classes = [
19+
'w-input',
20+
theme,
21+
fill && 'fill',
22+
className
23+
].filter(Boolean).join(' ')
24+
25+
const useLabel = !!(label || subText || icon)
26+
27+
return (
28+
<ConditionalWrapper condition={useLabel} wrapper={children => (
29+
<label className="w-input-label">
30+
{children}
31+
</label>
32+
)}>
33+
{label && (
34+
<div className="label">{label}</div>
35+
)}
36+
<ConditionalWrapper condition={!!icon} wrapper={children => (
37+
<div className="input-wrapper">
38+
{children}
39+
</div>
40+
)}>
41+
{icon && icon}
42+
<input
43+
type={type}
44+
className={classes}
45+
defaultValue={value}
46+
{...rest}
47+
/>
48+
</ConditionalWrapper>
49+
{subText && (
50+
<div
51+
className="subtext"
52+
dangerouslySetInnerHTML={{ __html: subText }}
53+
/>
54+
)}
55+
</ConditionalWrapper>
56+
)
57+
}
58+
59+
export default Input

src/components/Input/input.scss

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
@import '../../scss/config.scss';
2+
3+
.w-input {
4+
border-radius: 2px;
5+
padding: 5px 10px;
6+
border: 1px solid #252525;
7+
background: transparent;
8+
font-family: Regular;
9+
color: #FFF;
10+
line-height: 20px;
11+
width: 100%;
12+
color-scheme: dark;
13+
14+
&[disabled] {
15+
cursor: no-drop;
16+
color: #555;
17+
}
18+
19+
&::file-selector-button {
20+
background: transparent;
21+
border: 0;
22+
color: #FFF;
23+
}
24+
25+
&[type="color"] {
26+
padding: 0;
27+
}
28+
29+
&.info {
30+
border-color: #48dbfb;
31+
}
32+
33+
&.success {
34+
border-color: #1dd1a1;
35+
}
36+
37+
&.warning {
38+
border-color: #f7aa61;
39+
}
40+
41+
&.alert {
42+
border-color: #ee5253;
43+
}
44+
45+
&.fill {
46+
background: #252525;
47+
}
48+
}
49+
50+
.w-input-label {
51+
display: flex;
52+
flex-direction: column;
53+
54+
.label {
55+
font-size: 16px;
56+
color: #BBB;
57+
margin-bottom: 5px;
58+
}
59+
60+
.input-wrapper {
61+
display: flex;
62+
gap: 10px;
63+
align-items: center;
64+
position: relative;
65+
66+
input {
67+
padding-left: 40px;
68+
}
69+
70+
svg {
71+
position: absolute;
72+
left: 10px;
73+
width: 20px;
74+
height: 20px;
75+
}
76+
}
77+
78+
.subtext {
79+
font-size: 14px;
80+
color: #555;
81+
margin-top: 5px;
82+
}
83+
}

src/components/Input/input.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
export type InputProps = {
2+
type?: 'text'
3+
| 'email'
4+
| 'password'
5+
| 'number'
6+
| 'tel'
7+
| 'url'
8+
| 'search'
9+
| 'file'
10+
| 'date'
11+
| 'datetime-local'
12+
| 'month'
13+
| 'week'
14+
| 'time'
15+
| 'color'
16+
theme?: 'info'
17+
| 'success'
18+
| 'warning'
19+
| 'alert'
20+
| null
21+
value?: string | number
22+
name?: string
23+
placeholder?: string
24+
label?: string
25+
disabled?: boolean
26+
subText?: string
27+
fill?: boolean
28+
maxLength?: number
29+
min?: number
30+
max?: number
31+
step?: number
32+
multiple?: boolean
33+
pattern?: string
34+
required?: boolean
35+
autofocus?: boolean
36+
autocomplete?: 'on' | 'off'
37+
className?: string
38+
[key: string]: any
39+
}
40+
41+
export type ReactInputProps = {
42+
icon?: string
43+
children?: React.ReactNode
44+
} & InputProps

src/helpers.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export const getSections = ({
2+
title,
3+
components,
4+
showSubTitle = false
5+
}) => {
6+
return [
7+
{
8+
title: `Astro ${title}`,
9+
component: components[0],
10+
},
11+
{
12+
title: `Svelte ${title}`,
13+
component: components[1],
14+
...(showSubTitle && {
15+
subTitle: 'For interactive examples, visit <a href="/svelte">Svelte Playground</a>',
16+
})
17+
},
18+
{
19+
title: `React ${title}`,
20+
component: components[2],
21+
...(showSubTitle && {
22+
subTitle: 'For interactive examples, visit <a href="/react">React Playground</a>',
23+
})
24+
}
25+
]
26+
}

src/pages/alert.astro

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,12 @@ import AstroAlert from '@components/Alert/Alert.astro'
66
import SvelteAlert from '@components/Alert/Alert.svelte'
77
import ReactAlert from '@components/Alert/Alert.tsx'
88
9-
const sections = [
10-
{
11-
title: 'Astro alerts',
12-
component: AstroAlert
13-
},
14-
{
15-
title: 'Svelte alerts',
16-
component: SvelteAlert
17-
},
18-
{
19-
title: 'React alerts',
20-
component: ReactAlert
21-
}
22-
]
9+
import { getSections } from '@helpers'
10+
11+
const sections = getSections({
12+
title: 'alerts',
13+
components: [AstroAlert, SvelteAlert, ReactAlert]
14+
})
2315
---
2416

2517
<Layout>

0 commit comments

Comments
 (0)