лучшен выбор эмодзи для стикеров: добавлен модальный пикер эмодзи, оптимизирован список эмодзи, улучшен UX

This commit is contained in:
kazachilo 2025-03-17 15:51:10 +03:00
parent 4049792297
commit ce75907087
4 changed files with 179 additions and 9 deletions

View File

@ -0,0 +1,34 @@
.emojiContainer {
margin-bottom: var(--spacing-medium);
max-height: 300px;
overflow-y: auto;
}
.emojiGrid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 8px;
}
.emojiItem {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: 2px solid transparent;
border-radius: 8px;
cursor: pointer;
transition: border-color 0.2s;
font-size: 1.5rem;
}
.emojiItem:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.selected {
border-color: var(--color-primary);
background-color: rgba(var(--color-primary-rgb), 0.1);
}

View File

@ -0,0 +1,102 @@
import React, { useState } from 'react';
import styles from './NotificationModal.module.css';
import emojiStyles from './EmojiPickerModal.module.css';
interface EmojiPickerModalProps {
isVisible: boolean;
onCancel: () => void;
onSelect: (emoji: string) => void;
initialEmoji?: string;
}
const emojiList = [
// Смайлы и эмоции
'😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃', '😉', '😊',
'😇', '😍', '😘', '😗', '😚', '😙', '😋', '😛', '😜', '😝', '😐', '😑',
'😶', '😏', '😒', '🙄', '😬', '😌', '😔', '😪', '😴', '😷',
// Жесты и люди
'👍', '👎', '👌', '✌️', '👈', '👉', '👆', '👇', '👋', '✋', '👏', '🙌',
'👐', '🙏', '💪', '👂', '👃', '👀', '👄', '💋', '❤️', '💔', '💕', '💯',
// Животные
'🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', '🐨', '🐯', '🦁',
'🐮', '🐷', '🐸', '🐵', '🙈', '🙉', '🙊', '🐒', '🐔', '🐧', '🐦',
'🐤', '🐣', '🦆', '🦅', '🦉', '🐺', '🐗', '🐴', '🦄', '🐝',
'🐛', '🦋', '🐌', '🐞', '🐜', '🕷️', '🕸️',
// Еда и напитки
'🍏', '🍎', '🍐', '🍊', '🍋', '🍌', '🍉', '🍇', '🍓', '🍈', '🍒',
'🍑', '🍍', '🍅', '🍆', '🌽', '🍞', '🧀', '🍳', '🍗', '🍖', '🌭',
'🍔', '🍟', '🍕', '🍝', '🍜', '🍲', '🍛', '🍣', '🍱', '🍤', '🍙',
// Активности и объекты
'⚽', '🏀', '🏈', '⚾', '🎾', '🏐', '🏉', '🎱', '🏓', '🏸', '🏒', '🏑',
'⛳', '🏹', '🎣', '🏊', '🏄', '🏆', '🥇', '🥈', '🥉', '🏅',
// Символы
'❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕',
'💞', '💓', '💗', '💖', '💘', '💝', '💟', '☮️', '✝️', '☪️', '🕉️', '☸️',
'✡️', '🔯', '🕎', '☯️', '☦️', '🛐', '⛎', '♈', '♉', '♊', '♋', '♌', '♍',
'♎', '♏', '♐', '♑', '♒', '♓', '❌', '⭕', '🛑'
];
const EmojiPickerModal: React.FC<EmojiPickerModalProps> = ({
isVisible,
onCancel,
onSelect,
initialEmoji = '😊'
}) => {
const [selectedEmoji, setSelectedEmoji] = useState(initialEmoji);
if (!isVisible) return null;
const handleEmojiClick = (emoji: string) => {
setSelectedEmoji(emoji);
};
const handleApply = () => {
onSelect(selectedEmoji);
};
return (
<div className={styles.overlay}>
<div className={styles.modal}>
<div className={styles.header}>
<div className={styles.title}>Выберите эмодзи</div>
</div>
<div className={emojiStyles.emojiContainer}>
<div className={emojiStyles.emojiGrid}>
{emojiList.map((emoji, index) => (
<button
key={index}
className={`${emojiStyles.emojiItem} ${emoji === selectedEmoji ? emojiStyles.selected : ''}`}
onClick={() => handleEmojiClick(emoji)}
>
{emoji}
</button>
))}
</div>
</div>
<div className={styles.buttons}>
<button
className={`${styles.button} ${styles.secondaryButton}`}
onClick={onCancel}
>
Отмена
</button>
<button
className={`${styles.button} ${styles.primaryButton}`}
onClick={handleApply}
>
Применить
</button>
</div>
</div>
</div>
);
};
export default EmojiPickerModal;

