Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display the same emojis on all platforms #84

Merged
merged 3 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@types/react-dom": "^17.0.14",
"clsx": "^1.1.1",
"date-fns": "^2.28.0",
"emoji-picker-react": "^3.5.1",
"emoji-picker-react": "4.4.7",
"firebase": "^9.8.1",
"firestore-jest-mock": "^0.17.0",
"framer-motion": "^6.3.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ function AnswerTableRow({ time, selectedIcon, text }: AnswerTableRowProps) {
return (
<div className="grid grid-cols-6 p-3 my-2 mx-auto max-w-[800px] bg-white rounded-md shadow-sm">
<div className="col-span-2">{time}</div>
<div>
<Emoji symbol={selectedIcon} />
<div className="flex items-center">
<Emoji unified={selectedIcon} size={22} />
</div>
<div className="col-span-3 text-left break-words">{text || '-'}</div>
</div>
Expand Down
18 changes: 15 additions & 3 deletions src/features/surveys/components/BarChart/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
ResponsiveContainer,
} from 'recharts';

import { CustomTooltip } from './CustomTooltip';
import { CustomXAxisTick } from './CustomXAxisTick';

interface BarChartProps {
data: BarChartData[];
}
Expand Down Expand Up @@ -44,14 +47,23 @@ export default function BarChart({ data }: BarChartProps) {
bottom: 5,
}}
>
<XAxis dataKey="name" />
<XAxis
dataKey="name"
interval={0}
tick={(props) => <CustomXAxisTick {...props} />}
/>

<YAxis
domain={[0, getMaxValue()]}
dataKey="value"
allowDecimals={false}
/>
<Tooltip cursor={{ fill: '#eeeeee' }} />
<Bar dataKey="value" fill="#8884d8">
<Tooltip
wrapperStyle={{ outline: 'none' }}
cursor={false}
content={(props) => <CustomTooltip {...props} />}
/>
<Bar dataKey="value" fill="#8884d8" radius={[8, 8, 0, 0]}>
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index]} />
))}
Expand Down
23 changes: 23 additions & 0 deletions src/features/surveys/components/BarChart/CustomTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TooltipProps } from 'recharts';
import {
ValueType,
NameType,
} from 'recharts/types/component/DefaultTooltipContent';
import Emoji from '../Emoji/Emoji';

export const CustomTooltip = ({
active,
payload,
label,
}: TooltipProps<ValueType, NameType>) => {
if (active) {
return (
<div className=" flex flex-col items-center p-4 bg-white rounded-md border border-zinc-200 shadow-md">
<Emoji unified={label} size={22} />
<p className="mt-2"> value: {payload?.[0].value}</p>
</div>
);
}

return null;
Ryczko marked this conversation as resolved.
Show resolved Hide resolved
};
19 changes: 19 additions & 0 deletions src/features/surveys/components/BarChart/CustomXAxisTick.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Emoji from '../Emoji/Emoji';

interface CustomXAxisTickProps {
x: number;
y: number;
payload: {
value: string;
};
}

export const CustomXAxisTick = ({ x, y, payload }: CustomXAxisTickProps) => {
return (
<g transform={`translate(${x - 10},${y})`}>
<foreignObject width={20} height={20}>
<Emoji unified={payload.value} size={20} />
</foreignObject>
</g>
);
};
28 changes: 16 additions & 12 deletions src/features/surveys/components/Emoji/Emoji.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import dynamic from 'next/dynamic';
import { EMOJI_STYLE } from 'src/shared/constants/emojisConfig';

import { Emoji as StaticLibEmoji } from 'emoji-picker-react';

const LibEmoji = dynamic<React.ComponentProps<typeof StaticLibEmoji>>(
() => import('emoji-picker-react').then((mod) => mod.Emoji),
{
ssr: false,
}
);

interface EmojiProps {
symbol: string;
label?: string;
unified: string;
size?: number;
}

