Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/src/__tests__/index.browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ describe('export', () => {
expect({ ...index }).toEqual({
Button: expect.any(Function),
Input: expect.any(Function),
Textarea: expect.any(Function),
Stepper: expect.any(Function),
Select: expect.any(Function),
Radio: expect.any(Function),
Expand Down
79 changes: 79 additions & 0 deletions packages/components/src/components/Textarea/Textarea.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Meta, StoryObj } from '@storybook/react-vite'

import { Textarea } from './index'

type Story = StoryObj<typeof meta>

const meta: Meta<typeof Textarea> = {
title: 'Devfive/Textarea',
component: Textarea,
decorators: [
(Story) => (
<div style={{ padding: '10px', maxWidth: '400px' }}>
<Story />
</div>
),
],
}

export const Default: Story = {
args: {
placeholder: 'Enter your message...',
},
}

export const WithDefaultValue: Story = {
args: {
defaultValue: 'This is some default text in the textarea.',
placeholder: 'Enter your message...',
},
}

export const Disabled: Story = {
args: {
placeholder: 'Disabled textarea',
disabled: true,
},
}

export const DisabledWithValue: Story = {
args: {
defaultValue: 'This textarea is disabled',
disabled: true,
},
}

export const Error: Story = {
args: {
placeholder: 'Enter your message...',
error: true,
},
}

export const ErrorWithMessage: Story = {
args: {
placeholder: 'Enter your message...',
error: true,
errorMessage: 'Please enter a valid message.',
},
}

export const CustomRows: Story = {
args: {
placeholder: 'This textarea has 6 rows',
rows: 6,
},
}

export const CustomColors: Story = {
args: {
placeholder: 'Custom themed textarea',
colors: {
primary: '#8B5CF6',
border: '#E5E7EB',
background: '#F9FAFB',
},
},
}

export default meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots

exports[`Textarea should render with default props 1`] = `
"<div>
<div class=" display-0-inline-block--255 position-0-relative--255 box-sizing-0-border-box-_a_-255 box-sizing-0-border-box-_a__s__st_-255 width-0-100%--255">
<textarea aria-label="textarea" rows="3" class=" color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled_c__c_placeholder-1 background-0-var(--disabledBg,light-dark(#F0F0F3,#414244))-_a__c_disabled-1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))-_a__c_disabled-1 color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled-1 cursor-0-not-allowed-_a__c_disabled-1 opacity-0-.5-_a__c_disabled-1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#674DC726,#8163E140))-_a__c_focus-1 outline-0-none-_a__c_focus-1 color-0-var(--placeholder,light-dark(#A9A8AB,#CBCBCB))-_a__c__c_placeholder-1 background-0-var(--background,light-dark(#FFF,#2E2E2E))--1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))--1 border-radius-0-8px--1 border-style-0-solid--1 border-width-0-1px--1 color-0-var(--text,light-dark(#272727,#F6F6F6))--1 font-size-0-16px--1 font-size-4-14px--1 line-height-0-1.5--1 min-height-0-80px--1 padding-0-12px--1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb_-1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#D52B2E33,#FF5B5E66))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 transition-0-border-color .15s ease-in-out,box-shadow .15s ease-in-out--1 width-0-100%--1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_hover-1 ">
</textarea>
</div>
</div>"
`;

exports[`Textarea should render with disabled prop 1`] = `
"<div>
<div class=" display-0-inline-block--255 position-0-relative--255 box-sizing-0-border-box-_a_-255 box-sizing-0-border-box-_a__s__st_-255 width-0-100%--255">
<textarea aria-label="textarea" disabled="" rows="3" class=" color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled_c__c_placeholder-1 background-0-var(--disabledBg,light-dark(#F0F0F3,#414244))-_a__c_disabled-1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))-_a__c_disabled-1 color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled-1 cursor-0-not-allowed-_a__c_disabled-1 opacity-0-.5-_a__c_disabled-1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#674DC726,#8163E140))-_a__c_focus-1 outline-0-none-_a__c_focus-1 color-0-var(--placeholder,light-dark(#A9A8AB,#CBCBCB))-_a__c__c_placeholder-1 background-0-var(--background,light-dark(#FFF,#2E2E2E))--1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))--1 border-radius-0-8px--1 border-style-0-solid--1 border-width-0-1px--1 color-0-var(--text,light-dark(#272727,#F6F6F6))--1 font-size-0-16px--1 font-size-4-14px--1 line-height-0-1.5--1 min-height-0-80px--1 padding-0-12px--1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb_-1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#D52B2E33,#FF5B5E66))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 transition-0-border-color .15s ease-in-out,box-shadow .15s ease-in-out--1 width-0-100%--1 ">
</textarea>
</div>
</div>"
`;

exports[`Textarea should render error style when error is true 1`] = `
"<div>
<div class=" display-0-inline-block--255 position-0-relative--255 box-sizing-0-border-box-_a_-255 box-sizing-0-border-box-_a__s__st_-255 width-0-100%--255">
<textarea aria-invalid="true" aria-label="textarea" rows="3" class=" color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled_c__c_placeholder-1 background-0-var(--disabledBg,light-dark(#F0F0F3,#414244))-_a__c_disabled-1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))-_a__c_disabled-1 color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled-1 cursor-0-not-allowed-_a__c_disabled-1 opacity-0-.5-_a__c_disabled-1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#674DC726,#8163E140))-_a__c_focus-1 outline-0-none-_a__c_focus-1 color-0-var(--placeholder,light-dark(#A9A8AB,#CBCBCB))-_a__c__c_placeholder-1 background-0-var(--background,light-dark(#FFF,#2E2E2E))--1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))--1 border-radius-0-8px--1 border-style-0-solid--1 border-width-0-1px--1 color-0-var(--text,light-dark(#272727,#F6F6F6))--1 font-size-0-16px--1 font-size-4-14px--1 line-height-0-1.5--1 min-height-0-80px--1 padding-0-12px--1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb_-1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#D52B2E33,#FF5B5E66))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 transition-0-border-color .15s ease-in-out,box-shadow .15s ease-in-out--1 width-0-100%--1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_hover-1 ">
</textarea>
</div>
</div>"
`;

exports[`Textarea should render with error message 1`] = `
"<div>
<div class=" display-0-inline-block--255 position-0-relative--255 box-sizing-0-border-box-_a_-255 box-sizing-0-border-box-_a__s__st_-255 width-0-100%--255">
<textarea aria-invalid="true" aria-label="textarea" rows="3" class=" color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled_c__c_placeholder-1 background-0-var(--disabledBg,light-dark(#F0F0F3,#414244))-_a__c_disabled-1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))-_a__c_disabled-1 color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled-1 cursor-0-not-allowed-_a__c_disabled-1 opacity-0-.5-_a__c_disabled-1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#674DC726,#8163E140))-_a__c_focus-1 outline-0-none-_a__c_focus-1 color-0-var(--placeholder,light-dark(#A9A8AB,#CBCBCB))-_a__c__c_placeholder-1 background-0-var(--background,light-dark(#FFF,#2E2E2E))--1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))--1 border-radius-0-8px--1 border-style-0-solid--1 border-width-0-1px--1 color-0-var(--text,light-dark(#272727,#F6F6F6))--1 font-size-0-16px--1 font-size-4-14px--1 line-height-0-1.5--1 min-height-0-80px--1 padding-0-12px--1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb_-1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#D52B2E33,#FF5B5E66))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 transition-0-border-color .15s ease-in-out,box-shadow .15s ease-in-out--1 width-0-100%--1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_hover-1 ">
</textarea>
<span aria-label="error-message" class=" bottom-0--8px--1 color-0-var(--error,light-dark(#D52B2E,#FF5B5E))--1 font-size-0-12px--1 left-0-0--1 position-0-absolute--1 transform-0-translateY(100%)--1">
Error message
</span>
</div>
</div>"
`;

exports[`Textarea should have typography when typography is provided 1`] = `
"<div>
<div class=" display-0-inline-block--255 position-0-relative--255 box-sizing-0-border-box-_a_-255 box-sizing-0-border-box-_a__s__st_-255 width-0-100%--255">
<textarea aria-label="textarea" rows="3" class=" color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled_c__c_placeholder-1 background-0-var(--disabledBg,light-dark(#F0F0F3,#414244))-_a__c_disabled-1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))-_a__c_disabled-1 color-0-var(--disabledText,light-dark(#D6D7DE,#373737))-_a__c_disabled-1 cursor-0-not-allowed-_a__c_disabled-1 opacity-0-.5-_a__c_disabled-1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#674DC726,#8163E140))-_a__c_focus-1 outline-0-none-_a__c_focus-1 color-0-var(--placeholder,light-dark(#A9A8AB,#CBCBCB))-_a__c__c_placeholder-1 background-0-var(--background,light-dark(#FFF,#2E2E2E))--1 border-color-0-var(--border,light-dark(#E4E4E4,#434343))--1 border-radius-0-8px--1 border-style-0-solid--1 border-width-0-1px--1 color-0-var(--text,light-dark(#272727,#F6F6F6))--1 font-size-0-16px--1 font-size-4-14px--1 line-height-0-1.5--1 min-height-0-80px--1 padding-0-12px--1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb_-1 border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 box-shadow-0-0 0 0 3px var(--focusRing,light-dark(#D52B2E33,#FF5B5E66))-_a__lb_aria-invalid_eq__dq_true_dq__rb__c_focus-1 transition-0-border-color .15s ease-in-out,box-shadow .15s ease-in-out--1 width-0-100%--1 border-color-0-var(--primary,light-dark(#674DC7,#8163E1))-_a__c_hover-1 typo-inlineLabelS">
</textarea>
</div>
</div>"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { DevupThemeTypography } from '@devup-ui/react'
import { describe, expect, it } from 'bun:test'
import { render, userEvent } from 'bun-test-env-dom'

import { Textarea } from '..'

describe('Textarea', () => {
it('should render with default props', () => {
const { container } = render(<Textarea />)
expect(container).toMatchSnapshot()
})

it('should render with placeholder', () => {
const { container } = render(<Textarea placeholder="Enter text..." />)
expect(container.querySelector('textarea')).toHaveAttribute(
'placeholder',
'Enter text...',
)
})

it('should render with default value', () => {
const { container } = render(<Textarea defaultValue="Default text" />)
expect(container.querySelector('textarea')?.value).toBe('Default text')
})

it('should render with disabled prop', () => {
const { container } = render(<Textarea disabled />)
expect(container).toMatchSnapshot()
expect(container.querySelector('textarea')).toHaveAttribute('disabled')
})

it('should render error style when error is true', () => {
const { container } = render(<Textarea error />)
expect(container).toMatchSnapshot()
expect(container.querySelector('[aria-label="textarea"]')).toHaveClass(
'border-color-0-var(--error,light-dark(#D52B2E,#FF5B5E))-_a__lb_aria-invalid_eq__dq_true_dq__rb_-1',
)
})

it('should render with error message', () => {
const { container } = render(
<Textarea error errorMessage="Error message" />,
)
expect(container).toMatchSnapshot()
expect(
container.querySelector('[aria-label="error-message"]'),
).toBeInTheDocument()
expect(
container.querySelector('[aria-label="error-message"]')?.textContent,
).toBe('Error message')
})

it('should not render error message when error is false', () => {
const { container } = render(<Textarea errorMessage="Error message" />)
expect(
container.querySelector('[aria-label="error-message"]'),
).not.toBeInTheDocument()
})

it('should render with aria-invalid when error is true', () => {
const { container } = render(<Textarea error />)
expect(container.querySelector('textarea')).toHaveAttribute(
'aria-invalid',
'true',
)
})

it('should not have aria-invalid when error is false', () => {
const { container } = render(<Textarea />)
expect(
container.querySelector('textarea')?.hasAttribute('aria-invalid'),
).toBe(false)
})

it('should render with custom rows', () => {
const { container } = render(<Textarea rows={6} />)
expect(container.querySelector('textarea')).toHaveAttribute('rows', '6')
})

it('should pass colors prop', () => {
const { container } = render(
<Textarea
colors={{
primary: 'red',
error: 'blue',
text: 'green',
}}
/>,
)
const textarea = container.querySelector('[aria-label="textarea"]')
expect(textarea).toHaveStyle({
'--primary': 'red',
'--error': 'blue',
'--text': 'green',
})
})

it('should have typography when typography is provided', () => {
const { container } = render(
<Textarea typography={'inlineLabelS' as keyof DevupThemeTypography} />,
)
expect(container).toMatchSnapshot()
expect(container.querySelector('textarea')).toHaveClass('typo-inlineLabelS')
})

it('should pass className prop', () => {
const { container } = render(<Textarea className="custom-class" />)
expect(container.querySelector('textarea')).toHaveClass('custom-class')
})

it('should pass classNames.container prop', () => {
const { container } = render(
<Textarea classNames={{ container: 'container-class' }} />,
)
expect(container.firstChild).toHaveClass('container-class')
})

it('should pass classNames.textarea prop', () => {
const { container } = render(
<Textarea classNames={{ textarea: 'textarea-class' }} />,
)
expect(container.querySelector('textarea')).toHaveClass('textarea-class')
})

it('should pass classNames.errorMessage prop', () => {
const { container } = render(
<Textarea
classNames={{ errorMessage: 'error-class' }}
error
errorMessage="Error"
/>,
)
expect(container.querySelector('[aria-label="error-message"]')).toHaveClass(
'error-class',
)
})

it('should handle onChange event', async () => {
let value = ''
const { container } = render(
<Textarea onChange={(e) => (value = e.target.value)} />,
)
await userEvent.type(container.querySelector('textarea')!, 'new value')
expect(value).toBe('new value')
})

it('should render full width by default', () => {
const { container } = render(<Textarea />)
expect(container.querySelector('[aria-label="textarea"]')).toHaveClass(
'width-0-100%--1',
)
})
})
Loading
Loading