View File

@ -102,13 +102,15 @@
padding: 2px;
}
.emojiInput {
.emojiButton {
width: 2.5rem;
height: 2.5rem;
background: none;
border: none;
color: white;
font-size: 1.2rem;
text-align: center;
cursor: pointer;
}
.actions {

View File

@ -5,6 +5,7 @@ import { stickerService } from '../services/stickerService';
import apiService from '../services/api';
import { GeneratedImage } from '../types/api';
import { getCurrentUserId } from '../constants/user';
import EmojiPickerModal from '../components/shared/EmojiPickerModal';
/**
* Транслитерирует кириллический текст в латиницу.
@ -46,6 +47,7 @@ function transliterate(text: string): string {
return result.substring(0, 30);
}
const CreateStickerPack: React.FC = () => {
const navigate = useNavigate();
const [title, setTitle] = useState('');
@ -56,6 +58,8 @@ const CreateStickerPack: React.FC = () => {
const [creating, setCreating] = useState(false);
const [error, setError] = useState<string | null>(null);
const titleInputRef = useRef<HTMLInputElement>(null);
const [isEmojiPickerVisible, setIsEmojiPickerVisible] = useState(false);
const [activeEmojiIndex, setActiveEmojiIndex] = useState<number | null>(null);
// Функция для сворачивания клавиатуры
const dismissKeyboard = () => {
@ -71,6 +75,28 @@ const CreateStickerPack: React.FC = () => {
dismissKeyboard();
}
};
// Функция для открытия пикера эмодзи
const openEmojiPicker = (index: number, e: React.MouseEvent) => {
e.stopPropagation();
setActiveEmojiIndex(index);
setIsEmojiPickerVisible(true);
};
// Функция для закрытия пикера эмодзи без выбора
const handleCancelEmojiPicker = () => {
setIsEmojiPickerVisible(false);
setActiveEmojiIndex(null);
};
// Функция для выбора эмодзи
const handleSelectEmoji = (emoji: string) => {
if (activeEmojiIndex !== null) {
handleEmojiChange(activeEmojiIndex, emoji);
}
setIsEmojiPickerVisible(false);
setActiveEmojiIndex(null);
};
// Загрузка доступных изображений
useEffect(() => {
@ -230,14 +256,12 @@ const CreateStickerPack: React.FC = () => {
{isSelected && (
<div className={styles.emojiSelector}>
<input
type="text"
value={emojis[selectedIndex]}
onChange={(e) => handleEmojiChange(selectedIndex, e.target.value)}
className={styles.emojiInput}
maxLength={2}
onClick={(e) => e.stopPropagation()}
/>
<button
className={styles.emojiButton}
onClick={(e) => openEmojiPicker(selectedIndex, e)}
>
{emojis[selectedIndex] || '😊'}
</button>
</div>
)}
</div>
@ -259,6 +283,14 @@ const CreateStickerPack: React.FC = () => {
</button>
</div>
</div>
{/* Модальное окно выбора эмодзи */}
<EmojiPickerModal
isVisible={isEmojiPickerVisible && activeEmojiIndex !== null}
onCancel={handleCancelEmojiPicker}
onSelect={handleSelectEmoji}
initialEmoji={activeEmojiIndex !== null ? (emojis[activeEmojiIndex] || '😊') : '😊'}
/>
</div>
);
};