EthanHealy01 8f32082145
Feature/v2/all tools sidebar (#4151)
# Description of Changes

- Added the all tools sidebar
- Added a TextFit component that shrinks text to fit containers
- Added a TopToolIcon on the nav, that animates down to give users
feedback on what tool is selected
- Added the baseToolRegistry, to replace the old pattern of listing
tools, allowing us to clean up the ToolRegistry code
- Fixed Mantine light/dark theme race condition 
- General styling tweaks

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
2025-08-19 13:31:09 +01:00

105 lines
2.9 KiB
TypeScript

import React, { forwardRef } from 'react';
import { useMantineColorScheme } from '@mantine/core';
import styles from './textInput/TextInput.module.css';
/**
* Props for the TextInput component
*/
export interface TextInputProps {
/** The input value (required) */
value: string;
/** Callback when input value changes (required) */
onChange: (value: string) => void;
/** Placeholder text */
placeholder?: string;
/** Optional left icon */
icon?: React.ReactNode;
/** Whether to show the clear button (default: true) */
showClearButton?: boolean;
/** Custom clear handler (defaults to setting value to empty string) */
onClear?: () => void;
/** Additional CSS classes */
className?: string;
/** Additional inline styles */
style?: React.CSSProperties;
/** HTML autocomplete attribute (default: 'off') */
autoComplete?: string;
/** Whether the input is disabled (default: false) */
disabled?: boolean;
/** Whether the input is read-only (default: false) */
readOnly?: boolean;
/** Accessibility label */
'aria-label'?: string;
}
export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(({
value,
onChange,
placeholder,
icon,
showClearButton = true,
onClear,
className = '',
style,
autoComplete = 'off',
disabled = false,
readOnly = false,
'aria-label': ariaLabel,
...props
}, ref) => {
const { colorScheme } = useMantineColorScheme();
const handleClear = () => {
if (onClear) {
onClear();
} else {
onChange('');
}
};
const shouldShowClearButton = showClearButton && value.trim().length > 0 && !disabled && !readOnly;
return (
<div className={`${styles.container} ${className}`} style={style}>
{icon && (
<span
className={styles.icon}
style={{ color: colorScheme === 'dark' ? '#FFFFFF' : '#6B7382' }}
>
{icon}
</span>
)}
<input
ref={ref}
type="text"
placeholder={placeholder}
value={value}
onChange={(e) => onChange(e.currentTarget.value)}
autoComplete={autoComplete}
className={styles.input}
disabled={disabled}
readOnly={readOnly}
aria-label={ariaLabel}
style={{
backgroundColor: colorScheme === 'dark' ? '#4B525A' : '#FFFFFF',
color: colorScheme === 'dark' ? '#FFFFFF' : '#6B7382',
paddingRight: shouldShowClearButton ? '40px' : '12px',
paddingLeft: icon ? '40px' : '12px',
}}
{...props}
/>
{shouldShowClearButton && (
<button
type="button"
className={styles.clearButton}
onClick={handleClear}
style={{ color: colorScheme === 'dark' ? '#FFFFFF' : '#6B7382' }}
aria-label="Clear input"
>
<span className="material-symbols-rounded">close</span>
</button>
)}
</div>
);
});