export default function Emoji({ symbol, label }: EmojiProps) {
return (
<span
role="img"
aria-label={label ? label : ''}
aria-hidden={label ? 'false' : 'true'}
>
{symbol}
</span>
);
export default function Emoji({ unified, size = 32 }: EmojiProps) {
return <LibEmoji unified={unified} emojiStyle={EMOJI_STYLE} size={size} />;
}
15 changes: 5 additions & 10 deletions src/features/surveys/components/EmojiButton/EmojiButton.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
import React from 'react';
import Emoji from '../Emoji/Emoji';

interface EmojiButtonProps {
icon: string;
selected?: boolean;
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
onClick: (icon: string) => void;
}

function EmojiButton({
icon,
onClick,
selected = false,
}: EmojiButtonProps & React.HTMLProps<HTMLButtonElement>) {
function EmojiButton({ icon, onClick, selected = false }: EmojiButtonProps) {
return (
<button
className={`rounded-lg border-4 border-transparent bg-white p-3 text-3xl shadow duration-100 ${
className={`rounded-lg border-4 border-transparent bg-white p-3 flex justify-center items-center shadow duration-100 ${
selected ? 'scale-90 border-slate-300' : ''
}`}
onClick={onClick}
onClick={() => onClick(icon)}
>
<Emoji symbol={icon} />
<Emoji unified={icon} />
</button>
);
}
Expand Down
69 changes: 52 additions & 17 deletions src/features/surveys/components/EmojiPicker/EmojiPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { useRef, useState } from 'react';
import { useCloseComponent } from '../../../../shared/hooks/useCloseComponent';

import dynamic from 'next/dynamic';
import Emoji from '../Emoji/Emoji';
import Loader from '../../../../shared/components/Loader/Loader';
import { Categories, EmojiClickData } from 'emoji-picker-react';
import { EMOJI_STYLE } from 'src/shared/constants/emojisConfig';
import Emoji from '../Emoji/Emoji';

const Picker = dynamic(() => import('emoji-picker-react'), {
ssr: false,
loading: () => <Loader isLoading={true} />,
Expand All @@ -16,25 +19,26 @@ interface EmojiPickerProps {
}

function EmojiPicker({ defaultEmote, index, onEmotePick }: EmojiPickerProps) {
const [chosenEmoji, setChosenEmoji] = useState(null);
const [chosenEmoji, setChosenEmoji] = useState<EmojiClickData>();
const [displayPicker, setDisplayPicker] = useState(false);

const wrapperRef = useRef<HTMLDivElement>(null);

useCloseComponent(wrapperRef, () => setDisplayPicker(false));

const onEmojiClick = (_event: unknown, emojiObject: { emoji: string }) => {
const onEmojiClick = (emojiObject: EmojiClickData) => {
setChosenEmoji(emojiObject);
onEmotePick(index, emojiObject.emoji as string);
onEmotePick(index, emojiObject.unified);
setDisplayPicker(!displayPicker);
};

return (
<div ref={wrapperRef}>
<button
className="p-3 w-16 text-3xl bg-white rounded-lg shadow transition hover:scale-95 label-text"
className="flex justify-center items-center p-3 w-16 text-3xl bg-white rounded-lg shadow transition hover:scale-95 label-text"
onClick={() => setDisplayPicker(!displayPicker)}
>
<Emoji symbol={chosenEmoji?.emoji || defaultEmote} />
<Emoji unified={chosenEmoji?.unified || defaultEmote} />
</button>

{displayPicker && (
Expand All @@ -46,19 +50,50 @@ function EmojiPicker({ defaultEmote, index, onEmotePick }: EmojiPickerProps) {
{displayPicker && (
<div className="flex overflow-hidden fixed top-1/2 left-1/2 z-20 justify-center items-center w-[400px] max-w-[90%] h-[400px] max-h-[90%] bg-white rounded-md -translate-x-1/2 -translate-y-1/2">
<Picker
native
onEmojiClick={onEmojiClick}
disableAutoFocus
disableSearchBar
disableSkinTonePicker
groupVisibility={{
flags: false,
symbols: false,
}}
pickerStyle={{
width: '400px',
height: '400px',
autoFocusSearch={false}
emojiStyle={EMOJI_STYLE}
searchDisabled
skinTonesDisabled
previewConfig={{
showPreview: false,
}}
categories={[
{
category: Categories.SUGGESTED,
name: 'Frequently Used',
},
{
category: Categories.SMILEYS_PEOPLE,
name: 'Smileys & People',
},
{
category: Categories.ANIMALS_NATURE,
name: 'Animals & Nature',
},
{
category: Categories.FOOD_DRINK,
name: 'Food & Drink',
},
{
category: Categories.TRAVEL_PLACES,
name: 'Travel & Places',
},
{
category: Categories.ACTIVITIES,
name: 'Activities',
},
{
category: Categories.OBJECTS,
name: 'Objects',
},
{
category: Categories.FLAGS,
name: 'Flags',
},
]}
width={400}
height={400}
/>
</div>
)}
Expand Down
8 changes: 7 additions & 1 deletion src/features/surveys/managers/createSurveyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ import useCopyToClipboard from 'src/shared/hooks/useCopyToClipboard';

export const useCreateSurveyManager = () => {
const [title, setTitle] = useState('');
const [pack, setPack] = useState(['😃', '🙂', '🙁', '😡']);
const [pack, setPack] = useState([]);

const { user } = useApplicationContext();
const [buttonDisable, setButtonDisable] = useState(false);

const router = useRouter();
const [, copy] = useCopyToClipboard();

// Move to useState initial value when bug in emoji library will be solved:
// https://github.com/ealush/emoji-picker-react/issues/329
useEffect(() => {
setPack(['1f603', '1f642', '1f641', '1f621']);
}, []);

const handleChangeTitle = (e: React.ChangeEvent<HTMLInputElement>) => {
setTitle(e.target.value);
};
Expand Down
5 changes: 2 additions & 3 deletions src/features/surveys/managers/surveyAnswerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ export const useSurveyAnswerManager = () => {
}
}, [surveyId, getSurveyData]);

const handleIconClick = (e: React.MouseEvent<HTMLButtonElement>) => {
const target = e.target as HTMLElement;
setSelectedIcon(target.textContent);
const handleIconClick = (icon: string) => {
setSelectedIcon(icon);
};

const handleSave = async () => {
Expand Down
3 changes: 3 additions & 0 deletions src/shared/constants/emojisConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { EmojiStyle } from 'emoji-picker-react';

export const EMOJI_STYLE = EmojiStyle.APPLE;