Skip to content

Commit

Permalink
feat(vara-ui): add dark mode to Textarea, drop floating label (#1695)
Browse files Browse the repository at this point in the history
Co-authored-by: Nikita Yutanov <nikitayutanov@gmail.com>
  • Loading branch information
ereburg and nikitayutanov authored Jan 14, 2025
1 parent efa7fe1 commit b3a1566
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 175 deletions.
156 changes: 18 additions & 138 deletions utils/vara-ui/src/components/textarea/textarea.module.scss
Original file line number Diff line number Diff line change
@@ -1,149 +1,29 @@
.root {
&.disabled {
pointer-events: none;
opacity: 0.3;
}
}

.base {
position: relative;
}

.textarea,
.label {
font-weight: 400;
line-height: 24px;
letter-spacing: 0.009em;
color: #010500;

&.default {
font-size: 16px;
}

&.small {
font-size: 14px;
}
}
@use '../../utils.scss' as *;

.textarea {
outline: none;
resize: none;
background-color: transparent;
border: none;
font: inherit;
@include lightDark(color, #000, rgba(246, 246, 246, 0.9));

padding: 0;
background: transparent;
border: none;
outline: none;
width: 100%;
padding-right: 14px;
padding-left: 14px;

&:not(:focus) {
&::placeholder {
color: transparent;
}
}

&:focus,
&:not(:placeholder-shown),
&.error {
~ .label {
opacity: 0;
}

~ .fieldset {
.legendLabel {
opacity: 1;
max-width: 100%;
padding: 0 4px;
}
}
}

&:focus {
~ .fieldset {
border-color: #00b387;

.legendLabel {
color: #00b387;
}
}
}

&.error {
~ .fieldset {
border-color: #fc174d;

.legendLabel {
color: #fc174d;
}
}
}
font-family: inherit;
font-size: var(--input-font-size);
font-weight: 400;
line-height: var(--input-line-height);
resize: none;

&.default {
padding-top: 13px;
padding-bottom: 13px;
&:not(:disabled)[aria-invalid='true'] {
@include lightDark(color, #ff3231, #ff3757);
}

&.small {
padding-top: 8px;
padding-bottom: 8px;
&:disabled,
&:disabled::placeholder {
@include lightDark(color, rgba(88, 105, 110, 0.5), rgba(156, 172, 177, 0.4));
}
}

.label {
pointer-events: none;

position: absolute;
left: 13px;

&.default {
top: 13px;
&::placeholder {
@include lightDark(color, #58696e, #828b8e);
}

&.small {
top: 8px;
}
}

.fieldset {
min-width: 0;
margin: 0;
padding: 0 13px;
pointer-events: none;

position: absolute;
/* TODO: variables */
top: -6px;
bottom: 0;
left: 0;
right: 0;

border: 1px solid #0000003b;
border-radius: 4px;
}

.legend,
.message {
font-size: 12px;
font-weight: 400;
line-height: 1;
letter-spacing: 0.01em;
}

.legend {
opacity: 0;
max-width: 0.01px;
height: 1em;
padding: 0;

color: #313635;
}

.message {
margin: 4px 0 0 0;

color: #fc174d;
}

.block {
width: 100%;
}
16 changes: 16 additions & 0 deletions utils/vara-ui/src/components/textarea/textarea.stories.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Meta, StoryObj } from '@storybook/react';

import { Textarea } from './textarea';

type Type = typeof Textarea;
Expand All @@ -7,6 +8,21 @@ type Story = StoryObj<Type>;
const meta: Meta<Type> = {
title: 'Textarea',
component: Textarea,
args: {
label: '',
size: 'medium',
disabled: false,
block: false,
placeholder: 'Placeholder',
},
argTypes: {
disabled: { control: 'boolean' },
block: { control: 'boolean' },
size: {
options: ['small', 'medium', 'large'],
control: { type: 'select' },
},
},
};

const Default: Story = {
Expand Down
45 changes: 8 additions & 37 deletions utils/vara-ui/src/components/textarea/textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,16 @@
import { TextareaHTMLAttributes, ReactNode, useId, forwardRef } from 'react';
import cx from 'clsx';
import { TextareaHTMLAttributes, forwardRef } from 'react';

import { LabelContainer, LabelContainerProps } from '../label-container';
import styles from './textarea.module.scss';

type Props = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'id' | 'size'> & {
size?: 'default' | 'small';
label?: string;
error?: ReactNode;
block?: boolean;
};
type Props = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'id' | 'size'> & LabelContainerProps;

const Textarea = forwardRef<HTMLTextAreaElement, Props>(
({ className, label, error, size = 'default', rows = 5, placeholder = ' ', block, ...attrs }, ref) => {
const { disabled } = attrs;

const id = useId();

({ className, label, error, size, rows = 5, block, ...attrs }, ref) => {
return (
<div className={cx(styles.root, className, disabled && styles.disabled, block && styles.block)}>
<div className={styles.base}>
<textarea
rows={rows}
id={id}
className={cx(styles.textarea, styles[size], error && styles.error)}
placeholder={placeholder}
ref={ref}
{...attrs}
/>

{label && (
<label htmlFor={id} className={cx(styles.label, styles[size])}>
{label}
</label>
)}

<fieldset className={styles.fieldset}>
<legend className={cx(styles.legend, label && styles.legendLabel)}>{label}&#8203;</legend>
</fieldset>
</div>

{error && <p className={styles.message}>{error}</p>}
</div>
<LabelContainer className={className} label={label} error={error} size={size} block={block}>
<textarea rows={rows} className={styles.textarea} ref={ref} aria-invalid={Boolean(error)} {...attrs} />
</LabelContainer>
);
},
);
Expand Down

0 comments on commit b3a1566

Please sign in to comment.