Skip to content

Commit

Permalink
react/Text____
Browse files Browse the repository at this point in the history
  • Loading branch information
cobycloud committed Dec 12, 2024
1 parent dcb6b19 commit fcb27e0
Show file tree
Hide file tree
Showing 9 changed files with 393 additions and 0 deletions.
34 changes: 34 additions & 0 deletions libs/react/src/components/TextField/TextField.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<style scoped>
.text-field {
display: flex;
flex-direction: column;
}

.input {
padding: var(--input-padding, 0.5rem);
border: 1px solid var(--input-border, #ccc);
border-radius: var(--input-radius, 4px);
transition: border-color 0.3s, box-shadow 0.3s;
}

.input:focus {
outline: none;
border-color: var(--input-focus-border, #007bff);
box-shadow: 0 0 0 3px var(--input-focus-shadow, rgba(0, 123, 255, 0.25));
}

.input.error {
border-color: var(--input-error-border, #dc3545);
}

.input[disabled] {
background-color: var(--input-disabled-bg, #e9ecef);
cursor: not-allowed;
}

.helper-text {
margin-top: 0.25rem;
font-size: var(--helper-text-size, 0.875rem);
color: var(--helper-text-color, #6c757d);
}
</style>
68 changes: 68 additions & 0 deletions libs/react/src/components/TextField/TextField.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import { Meta, Story } from '@storybook/react';
import TextField, { TextFieldProps } from './TextField';

export default {
title: 'component/Forms/TextField',
component: TextField,
tags: ['autodocs'],
} as Meta;

const Template: Story<TextFieldProps> = (args) => <TextField {...args} />;

export const Default = Template.bind({});
Default.args = {
value: '',
onChange: (value: string) => console.log(`Value: ${value}`),
};

export const Focused = Template.bind({});
Focused.args = {
value: '',
onChange: (value: string) => console.log(`Value: ${value}`),
};
Focused.parameters = {
pseudo: { focus: true },
};

export const Filled = Template.bind({});
Filled.args = {
value: 'Sample text',
onChange: (value: string) => console.log(`Value: ${value}`),
};

export const Error = Template.bind({});
Error.args = {
value: '',
onChange: (value: string) => console.log(`Value: ${value}`),
error: true,
helperText: 'This field has an error',
};

export const Disabled = Template.bind({});
Disabled.args = {
value: '',
onChange: (value: string) => console.log(`Value: ${value}`),
disabled: true,
};

export const ReadOnly = Template.bind({});
ReadOnly.args = {
value: 'Read-only text',
onChange: (value: string) => console.log(`Value: ${value}`),
readOnly: true,
};

export const WithHelperText = Template.bind({});
WithHelperText.args = {
value: '',
onChange: (value: string) => console.log(`Value: ${value}`),
helperText: 'This is a helper text',
};

export const WithPlaceholder = Template.bind({});
WithPlaceholder.args = {
value: '',
onChange: (value: string) => console.log(`Value: ${value}`),
placeholder: 'Enter text here...',
};
41 changes: 41 additions & 0 deletions libs/react/src/components/TextField/TextField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import './TextField.css';

interface TextFieldProps {
value: string;
onChange: (value: string) => void;
placeholder?: string;
disabled?: boolean;
readOnly?: boolean;
error?: boolean;
helperText?: string;
}

const TextField: React.FC<TextFieldProps> = ({ value, onChange, placeholder, disabled, readOnly, error, helperText }) => {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!readOnly && !disabled) {
onChange(event.target.value);
}
};

return (
<div className="text-field">
<input
type="text"
className={`input ${error ? 'error' : ''}`}
value={value}
onChange={handleChange}
placeholder={placeholder}
disabled={disabled}
readOnly={readOnly}
aria-invalid={error}
aria-readonly={readOnly}
aria-disabled={disabled}
aria-describedby={helperText ? 'helper-text' : undefined}
/>
{helperText && <span id="helper-text" className="helper-text">{helperText}</span>}
</div>
);
};

export default TextField;
46 changes: 46 additions & 0 deletions libs/react/src/components/TextTool/TextTool.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<style scoped>
.text-tool {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px;
border: var(--text-tool-border, 1px solid #ccc);
border-radius: var(--text-tool-border-radius, 4px);
background-color: var(--text-tool-background-color, #f9f9f9);
}

.text-tool.active {
background-color: var(--text-tool-active-background-color, #e0f7fa);
}

textarea {
width: 100%;
height: 60px;
resize: none;
font-family: inherit;
border: var(--textarea-border, 1px solid #ccc);
border-radius: var(--textarea-border-radius, 4px);
}

select, input[type='number'], input[type='color'] {
width: 100%;
padding: 5px;
border: var(--input-border, 1px solid #ccc);
border-radius: var(--input-border-radius, 4px);
}

button {
padding: 6px 12px;
border: none;
border-radius: var(--button-border-radius, 4px);
background-color: var(--button-background-color, #007bff);
color: var(--button-text-color, #fff);
cursor: pointer;
transition: background-color 0.3s ease;
}

button:disabled {
background-color: var(--button-disabled-background-color, #d3d3d3);
cursor: not-allowed;
}
</style>
33 changes: 33 additions & 0 deletions libs/react/src/components/TextTool/TextTool.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { Meta, Story } from '@storybook/react';
import TextTool, { TextToolProps } from './TextTool';

export default {
title: 'component/Drawing/TextTool',
component: TextTool,
tags: ['autodocs'],
} as Meta;

const Template: Story<TextToolProps> = (args) => <TextTool {...args} />;

export const Default = Template.bind({});
Default.args = {
active: false,
onAddText: (text, options) => console.log(`Added text: ${text} with options`, options),
};

export const Active = Template.bind({});
Active.args = {
...Default.args,
active: true,
};

export const TextAdded = Template.bind({});
TextAdded.args = {
...Active.args,
};

export const TextEdited = Template.bind({});
TextEdited.args = {
...Active.args,
};
76 changes: 76 additions & 0 deletions libs/react/src/components/TextTool/TextTool.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from 'react';
import './TextTool.css';

interface TextToolProps {
active: boolean;
onAddText: (text: string, options: TextOptions) => void;
}

interface TextOptions {
fontStyle: string;
fontSize: number;
color: string;
alignment: 'left' | 'center' | 'right';
}

const TextTool: React.FC<TextToolProps> = ({ active, onAddText }) => {
const [text, setText] = useState<string>('');
const [fontStyle, setFontStyle] = useState<string>('Arial');
const [fontSize, setFontSize] = useState<number>(16);
const [color, setColor] = useState<string>('#000000');
const [alignment, setAlignment] = useState<'left' | 'center' | 'right'>('left');

const handleAddText = () => {
if (active && text) {
onAddText(text, { fontStyle, fontSize, color, alignment });
}
};

return (
<div className={`text-tool ${active ? 'active' : ''}`}>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Enter text here"
aria-label="Text input"
/>
<select
value={fontStyle}
onChange={(e) => setFontStyle(e.target.value)}
aria-label="Font style"
>
<option value="Arial">Arial</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Courier New">Courier New</option>
</select>
<input
type="number"
value={fontSize}
onChange={(e) => setFontSize(Number(e.target.value))}
min="10"
max="100"
aria-label="Font size"
/>
<input
type="color"
value={color}
onChange={(e) => setColor(e.target.value)}
aria-label="Font color"
/>
<select
value={alignment}
onChange={(e) => setAlignment(e.target.value as 'left' | 'center' | 'right')}
aria-label="Text alignment"
>
<option value="left">Left</option>
<option value="center">Center</option>
<option value="right">Right</option>
</select>
<button onClick={handleAddText} disabled={!active || !text} aria-label="Add text to canvas">
Add Text
</button>
</div>
);
};

export default TextTool;
42 changes: 42 additions & 0 deletions libs/react/src/components/Textarea/Textarea.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<style scoped>
.custom-textarea {
width: 100%;
padding: 8px;
border: 1px solid var(--input-border-color);
background-color: var(--background-color);
color: var(--text-color);
font-size: 16px;
resize: vertical;
}

.custom-textarea:disabled {
background-color: var(--disabled-background-color);
color: var(--disabled-text-color);
border-color: var(--disabled-border-color);
opacity: 0.5;
}

@media (max-width: 600px) {
.custom-textarea {
font-size: 14px;
}
}

@media (min-width: 601px) and (max-width: 768px) {
.custom-textarea {
font-size: 15px;
}
}

@media (min-width: 769px) and (max-width: 1024px) {
.custom-textarea {
font-size: 16px;
}
}

@media (min-width: 1025px) {
.custom-textarea {
font-size: 16px;
}
}
</style>
24 changes: 24 additions & 0 deletions libs/react/src/components/Textarea/Textarea.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { Meta, Story } from '@storybook/react';
import Textarea from './Textarea';

export default {
title: 'component/Forms/Textarea',
component: Textarea,
tags: ['autodocs'],
} as Meta;

const Template: Story = (args) => <Textarea {...args} />;

export const Default = Template.bind({});
Default.args = {
placeholder: 'Enter text here...',
value: '',
onChange: (value: string) => console.log(`Textarea value: ${value}`),
};

export const Disabled = Template.bind({});
Disabled.args = {
...Default.args,
disabled: true,
};
Loading

0 comments on commit fcb27e0

Please sign in to comment.