Files
twenty/packages/twenty-chrome-extension/src/options/modules/ui/input/components/TextInput.tsx
Raphaël Bosi c6e5bab4e9 Replace hotkey scopes by focus stack (Part 4 - Inputs) (#12933)
# Replace hotkey scopes by focus stack (Part 4 - Inputs)

This PR is the 4th part of a refactoring aiming to deprecate the hotkey
scopes api in favor of the new focus stack api which is more robust.
Part 1: https://github.com/twentyhq/twenty/pull/12673
Part 2: https://github.com/twentyhq/twenty/pull/12798
Part 3: https://github.com/twentyhq/twenty/pull/12910

In this part, I refactored all inputs in the app so that each input has
a unique id which can be used to track the focused element.
2025-07-07 15:42:12 +02:00

88 lines
2.0 KiB
TypeScript

import styled from '@emotion/styled';
import React, { useId } from 'react';
interface TextInputProps {
label?: string;
value: string;
onChange: (value: string) => void;
fullWidth?: boolean;
error?: string;
placeholder?: string;
icon?: React.ReactNode;
}
const StyledContainer = styled.div<{ fullWidth?: boolean }>`
display: flex;
flex-direction: column;
width: ${({ fullWidth }) => (fullWidth ? `100%` : 'auto')};
margin-bottom: ${({ theme }) => theme.spacing(4)};
`;
const StyledLabel = styled.label`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: ${({ theme }) => theme.spacing(1)};
text-transform: uppercase;
`;
const StyledInputContainer = styled.div`
display: flex;
align-items: center;
border: 1px solid ${({ theme }) => theme.color.gray30};
border-radius: 4px;
padding: 8px;
`;
const StyledIcon = styled.span`
margin-right: 8px;
`;
const StyledInput = styled.input`
flex: 1;
border: none;
outline: none;
font-size: 14px;
&::placeholder {
color: ${({ theme }) => theme.font.color.light};
}
`;
const StyledErrorHelper = styled.div`
color: ${({ theme }) => theme.color.red};
font-size: 12px;
padding: 5px 0;
`;
const TextInput: React.FC<TextInputProps> = ({
label,
value,
onChange,
fullWidth,
error,
placeholder,
icon,
}) => {
const instanceId = useId();
return (
<StyledContainer fullWidth={fullWidth}>
{label && <StyledLabel htmlFor={instanceId}>{label}</StyledLabel>}
<StyledInputContainer>
{icon && <StyledIcon>{icon}</StyledIcon>}
<StyledInput
id={instanceId}
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
/>
</StyledInputContainer>
{error && <StyledErrorHelper>{error}</StyledErrorHelper>}
</StyledContainer>
);
};
export { TextInput };