Skip to content

Commit

Permalink
Add support for object based characterCounter
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Jan 22, 2024
1 parent 00c278c commit 678a55f
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ export const TextareaCharacterCounter = () => (
autoresize
value="Textarea value\nNewline"
status="Message to the user"
characterCounter
maxLength={40}
characterCounter={40}
/>
</ComponentBox>
</Wrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ showTabs: true
| `label_sr_only` | _(optional)_ use `true` to make the label only readable by screen readers. |
| `autoresize` | _(optional)_ use `true` to make the Textarea grow and shrink depending on how many lines the user has filled. |
| `autoresize_max_rows` | _(optional)_ set a number to define how many rows the Textarea can auto grow. |
| `characterCounter` | _(optional)_ use `up` or `down` or `true` (down) to show a character counter. You need to set a `maxLength={number}` in order to show the counter. |
| `characterCounter` | _(optional)_ use a number to define the displayed max length. You can also use an object defining the [TextCounter](/uilib/fragments/TextCounter/) `variant` or properties. Please avoid using `maxLength` for accessibility reasons. |
| `status` | _(optional)_ text with a status message. The style defaults to an error message. You can use `true` to only get the status color, without a message. |
| `status_state` | _(optional)_ defines the state of the status. Currently, there are two statuses `[error, info]`. Defaults to `error`. |
| `status_props` | _(optional)_ use an object to define additional FormStatus properties. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.

### Component-specific props

| Property | Type | Description |
| --------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `string` | _(optional)_ Input DOM element type. |
| `multiline` | `boolean` | _(optional)_ True to be able to write in multiple lines (switching from input-element to textarea-element). |
| `leftIcon` | `string` | _(optional)_ For icon at the left side of the text input. |
| `rightIcon` | `string` | _(optional)_ For icon at the right side of the text input. |
| `inputClassName` | `string` | _(optional)_ Class name set on the &lt;input&gt; DOM element. |
| `innerRef` | `React.ref` | _(optional)_ by providing a React.ref we can get the internally used input element (DOM). E.g. `innerRef={myRef}` by using `React.createRef()` or `React.useRef()`. |
| `clear` | `boolean` | _(optional)_ True to have a clickable clear-icon for removing the active value. |
| `autoresize` | `boolean` | _(optional)_ For `multiline`, set `true` to expand when writing longer texts. |
| `autoComplete` | `on` or `string` | _(optional)_ For HTML `autocomplete` [attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete). |
| `capitalize` | `boolean` | _(optional)_ When set to `true`, it will capitalize the first letter of every word, transforming the rest to lowercase. |
| `trim` | `boolean` | _(optional)_ When `true`, it will trim leading and trailing whitespaces on blur, triggering onChange if the value changes. |
| `inputMode` | `string` | _(optional)_ Define a [inputmode](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode). |
| `autoresizeMaxRows` | `boolean` | _(optional)_ For `multiline`, set how many rows of text can be shown at max. |
| `characterCounter` | `boolean` or `string` | _(optional)_ Use `up` or `down` or `true` (down) to show a character counter. You need to set a `maxLength={number}` as well as have `multiline` enabled in order to show the counter. |
| `minLength` | `number` | _(optional)_ Validation for minimum length of the text (number of characters). |
| `maxLength` | `number` | _(optional)_ Validation for maximum length of the text (number of characters). |
| `pattern` | `string` | _(optional)_ Validation based on regex pattern. |
| `width` | `string` or `false` | _(optional)_ `false` for no width (use browser default), `small`, `medium` or `large` for predefined standard widths, `stretch` for fill available width. |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `content`. |
| [Space](/uilib/layout/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |
| Property | Type | Description |
| --------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `string` | _(optional)_ Input DOM element type. |
| `multiline` | `boolean` | _(optional)_ True to be able to write in multiple lines (switching from input-element to textarea-element). |
| `leftIcon` | `string` | _(optional)_ For icon at the left side of the text input. |
| `rightIcon` | `string` | _(optional)_ For icon at the right side of the text input. |
| `inputClassName` | `string` | _(optional)_ Class name set on the &lt;input&gt; DOM element. |
| `innerRef` | `React.ref` | _(optional)_ by providing a React.ref we can get the internally used input element (DOM). E.g. `innerRef={myRef}` by using `React.createRef()` or `React.useRef()`. |
| `clear` | `boolean` | _(optional)_ True to have a clickable clear-icon for removing the active value. |
| `autoresize` | `boolean` | _(optional)_ For `multiline`, set `true` to expand when writing longer texts. |
| `autoComplete` | `on` or `string` | _(optional)_ For HTML `autocomplete` [attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete). |
| `capitalize` | `boolean` | _(optional)_ When set to `true`, it will capitalize the first letter of every word, transforming the rest to lowercase. |
| `trim` | `boolean` | _(optional)_ When `true`, it will trim leading and trailing whitespaces on blur, triggering onChange if the value changes. |
| `inputMode` | `string` | _(optional)_ Define a [inputmode](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode). |
| `autoresizeMaxRows` | `boolean` | _(optional)_ For `multiline`, set how many rows of text can be shown at max. |
| `characterCounter` | `boolean` or `string` | _(optional)_ For `multiline`, use a number to define the displayed max length. You can also use an object defining the [TextCounter](/uilib/fragments/TextCounter/) `variant` or properties. |
| `minLength` | `number` | _(optional)_ Validation for minimum length of the text (number of characters). |
| `maxLength` | `number` | _(optional)_ Validation for maximum length of the text (number of characters). |
| `pattern` | `string` | _(optional)_ Validation based on regex pattern. |
| `width` | `string` or `false` | _(optional)_ `false` for no width (use browser default), `small`, `medium` or `large` for predefined standard widths, `stretch` for fill available width. |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `content`. |
| [Space](/uilib/layout/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |

## Properties

Expand Down
3 changes: 2 additions & 1 deletion packages/dnb-eufemia/src/components/textarea/Textarea.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { SkeletonShow } from '../Skeleton';
import type { SpacingProps } from '../space/types';
import type { FormLabelLabelDirection, FormLabelText } from '../FormLabel';
import type { GlobalStatusConfigObject } from '../GlobalStatus';
import type { TextCounterProps } from '../../fragments/TextCounter';
export type TextareaSuffix =
| string
| ((...args: any[]) => any)
Expand Down Expand Up @@ -90,7 +91,7 @@ export interface TextareaProps
/**
* Use `up` or `down` or `true` (down) to show a character counter. You need to set a `maxLength={number}` in order to show the counter.
*/
characterCounter?: boolean;
characterCounter?: Omit<TextCounterProps, 'text'> | number;
/**
* Set a number to define how many rows the Textarea can auto grow.
*/
Expand Down
15 changes: 8 additions & 7 deletions packages/dnb-eufemia/src/components/textarea/Textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,11 @@ export default class Textarea extends React.PureComponent {
disabled: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
skeleton: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
characterCounter: PropTypes.oneOfType([
PropTypes.oneOf(['down', 'up']),
PropTypes.bool,
PropTypes.shape({
max: PropTypes.number,
variant: PropTypes.oneOf(['down', 'up']),
}),
PropTypes.number,
]),
autoresize: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
autoresize_max_rows: PropTypes.oneOfType([
Expand Down Expand Up @@ -374,7 +377,6 @@ export default class Textarea extends React.PureComponent {
className,
autoresize,
characterCounter,
maxLength,
autoresize_max_rows, //eslint-disable-line
id: _id, //eslint-disable-line
children, //eslint-disable-line
Expand Down Expand Up @@ -405,7 +407,6 @@ export default class Textarea extends React.PureComponent {
value: hasValue ? value : '',
id,
name: id,
maxLength,
disabled: isTrue(disabled) || isTrue(skeleton),
'aria-placeholder': placeholder,
...attributes,
Expand Down Expand Up @@ -547,14 +548,14 @@ export default class Textarea extends React.PureComponent {
)}
</span>

{characterCounter && maxLength > 0 && (
{characterCounter && (
<TextCounter
variant={characterCounter}
text={value}
max={maxLength}
max={characterCounter}
bypassAriaLive={textareaState === 'virgin'}
lang={this.props.lang}
locale={this.props.locale}
{...characterCounter}
/>
)}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ describe('Textarea component', () => {

it('should render characterCounter', async () => {
const { rerender } = render(
<Textarea maxLength={8} characterCounter value="foo" />
<Textarea characterCounter={{ max: 8 }} value="foo" />
)

const counter = document.querySelector('.dnb-text-counter__message')
Expand All @@ -315,14 +315,24 @@ describe('Textarea component', () => {
expect(ariaLive).toHaveTextContent('6 av 8 tegn gjenstår')

rerender(
<Textarea maxLength={8} characterCounter value="foo" lang="en-GB" />
<Textarea characterCounter={{ max: 8 }} value="foo" lang="en-GB" />
)

expect(counter).toHaveTextContent('6 of 8 characters remaining')

await userEvent.type(textarea, 'baz')

expect(ariaLive).toHaveTextContent('8 of 8 characters remaining')

rerender(
<Textarea
characterCounter={{ max: 8, variant: 'up' }}
value="foo"
lang="en-GB"
/>
)

expect(counter).toHaveTextContent('You have used 8 of 8 characters')
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import InputMasked, {
import SharedContext from '../../../../shared/Context'
import FieldBlock from '../../FieldBlock'
import { useDataValue } from '../../hooks'
import { FieldProps, FieldHelpProps, JSONSchema } from '../../types'
import { pickSpacingProps } from '../../../../components/flex/utils'
import { toCapitalized } from '../../../../shared/component-helper'
import type { TextCounterProps } from '../../../../fragments/TextCounter'
import type { FieldProps, FieldHelpProps, JSONSchema } from '../../types'

interface ErrorMessages {
required?: string
Expand All @@ -32,7 +33,7 @@ export type Props = FieldHelpProps &
autoComplete?: HTMLInputElement['autocomplete']
inputMode?: React.HTMLAttributes<HTMLInputElement>['inputMode']
autoresizeMaxRows?: number
characterCounter?: boolean
characterCounter?: Omit<TextCounterProps, 'text'> | number
mask?: InputMaskedProps['mask']
// Validation
minLength?: number
Expand Down Expand Up @@ -200,7 +201,6 @@ function StringComponent(props: Props) {
autoresize={autoresize}
autoresize_max_rows={autoresizeMaxRows}
characterCounter={characterCounter}
maxLength={characterCounter ? props.maxLength : undefined}
/>
) : mask ? (
<InputMasked
Expand Down
Loading

0 comments on commit 678a55f

Please sign in to comment.