diff --git a/packages/eds-core-react/src/components/Input/Input.docs.mdx b/packages/eds-core-react/src/components/Input/Input.docs.mdx
index 0267ac8c02..db48ceaebe 100644
--- a/packages/eds-core-react/src/components/Input/Input.docs.mdx
+++ b/packages/eds-core-react/src/components/Input/Input.docs.mdx
@@ -58,3 +58,8 @@ Compact `Input` using `EdsProvider`.
+
+### Casted as textarea
+
+
+
diff --git a/packages/eds-core-react/src/components/Input/Input.stories.tsx b/packages/eds-core-react/src/components/Input/Input.stories.tsx
index 9504bcf265..d34a53c7b4 100644
--- a/packages/eds-core-react/src/components/Input/Input.stories.tsx
+++ b/packages/eds-core-react/src/components/Input/Input.stories.tsx
@@ -215,9 +215,7 @@ export const WithAdornments: Story = () => {
type="text"
id="adornments-default"
placeholder="Placeholder text Placeholder text"
- leftAdornmentsWidth={40}
leftAdornments={IT}
- rightAdornmentsWidth={52}
rightAdornments={
<>
unit
@@ -230,9 +228,7 @@ export const WithAdornments: Story = () => {
type="text"
id="adornments-error"
variant="error"
- leftAdornmentsWidth={40}
leftAdornments={IT}
- rightAdornmentsWidth={52}
rightAdornments={
<>
unit
@@ -245,9 +241,7 @@ export const WithAdornments: Story = () => {
type="text"
id="adornments-warning"
variant="warning"
- leftAdornmentsWidth={40}
leftAdornments={IT}
- rightAdornmentsWidth={52}
rightAdornments={
<>
unit
@@ -260,9 +254,7 @@ export const WithAdornments: Story = () => {
type="text"
id="adornments-success"
variant="success"
- leftAdornmentsWidth={40}
leftAdornments={IT}
- rightAdornmentsWidth={52}
rightAdornments={
<>
unit
@@ -277,7 +269,6 @@ export const WithAdornments: Story = () => {
disabled
placeholder="Placeholder text Placeholder text"
value="Some text Some textSome textSome text"
- leftAdornmentsWidth={40}
leftAdornments={
<>
@@ -285,7 +276,6 @@ export const WithAdornments: Story = () => {
>
}
- rightAdornmentsWidth={52}
rightAdornments={
<>
unit
@@ -298,13 +288,11 @@ export const WithAdornments: Story = () => {
type="text"
id="adornments-readonly"
readOnly
- leftAdornmentsWidth={40}
leftAdornments={
<>
IT
>
}
- rightAdornmentsWidth={52}
rightAdornments={
<>
unit
@@ -325,3 +313,7 @@ WithAdornments.decorators = [
)
},
]
+
+export const casted: Story = (args) => {
+ return
+}
diff --git a/packages/eds-core-react/src/components/Input/Input.tsx b/packages/eds-core-react/src/components/Input/Input.tsx
index 9eb15c8b45..cead041dcb 100644
--- a/packages/eds-core-react/src/components/Input/Input.tsx
+++ b/packages/eds-core-react/src/components/Input/Input.tsx
@@ -1,4 +1,12 @@
-import { InputHTMLAttributes, forwardRef, ReactNode, useMemo } from 'react'
+import {
+ forwardRef,
+ ReactNode,
+ useState,
+ useCallback,
+ CSSProperties,
+ ElementType,
+ ComponentPropsWithoutRef,
+} from 'react'
import styled, { css } from 'styled-components'
import { ComponentToken } from '@equinor/eds-tokens'
import {
@@ -6,10 +14,11 @@ import {
spacingsTemplate,
outlineTemplate,
useToken,
+ OverridableComponent,
} from '@equinor/eds-utils'
import { inputToken as tokens } from './Input.tokens'
import type { InputToken } from './Input.tokens'
-import type { Variants } from '../TextField/types'
+import type { Variants } from '../types'
import { useEds } from '../EdsProvider'
const Container = styled.div(({ token, disabled, readOnly }: StyledProps) => {
@@ -25,7 +34,6 @@ const Container = styled.div(({ token, disabled, readOnly }: StyledProps) => {
flex-direction: row;
border: none;
box-sizing: border-box;
- height: ${token.height};
box-shadow: ${token.boxShadow};
background: ${token.background};
${outlineTemplate(token.outline)}
@@ -53,25 +61,30 @@ const Container = styled.div(({ token, disabled, readOnly }: StyledProps) => {
`
})
-const StyledInput = styled.input(({ token }: StyledProps) => {
- return css`
- width: 100%;
- border: none;
- background: transparent;
- ${spacingsTemplate(token.spacings)}
- ${typographyMixin(token.typography)}
- outline: none;
-
- &::placeholder {
- color: ${token.entities.placeholder.typography.color};
- }
-
- &:disabled {
- color: var(--eds-input-color);
- cursor: not-allowed;
- }
- `
-})
+const StyledInput = styled.input(
+ ({ token, paddingLeft, paddingRight }: StyledProps) => {
+ return css`
+ width: 100%;
+ border: none;
+ background: transparent;
+ ${spacingsTemplate(token.spacings)}
+ ${typographyMixin(token.typography)}
+ outline: none;
+
+ padding-left: ${paddingLeft};
+ padding-right: ${paddingRight};
+
+ &::placeholder {
+ color: ${token.entities.placeholder.typography.color};
+ }
+
+ &:disabled {
+ color: var(--eds-input-color);
+ cursor: not-allowed;
+ }
+ `
+ },
+)
type AdornmentProps = {
token: InputToken
@@ -80,8 +93,8 @@ type AdornmentProps = {
const Adornments = styled.div(({ token }) => {
return css`
position: absolute;
- top: 0;
- bottom: 0;
+ top: ${token.spacings.top};
+ bottom: ${token.spacings.bottom};
display: flex;
align-items: center;
${typographyMixin(token.entities.adornment.typography)}
@@ -102,9 +115,10 @@ const RightAdornments = styled(Adornments)(
padding-right: ${token.entities.adornment.spacings.right};
`,
)
-
type StyledProps = {
token: InputToken
+ paddingLeft?: string
+ paddingRight?: string
} & Required>
export type InputProps = {
@@ -120,90 +134,110 @@ export type InputProps = {
readOnly?: boolean
/** Left adornments */
leftAdornments?: ReactNode
- /** Left adornments width */
- leftAdornmentsWidth?: number
/** Right adornments */
rightAdornments?: ReactNode
- /** Right adornments width */
- rightAdornmentsWidth?: number
-} & InputHTMLAttributes
-
-export const Input = forwardRef(function Input(
- {
- variant = 'default',
- disabled = false,
- type = 'text',
- leftAdornments,
- rightAdornments,
- leftAdornmentsWidth,
- rightAdornmentsWidth,
- readOnly,
- className,
- style,
- ...other
- },
- ref,
-) {
- const actualVariant = variant === 'default' ? 'input' : variant
- const inputVariant = tokens[actualVariant]
- const { density } = useEds()
- const token = useToken({ density }, inputVariant)()
-
- const updatedToken = useMemo(
- (): ComponentToken => ({
- ...token,
- spacings: {
- ...token.spacings,
- left:
- typeof leftAdornmentsWidth !== 'undefined'
- ? `${leftAdornmentsWidth}px`
- : token.spacings.left,
- right:
- typeof rightAdornmentsWidth !== 'undefined'
- ? `${rightAdornmentsWidth}px`
- : token.spacings.right,
- },
- }),
- [leftAdornmentsWidth, rightAdornmentsWidth, token],
- )
- const inputProps = {
+ /** Left adornments props */
+ leftAdornmentsProps?: ComponentPropsWithoutRef<'div'>
+ /** Right adornments props */
+ rightAdornmentsProps?: ComponentPropsWithoutRef<'div'>
+ /** Cast the input to another element */
+ as?: ElementType
+ /** */
+ className?: string
+ style?: CSSProperties
+}
+
+export const Input: OverridableComponent =
+ forwardRef(function Input(
+ {
+ variant,
+ disabled = false,
+ type = 'text',
+ leftAdornments,
+ rightAdornments,
+ readOnly,
+ className,
+ style,
+ leftAdornmentsProps,
+ rightAdornmentsProps,
+ ...other
+ },
ref,
- type,
- disabled,
- readOnly,
- token: updatedToken,
- ...other,
- }
-
- const containerProps = {
- disabled,
- readOnly,
- className,
- style,
- token: updatedToken,
- }
-
- const leftAdornmentProps = {
- token: updatedToken,
- }
- const rightAdornmentProps = {
- token: updatedToken,
- }
-
- return (
- // Not using because of cascading styling messing with adornments
-
- {leftAdornments ? (
-
- {leftAdornments}
-
- ) : null}
-
- {rightAdornments ? (
-
- {rightAdornments}
-
- ) : null}
-
- )
-})
+ ) {
+ const inputVariant = tokens[variant] ? tokens[variant] : tokens.input
+ const { density } = useEds()
+ const _token = useToken({ density }, inputVariant)()
+
+ const [rightAdornmentsRef, setRightAdornmentsRef] =
+ useState()
+ const [leftAdornmentsRef, setLeftAdornmentsRef] = useState()
+
+ const token = useCallback((): ComponentToken => {
+ const leftAdornmentsWidth = leftAdornmentsRef
+ ? leftAdornmentsRef.clientWidth
+ : 0
+ const rightAdornmentsWidth = rightAdornmentsRef
+ ? rightAdornmentsRef.clientWidth
+ : 0
+ return {
+ ..._token,
+ spacings: {
+ ..._token.spacings,
+ left: `${leftAdornmentsWidth + parseInt(_token.spacings.left)}px`,
+ right: `${rightAdornmentsWidth + parseInt(_token.spacings.right)}px`,
+ },
+ }
+ }, [leftAdornmentsRef, rightAdornmentsRef, _token])()
+
+ const inputProps = {
+ ref,
+ type,
+ disabled,
+ readOnly,
+ token,
+ style: {
+ resize: 'none',
+ },
+ ...other,
+ }
+
+ const containerProps = {
+ disabled,
+ readOnly,
+ className,
+ style,
+ token,
+ }
+
+ const _leftAdornmentProps = {
+ ...leftAdornmentsProps,
+ ref: setLeftAdornmentsRef,
+ token,
+ }
+ const _rightAdornmentProps = {
+ ...rightAdornmentsProps,
+ ref: setRightAdornmentsRef,
+ token,
+ }
+
+ return (
+ // Not using because of cascading styling messing with adornments
+
+ {leftAdornments ? (
+
+ {leftAdornments}
+
+ ) : null}
+
+ {rightAdornments ? (
+
+ {rightAdornments}
+
+ ) : null}
+
+ )
+ })
diff --git a/packages/eds-core-react/src/components/Input/__snapshots__/Input.test.tsx.snap b/packages/eds-core-react/src/components/Input/__snapshots__/Input.test.tsx.snap
index e7eb5b8df3..13a71fa95e 100644
--- a/packages/eds-core-react/src/components/Input/__snapshots__/Input.test.tsx.snap
+++ b/packages/eds-core-react/src/components/Input/__snapshots__/Input.test.tsx.snap
@@ -16,7 +16,6 @@ exports[`Input Matches snapshot 1`] = `
flex-direction: row;
border: none;
box-sizing: border-box;
- height: 36px;
box-shadow: inset 0px -1px 0px 0px var(--eds_text__static_icons__tertiary,rgba(111,111,111,1));
background: var(--eds_ui_background__light,rgba(247,247,247,1));
outline: 1px solid transparent;
@@ -78,6 +77,7 @@ exports[`Input Matches snapshot 1`] = `
diff --git a/packages/eds-core-react/src/components/InputWrapper/HelperText/HelperText.token.ts b/packages/eds-core-react/src/components/InputWrapper/HelperText/HelperText.token.ts
new file mode 100644
index 0000000000..541e839cc2
--- /dev/null
+++ b/packages/eds-core-react/src/components/InputWrapper/HelperText/HelperText.token.ts
@@ -0,0 +1,39 @@
+import { tokens } from '@equinor/eds-tokens'
+import type { Spacing, Typography } from '@equinor/eds-tokens'
+
+const {
+ colors,
+ spacings: { comfortable },
+ typography,
+} = tokens
+
+export type HelperTextProps = {
+ background: string
+ typography: Typography
+ spacings: {
+ comfortable: Spacing
+ compact: Spacing
+ }
+}
+
+export const helperText: HelperTextProps = {
+ background: colors.ui.background__light.hex,
+ typography: {
+ ...typography.input.helper,
+ color: colors.text.static_icons__tertiary.rgba,
+ },
+ spacings: {
+ comfortable: {
+ left: comfortable.small,
+ right: comfortable.small,
+ top: comfortable.small,
+ bottom: '6px',
+ },
+ compact: {
+ left: comfortable.small,
+ right: comfortable.small,
+ top: comfortable.xx_small,
+ bottom: '6px',
+ },
+ },
+}
diff --git a/packages/eds-core-react/src/components/InputWrapper/HelperText.tsx b/packages/eds-core-react/src/components/InputWrapper/HelperText/HelperText.tsx
similarity index 64%
rename from packages/eds-core-react/src/components/InputWrapper/HelperText.tsx
rename to packages/eds-core-react/src/components/InputWrapper/HelperText/HelperText.tsx
index 2d901a72a7..24f6d20591 100644
--- a/packages/eds-core-react/src/components/InputWrapper/HelperText.tsx
+++ b/packages/eds-core-react/src/components/InputWrapper/HelperText/HelperText.tsx
@@ -1,7 +1,7 @@
import { forwardRef, ReactNode, HTMLAttributes } from 'react'
import styled, { css } from 'styled-components'
-import { tokens } from '@equinor/eds-tokens'
-import { Typography } from '../Typography'
+import { typographyMixin } from '@equinor/eds-utils'
+import { helperText as tokens } from './HelperText.token'
type ContainerProps = {
color?: string
@@ -17,6 +17,10 @@ const Container = styled.div(({ color }) =>
color,
}),
)
+const Text = styled.p`
+ margin: 0;
+ ${typographyMixin(tokens.typography)};
+`
export type HelperTextProps = {
/** Helper text */
@@ -27,14 +31,9 @@ export type HelperTextProps = {
color?: string
} & HTMLAttributes
-export const HelperText = forwardRef(
+const TextfieldHelperText = forwardRef(
function TextfieldHelperText(
- {
- text,
- icon,
- color = tokens.colors.text.static_icons__tertiary.rgba,
- ...rest
- },
+ { text, icon, color = tokens.typography.color, ...rest },
ref,
) {
if (!text) {
@@ -44,10 +43,10 @@ export const HelperText = forwardRef(
return (
{icon}
-
- {text}
-
+ {text}
)
},
)
+
+export { TextfieldHelperText as HelperText }
diff --git a/packages/eds-core-react/src/components/InputWrapper/HelperText/index.ts b/packages/eds-core-react/src/components/InputWrapper/HelperText/index.ts
new file mode 100644
index 0000000000..a5e6cf6966
--- /dev/null
+++ b/packages/eds-core-react/src/components/InputWrapper/HelperText/index.ts
@@ -0,0 +1 @@
+export * from './HelperText'
diff --git a/packages/eds-core-react/src/components/InputWrapper/InputWrapper.stories.tsx b/packages/eds-core-react/src/components/InputWrapper/InputWrapper.stories.tsx
index 448958f55d..ae3d1b3129 100644
--- a/packages/eds-core-react/src/components/InputWrapper/InputWrapper.stories.tsx
+++ b/packages/eds-core-react/src/components/InputWrapper/InputWrapper.stories.tsx
@@ -1,8 +1,8 @@
import { Story, ComponentMeta } from '@storybook/react'
import { accessible, dropper, search } from '@equinor/eds-icons'
+import { Stack } from './../../../.storybook/components'
import { InputWrapper, InputWrapperProps, Input, Icon, Button } from '../..'
import styled from 'styled-components'
-import { useId } from '@equinor/eds-utils'
export default {
title: 'Inputs/InputWrapper',
@@ -16,35 +16,20 @@ const SmallButton = styled(Button)`
export const Introduction: Story = (args) => {
const { color } = args
- const inputId = useId(null, 'inputwrapper-input')
- const helperTextId = useId(null, 'inputwrapper-helpertext')
-
+ const inputId = 'some-input-id'
+ const helperTextId = 'some-helper-id'
+ const helperProps = {
+ text: 'helperText',
+ }
return (
,
- }}
+ helperProps={helperProps}
labelProps={{
- htmlFor: inputId,
- meta: 'meta tag',
+ label: "I'm a label, play with me!",
}}
{...args}
>
- }
- rightAdornmentsWidth={24 + 8}
- rightAdornments={
-
-
-
- }
- />
+
)
}
diff --git a/packages/eds-core-react/src/components/InputWrapper/InputWrapper.tsx b/packages/eds-core-react/src/components/InputWrapper/InputWrapper.tsx
index 8d777ab083..ff9fd18f24 100644
--- a/packages/eds-core-react/src/components/InputWrapper/InputWrapper.tsx
+++ b/packages/eds-core-react/src/components/InputWrapper/InputWrapper.tsx
@@ -1,10 +1,11 @@
-import { HTMLAttributes, forwardRef, useMemo, ReactNode } from 'react'
+import { HTMLAttributes, forwardRef, ReactNode, useCallback } from 'react'
import styled, { ThemeProvider } from 'styled-components'
import { useToken } from '@equinor/eds-utils'
import { Label as _Label, LabelProps } from '../Label'
import { HelperText as _HelperText, HelperTextProps } from './HelperText'
import { useEds } from './../EdsProvider'
import { inputToken as tokens } from './InputWrapper.tokens'
+import { Variants } from '../types'
const Container = styled.div``
@@ -26,19 +27,29 @@ export type InputWrapperProps = {
/** Read Only */
readOnly?: boolean
/** Highlight color */
- color?: 'error' | 'warning' | 'success'
+ color?: Variants
/** Label props */
- labelProps: LabelProps
+ labelProps?: LabelProps
/** Helpertext props */
helperProps?: HelperTextProps
- /** Input or Textarea elements */
+ /** Helper Icon */
+ helperIcon?: ReactNode
+ /** Input or Textarea element */
children: ReactNode
} & HTMLAttributes
/** InputWrapper is a internal skeleton component for structering form elements */
export const InputWrapper = forwardRef(
function InputWrapper(
- { children, color, label, labelProps = {}, helperProps = {}, ...other },
+ {
+ children,
+ color,
+ label,
+ labelProps = {},
+ helperProps = {},
+ helperIcon,
+ ...other
+ },
ref,
) {
const { density } = useEds()
@@ -46,23 +57,26 @@ export const InputWrapper = forwardRef(
const inputToken = tokens[actualVariant]
const token = useToken({ density }, inputToken)
- const helperTextColor = useMemo(() => {
+ const helperTextColor = useCallback(() => {
const _token = token()
return other.disabled
? _token.entities.helperText.states.disabled.typography.color
: _token.entities.helperText.typography.color
- }, [token, other.disabled])
+ }, [token, other.disabled])()
- const hasHelperText = Boolean(helperProps.text)
- const hasLabel = Boolean(label || labelProps.label)
+ const hasHelperText = Boolean(helperProps?.text)
+ const hasLabel = Boolean(label || labelProps?.label)
return (
- {hasLabel && }
+ {hasLabel && }
{children}
{hasHelperText && (
-
+
)}
diff --git a/packages/eds-core-react/src/components/Search/__snapshots__/Search.test.tsx.snap b/packages/eds-core-react/src/components/Search/__snapshots__/Search.test.tsx.snap
index f23dc921ed..08bb898764 100644
--- a/packages/eds-core-react/src/components/Search/__snapshots__/Search.test.tsx.snap
+++ b/packages/eds-core-react/src/components/Search/__snapshots__/Search.test.tsx.snap
@@ -116,7 +116,6 @@ exports[`Search Matches snapshot 1`] = `
flex-direction: row;
border: none;
box-sizing: border-box;
- height: 36px;
box-shadow: inset 0px -1px 0px 0px var(--eds_text__static_icons__tertiary,rgba(111,111,111,1));
background: var(--eds_ui_background__light,rgba(247,247,247,1));
outline: 1px solid transparent;
@@ -321,6 +320,7 @@ exports[`Search Matches snapshot 1`] = `
aria-label="search input"
class="c3"
role="searchbox"
+ style="padding-left: 8px; padding-right: 8px;"
type="search"
value=""
/>
diff --git a/packages/eds-core-react/src/components/Select/SingleSelect/__snapshots__/SingleSelect.test.tsx.snap b/packages/eds-core-react/src/components/Select/SingleSelect/__snapshots__/SingleSelect.test.tsx.snap
index 3632b3af1b..121deca9df 100644
--- a/packages/eds-core-react/src/components/Select/SingleSelect/__snapshots__/SingleSelect.test.tsx.snap
+++ b/packages/eds-core-react/src/components/Select/SingleSelect/__snapshots__/SingleSelect.test.tsx.snap
@@ -42,7 +42,6 @@ exports[`SingleSelect Matches snapshot 1`] = `
flex-direction: row;
border: none;
box-sizing: border-box;
- height: 36px;
box-shadow: inset 0px -1px 0px 0px var(--eds_text__static_icons__tertiary,rgba(111,111,111,1));
background: var(--eds_ui_background__light,rgba(247,247,247,1));
outline: 1px solid transparent;
@@ -285,6 +284,7 @@ exports[`SingleSelect Matches snapshot 1`] = `
autocomplete="off"
class="c6"
id="downshift-0-input"
+ style="padding-left: 8px; padding-right: 8px;"
type="text"
value=""
/>
diff --git a/packages/eds-core-react/src/components/TextField/Field.tsx b/packages/eds-core-react/src/components/TextField/Field.tsx
deleted file mode 100644
index 7e4cc161a4..0000000000
--- a/packages/eds-core-react/src/components/TextField/Field.tsx
+++ /dev/null
@@ -1,247 +0,0 @@
-import { ReactNode, forwardRef, Ref } from 'react'
-import { useTextField } from './TextField.context'
-import { Input } from '../Input'
-import { Icon } from './Icon'
-import type { Variants } from './types'
-import type { TextFieldToken } from './TextField.tokens'
-import styled, { css } from 'styled-components'
-import { typographyTemplate, outlineTemplate } from '@equinor/eds-utils'
-import * as tokens from './TextField.tokens'
-import { Textarea } from '../Textarea'
-import { useEds } from './../EdsProvider'
-
-const { textfield } = tokens
-
-const Variation = ({
- variant,
- isFocused,
- token,
-}: {
- variant: string
- token: TextFieldToken
- isFocused: boolean
-}) => {
- if (!variant) {
- return ``
- }
-
- return css`
- box-shadow: ${isFocused
- ? `none`
- : variant === 'default'
- ? `inset 0 -1px 0 0 ${
- token.border?.type === 'border' && token.border?.color
- }`
- : `0 0 0 1px ${token.border?.type === 'border' && token.border?.color}`};
- ${isFocused && outlineTemplate(token.states.focus.outline)}
- `
-}
-
-const StrippedInput = styled(Input)`
- outline: none;
-
- &:active,
- &:focus {
- outline: none;
- box-shadow: none;
- }
-`
-
-const StrippedTextarea = styled(Textarea)`
- outline: none;
-
- &:active,
- &:focus {
- outline: none;
- box-shadow: none;
- }
-`
-
-type InputWrapperType = {
- isFocused: boolean
- isDisabled: boolean
- isReadOnly: boolean
- variant: string
- token: TextFieldToken
- inputIcon?: ReactNode
- unit?: string
- multiline?: boolean
-}
-
-export const InputWrapper = styled.div(
- ({ inputIcon, unit, isDisabled, isReadOnly, multiline, variant }) => css`
- ${Variation}
- ${(inputIcon || unit) &&
- css`
- display: flex;
- align-items: center;
- background: ${textfield.background};
- padding-right: ${textfield.spacings.right};
- `}
- ${isReadOnly &&
- css`
- box-shadow: ${textfield.states.readOnly.boxShadow};
- background: ${textfield.states.readOnly.background};
- `}
- ${isDisabled &&
- css`
- box-shadow: none;
- cursor: not-allowed;
- outline: none;
- `}
- ${multiline &&
- variant === 'default' &&
- !inputIcon &&
- !unit &&
- css`
- box-shadow: none;
- `}
- `,
-)
-
-type UnitType = {
- isDisabled: boolean
-}
-
-const Unit = styled.span`
- ${typographyTemplate(textfield.entities.unit.typography)};
- /* Yes, we don't like magic numbers, but if you have both unit and icon,
- the unit is slightly off due to line-height and font */
- display: inline-block;
- margin-top: 3px;
- ${({ isDisabled }) =>
- isDisabled && {
- color: textfield.entities.unit.states.disabled.typography.color,
- }}
-`
-
-type AdornmentsType = {
- multiline: boolean
-}
-
-const Adornments = styled.div`
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
- margin-left: ${textfield.spacings.left};
- & div:nth-child(2) {
- margin-left: ${textfield.spacings.left};
- }
- ${({ multiline, theme }) =>
- multiline && {
- marginTop: theme.spacings.top,
- alignSelf: 'start',
- }}
-`
-
-type FieldProps = {
- /** Specifies if input should be multiline*/
- multiline?: boolean
- /** Placeholder */
- placeholder?: string
- /** Variant */
- variant?: Variants
- /** Disabled state */
- disabled?: boolean
- /** Type */
- type?: string
- /** Read Only */
- readOnly?: boolean
- /** Unit text */
- unit?: string
- /* Input icon */
- inputIcon?: ReactNode
- /** Specifies max rows for multiline input */
- rowsMax?: number
-} & React.HTMLAttributes
-
-export const Field = forwardRef<
- HTMLTextAreaElement | HTMLInputElement,
- FieldProps
->(function Field(
- {
- multiline,
- variant,
- disabled,
- readOnly,
- type,
- unit,
- inputIcon,
- rowsMax,
- onBlur,
- onFocus,
- ...other
- },
- ref,
-) {
- const { handleFocus, handleBlur, isFocused } = useTextField()
- const { density } = useEds()
- const iconSize = density === 'compact' ? 16 : 24
- const actualVariant = variant === 'default' ? 'textfield' : variant
- const inputVariant = tokens[actualVariant]
- const isError = actualVariant === 'error'
-
- const focusHandler = (
- e: React.FocusEvent,
- ) => {
- handleFocus()
- onFocus && onFocus(e)
- }
-
- const blurHandler = (
- e: React.FocusEvent,
- ) => {
- handleBlur()
- onBlur && onBlur(e)
- }
-
- const inputWrapperProps = {
- isFocused,
- isDisabled: disabled,
- isReadOnly: readOnly,
- variant,
- token: inputVariant,
- inputIcon,
- unit,
- multiline,
- }
-
- const inputProps = {
- ref: ref as Ref,
- 'aria-invalid': isError,
- type,
- disabled,
- readOnly,
- variant,
- onBlur: blurHandler,
- onFocus: focusHandler,
- ...other,
- }
-
- const textareaProps = {
- ...inputProps,
- rowsMax,
- ref: ref as Ref,
- }
-
- return (
-
- {multiline ? (
-
- ) : (
-
- )}
- {(inputIcon || unit) && (
-
- {unit && {unit}}
- {inputIcon && (
-
- {inputIcon}
-
- )}
-
- )}
-
- )
-})
diff --git a/packages/eds-core-react/src/components/TextField/HelperText/HelperText.token.ts b/packages/eds-core-react/src/components/TextField/HelperText/HelperText.token.ts
deleted file mode 100644
index 2d1d66656d..0000000000
--- a/packages/eds-core-react/src/components/TextField/HelperText/HelperText.token.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { tokens } from '@equinor/eds-tokens'
-import type { Spacing, Typography } from '@equinor/eds-tokens'
-import { ColorStateProps } from '../types'
-
-const {
- colors,
- spacings: { comfortable },
- typography,
-} = tokens
-
-export type HelperTextProps = {
- background: string
- typography: Typography
- spacings: {
- comfortable: Spacing
- compact: Spacing
- }
- default: ColorStateProps
- error: ColorStateProps
- warning: ColorStateProps
- success: ColorStateProps
-}
-
-export const helperText: HelperTextProps = {
- background: colors.ui.background__light.hex,
- typography: typography.input.helper,
- spacings: {
- comfortable: {
- left: comfortable.small,
- right: comfortable.small,
- top: comfortable.small,
- bottom: '6px',
- },
- compact: {
- left: comfortable.small,
- right: comfortable.small,
- top: comfortable.xx_small,
- bottom: '6px',
- },
- },
- default: {
- color: colors.text.static_icons__tertiary.hex,
- disabledColor: colors.interactive.disabled__text.hex,
- focusColor: colors.text.static_icons__tertiary.hex,
- },
- error: {
- color: colors.interactive.danger__text.hex,
- disabledColor: colors.interactive.disabled__text.hex,
- focusColor: colors.interactive.danger__hover.hex,
- },
- warning: {
- color: colors.interactive.warning__text.hex,
- disabledColor: colors.interactive.disabled__text.hex,
- focusColor: colors.interactive.warning__hover.hex,
- },
- success: {
- color: colors.interactive.success__text.hex,
- disabledColor: colors.interactive.disabled__text.hex,
- focusColor: colors.interactive.success__hover.hex,
- },
-}
diff --git a/packages/eds-core-react/src/components/TextField/HelperText/HelperText.tsx b/packages/eds-core-react/src/components/TextField/HelperText/HelperText.tsx
deleted file mode 100644
index edf0ef0706..0000000000
--- a/packages/eds-core-react/src/components/TextField/HelperText/HelperText.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import { ReactNode, forwardRef } from 'react'
-import styled, { css } from 'styled-components'
-import { typographyTemplate } from '@equinor/eds-utils'
-import { helperText as tokens } from './HelperText.token'
-import { useTextField } from '../TextField.context'
-import { Icon } from '../Icon'
-import type { Variants, ColorStateProps } from '../types'
-import type { Spacing } from '@equinor/eds-tokens'
-
-type VariationProps = {
- variant: ColorStateProps
- isFocused: boolean
- isDisabled: boolean
-}
-
-const Variation = ({ variant, isFocused, isDisabled }: VariationProps) => {
- if (!variant) {
- return ``
- }
-
- const { focusColor, color, disabledColor } = variant
-
- if (isDisabled) {
- return css`
- color: ${disabledColor};
- `
- }
-
- if (isFocused) {
- return css`
- color: ${focusColor};
- `
- }
-
- return css`
- color: ${color};
- `
-}
-
-type StyledProps = {
- spacings: Spacing
-}
-
-const Container = styled.div`
- display: flex;
- align-items: flex-start;
- margin-top: ${({ spacings }) => spacings.top};
-`
-const Text = styled.p`
- ${typographyTemplate(tokens.typography)}
- margin: 0 0 0 ${({ spacings }) => spacings.left};
- ${Variation}
-`
-
-type TextfieldHelperTextProps = {
- /** Helper text */
- helperText?: string
- /** Icon */
- icon?: ReactNode
- /** Disabled */
- disabled?: boolean
- /** Variant */
- variant: Variants
-}
-
-const TextfieldHelperText = forwardRef<
- HTMLDivElement,
- TextfieldHelperTextProps
->(function TextfieldHelperText(
- { helperText, icon, variant = 'default', disabled: isDisabled, ...rest },
- ref,
-) {
- const helperVariant = tokens[variant]
- const spacings = tokens.spacings.comfortable
-
- const { isFocused } = useTextField()
-
- const colors = {
- color: helperVariant.color,
- disabledColor: helperVariant.disabledColor,
- focusColor: helperVariant.focusColor,
- }
-
- return (
-
- {icon && (
-
- {icon}
-
- )}
-
- {helperText}
-
-
- )
-})
-
-export { TextfieldHelperText as HelperText }
diff --git a/packages/eds-core-react/src/components/TextField/HelperText/index.ts b/packages/eds-core-react/src/components/TextField/HelperText/index.ts
deleted file mode 100644
index 23c77d008a..0000000000
--- a/packages/eds-core-react/src/components/TextField/HelperText/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { HelperText } from './HelperText'
diff --git a/packages/eds-core-react/src/components/TextField/Icon/Icon.tokens.ts b/packages/eds-core-react/src/components/TextField/Icon/Icon.tokens.ts
deleted file mode 100644
index 0546d54c30..0000000000
--- a/packages/eds-core-react/src/components/TextField/Icon/Icon.tokens.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { tokens } from '@equinor/eds-tokens'
-import type { Spacing } from '@equinor/eds-tokens'
-import { ColorStateProps } from '../types'
-
-const {
- colors,
- spacings: { comfortable },
-} = tokens
-
-type InputProps = {
- spacings: {
- comfortable: Spacing
- compact: Spacing
- }
- default: ColorStateProps
- error: ColorStateProps
- warning: ColorStateProps
- success: ColorStateProps
-}
-
-export const input: InputProps = {
- spacings: {
- comfortable: {
- left: comfortable.small,
- right: comfortable.small,
- top: '10px',
- bottom: '10px',
- },
- compact: {
- left: comfortable.small,
- right: comfortable.small,
- top: '10px',
- bottom: '10px',
- },
- },
- default: {
- color: colors.text.static_icons__tertiary.hex,
- disabledColor: colors.interactive.disabled__fill.hex,
- focusColor: colors.interactive.primary__resting.hex,
- },
- error: {
- color: colors.interactive.danger__resting.hex,
- disabledColor: colors.interactive.disabled__fill.hex,
- focusColor: colors.interactive.danger__hover.hex,
- },
- warning: {
- color: colors.interactive.warning__resting.hex,
- disabledColor: colors.interactive.disabled__fill.hex,
- focusColor: colors.interactive.warning__hover.hex,
- },
- success: {
- color: colors.interactive.success__resting.hex,
- disabledColor: colors.interactive.disabled__fill.hex,
- focusColor: colors.interactive.success__hover.hex,
- },
-}
diff --git a/packages/eds-core-react/src/components/TextField/Icon/Icon.tsx b/packages/eds-core-react/src/components/TextField/Icon/Icon.tsx
deleted file mode 100644
index 476b33b1bf..0000000000
--- a/packages/eds-core-react/src/components/TextField/Icon/Icon.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import { HTMLAttributes, forwardRef } from 'react'
-import styled, { css } from 'styled-components'
-import { useTextField } from '../TextField.context'
-import { input as tokens } from './Icon.tokens'
-import type { Variants, ColorStateProps } from '../types'
-
-type StyledIconProps = {
- colors: ColorStateProps
- isDisabled?: boolean
- isFocused?: boolean
- size?: 16 | 24
-}
-
-const StyledIcon = styled.div(
- ({ colors, isDisabled, isFocused, size }) => {
- const { focusColor, color, disabledColor } = colors
- let fill = color
-
- if (isDisabled) {
- fill = disabledColor
- }
- if (isFocused) {
- fill = focusColor
- }
-
- return css`
- &,
- svg {
- fill: ${fill};
- width: ${size}px;
- height: ${size}px;
- }
- `
- },
-)
-
-type TextfieldIconProps = {
- /** isDisabled */
- isDisabled?: boolean
- /** Variant */
- variant?: Variants
- /** Colors */
- colors?: ColorStateProps
- /** Size */
- size?: 16 | 24
-} & HTMLAttributes
-
-const InputIcon = forwardRef(
- function InputIcon(
- {
- size = 24,
- variant = 'default',
- isDisabled = false,
- colors = {
- color: tokens[variant].color,
- disabledColor: tokens[variant].disabledColor,
- focusColor: tokens[variant].focusColor,
- },
- children,
- ...other
- },
- ref,
- ) {
- const { isFocused } = useTextField()
-
- const iconProps = {
- isDisabled,
- colors,
- isFocused,
- size,
- }
-
- return (
-
- {children}
-
- )
- },
-)
-
-export { InputIcon as Icon }
diff --git a/packages/eds-core-react/src/components/TextField/Icon/index.ts b/packages/eds-core-react/src/components/TextField/Icon/index.ts
deleted file mode 100644
index d78603a27e..0000000000
--- a/packages/eds-core-react/src/components/TextField/Icon/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { Icon } from './Icon'
diff --git a/packages/eds-core-react/src/components/TextField/TextField.context.tsx b/packages/eds-core-react/src/components/TextField/TextField.context.tsx
deleted file mode 100644
index c31f6c47aa..0000000000
--- a/packages/eds-core-react/src/components/TextField/TextField.context.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { useState, useContext, ReactNode, createContext } from 'react'
-
-export const propsFor = {
- variants: ['error', 'warning', 'success', 'default'],
-}
-
-type State = {
- isFocused: boolean
-}
-
-type UseTextFieldProps = {
- handleFocus: () => void
- handleBlur: () => void
-} & T
-
-const initalState: State = {
- isFocused: false,
-}
-
-const TextFieldContext = createContext(initalState)
-
-type ProviderProps = { children: ReactNode }
-
-export const TextFieldProvider = ({ children }: ProviderProps): JSX.Element => {
- const [state, setState] = useState(initalState)
-
- const handleFocus = () => {
- setState((prevState) => ({ ...prevState, isFocused: true }))
- }
- const handleBlur = () => {
- setState((prevState) => ({ ...prevState, isFocused: false }))
- }
- const value = {
- handleFocus,
- handleBlur,
- isFocused: state.isFocused,
- }
- return (
-
- {children}
-
- )
-}
-
-export const useTextField = (): UseTextFieldProps =>
- useContext(TextFieldContext) as UseTextFieldProps
diff --git a/packages/eds-core-react/src/components/TextField/TextField.docs.mdx b/packages/eds-core-react/src/components/TextField/TextField.docs.mdx
index 17fd2d42b1..b9615dede5 100644
--- a/packages/eds-core-react/src/components/TextField/TextField.docs.mdx
+++ b/packages/eds-core-react/src/components/TextField/TextField.docs.mdx
@@ -43,15 +43,15 @@ import { TextField } from '@equinor/eds-core-react'
-### Single line
+### Types
-Single line text fields display only one line of text.
+Examples of common used types (`input` type).
### Multiline
-Multi-line text fields grow to accommodate multiple lines of text.
+Changes the `input` to `textarea` for multiline support.
diff --git a/packages/eds-core-react/src/components/TextField/TextField.stories.tsx b/packages/eds-core-react/src/components/TextField/TextField.stories.tsx
index f091ac2940..1fb38f1a47 100644
--- a/packages/eds-core-react/src/components/TextField/TextField.stories.tsx
+++ b/packages/eds-core-react/src/components/TextField/TextField.stories.tsx
@@ -33,9 +33,9 @@ export default {
inputIcon: {
options: ['error', 'warning', 'success'],
mapping: {
- error: [],
- warning: [],
- success: [],
+ error: [],
+ warning: [],
+ success: [],
},
control: {
type: 'select',
@@ -46,9 +46,9 @@ export default {
helperIcon: {
options: ['error', 'warning', 'success'],
mapping: {
- error: [],
- warning: [],
- success: [],
+ error: [],
+ warning: [],
+ success: [],
},
control: {
type: 'select',
@@ -77,25 +77,24 @@ export default {
} as ComponentMeta
export const Introduction: Story = (args) => (
-
+
)
+Introduction.bind({})
+Introduction.args = {
+ unit: 'unit',
+ meta: 'meta',
+ id: 'playWithMe',
+ label: 'Play with me',
+ helperText: 'helper text',
+}
+
export const Types: Story = () => (
<>
= () => (
id="textfield-email"
placeholder="Placeholder text"
label="Email"
- meta="Meta"
helperText="Helper Text"
/>
= () => (
id="textfield-password"
placeholder="Placeholder text"
label="Password"
- meta="Meta"
helperText="Helper Text"
+ inputIcon={}
/>
>
)
-Types.storyName = 'Single line'
Types.decorators = [
(Story) => {
return (
@@ -151,10 +148,7 @@ Types.decorators = [
export const Multiline: Story = () => (
= () => (
export const MultilineRowsMax: Story = () => (
)
-MultilineRowsMax.storyName = 'Multiline with rowsMax'
export const MultilineFixedHeight: Story = () => (
= () => (
meta="Meta"
helperText="Validation error"
variant="error"
- helperIcon={}
+ helperIcon={}
/>
= () => (
rows={3}
helperText="Validation error"
variant="error"
- helperIcon={}
+ helperIcon={}
/>
= () => (
meta="Meta"
helperText="Helper/warning text"
variant="warning"
- helperIcon={}
+ helperIcon={}
/>
= () => (
meta="Meta"
helperText="Helper text"
variant="success"
- helperIcon={}
+ helperIcon={}
/>
= () => (
rows={3}
helperText="Helper text"
variant="success"
- helperIcon={}
+ helperIcon={}
/>
>
)
@@ -539,7 +531,7 @@ export const Compact: Story = () => {
label="Single line"
meta="Meta"
unit="km/h"
- helperIcon={}
+ helperIcon={}
helperText="Helper information text over several lines so that it breaks"
/>
@@ -602,7 +594,7 @@ export const ValidationWithReactHookForm: Story = () => {
invalid ? : undefined
}
helperText={error?.message}
- variant={invalid ? 'error' : 'default'}
+ variant={invalid ? 'error' : undefined}
/>
)}
/>
diff --git a/packages/eds-core-react/src/components/TextField/TextField.tokens.ts b/packages/eds-core-react/src/components/TextField/TextField.tokens.ts
deleted file mode 100644
index 15cba14539..0000000000
--- a/packages/eds-core-react/src/components/TextField/TextField.tokens.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { tokens } from '@equinor/eds-tokens'
-import type { ComponentToken } from '@equinor/eds-tokens'
-
-const {
- colors,
- typography,
- spacings: {
- comfortable: { small, x_small },
- },
-} = tokens
-
-export type TextFieldToken = ComponentToken & {
- entities?: {
- unit?: ComponentToken
- }
-}
-export const textfield: TextFieldToken = {
- background: colors.ui.background__light.hex,
- border: {
- type: 'border',
- radius: 0,
- width: '1px',
- color: colors.text.static_icons__tertiary.hex,
- },
- spacings: {
- left: small,
- right: small,
- top: small,
- },
- states: {
- focus: {
- outline: {
- width: '2px',
- color: colors.interactive.primary__resting.hex,
- style: 'solid',
- type: 'outline',
- offset: '0px',
- },
- },
- readOnly: {
- background: 'transparent',
- boxShadow: 'none',
- },
- },
- entities: {
- unit: {
- typography: {
- ...typography.input.label,
- color: colors.text.static_icons__tertiary.hex,
- },
- states: {
- disabled: {
- typography: {
- color: colors.interactive.disabled__text.hex,
- },
- },
- },
- },
- },
- modes: {
- compact: {
- spacings: {
- left: x_small,
- right: x_small,
- top: x_small,
- bottom: x_small,
- },
- },
- },
-}
-
-export const error: TextFieldToken = {
- border: {
- type: 'border',
- radius: 0,
- width: '1px',
- color: colors.interactive.danger__resting.hex,
- },
- states: {
- focus: {
- outline: {
- width: '2px',
- color: colors.interactive.danger__hover.hex,
- style: 'solid',
- type: 'outline',
- offset: '0px',
- },
- },
- },
-}
-export const warning: TextFieldToken = {
- border: {
- type: 'border',
- radius: 0,
- width: '1px',
- color: colors.interactive.warning__resting.hex,
- },
- states: {
- focus: {
- outline: {
- width: '2px',
- color: colors.interactive.warning__hover.hex,
- style: 'solid',
- type: 'outline',
- offset: '0px',
- },
- },
- },
-}
-export const success: TextFieldToken = {
- border: {
- type: 'border',
- radius: 0,
- width: '1px',
- color: colors.interactive.success__resting.hex,
- },
- states: {
- focus: {
- outline: {
- width: '2px',
- color: colors.interactive.success__hover.hex,
- style: 'solid',
- type: 'outline',
- offset: '0px',
- },
- },
- },
-}
diff --git a/packages/eds-core-react/src/components/TextField/TextField.tsx b/packages/eds-core-react/src/components/TextField/TextField.tsx
index e98f97fc87..11500b6cb8 100644
--- a/packages/eds-core-react/src/components/TextField/TextField.tsx
+++ b/packages/eds-core-react/src/components/TextField/TextField.tsx
@@ -3,29 +3,31 @@ import {
InputHTMLAttributes,
TextareaHTMLAttributes,
forwardRef,
- Ref,
+ ForwardedRef,
} from 'react'
-import styled, { ThemeProvider } from 'styled-components'
-import { Field } from './Field'
-import { Label } from '../Label'
-import { HelperText } from './HelperText'
-import { TextFieldProvider } from './TextField.context'
-import type { Variants } from './types'
-import { textfield as tokens } from './TextField.tokens'
-import { useToken, useId } from '@equinor/eds-utils'
-import { useEds } from '../EdsProvider'
+import { useId } from '@equinor/eds-utils'
+import { InputWrapper } from '../InputWrapper'
+import { Input } from '../Input'
+import { Textarea } from '../Textarea'
+import type { Variants } from '../types'
-const Container = styled.div`
- min-width: 100px;
- width: 100%;
-`
+type FieldProps = SharedTextFieldProps &
+ React.HTMLAttributes
+/** Proxy component for working around typescript and element type switching */
+const Field = forwardRef(
+ function Field(props, ref) {
+ return props.multiline ? (
+