diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index f3b6525f9..6fa1ccb9a 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -26,6 +26,7 @@ "plugin:storybook/recommended" ], "rules": { + "react/prop-types": "off", "@typescript-eslint/consistent-type-imports": "error", "jsx-a11y/click-events-have-key-events": "off", "jsx-a11y/no-noninteractive-element-interactions": "off", diff --git a/frontend/.storybook/preview.tsx b/frontend/.storybook/preview.tsx index d8c7918cb..458702f32 100644 --- a/frontend/.storybook/preview.tsx +++ b/frontend/.storybook/preview.tsx @@ -2,6 +2,7 @@ import { Global, ThemeProvider } from '@emotion/react'; import type { Preview } from '@storybook/react'; import React from 'react'; +import ToastProvider from '../src/contexts/ToastProvider'; import globalStyles from '../src/styles/global'; import theme from '../src/styles/theme'; @@ -21,8 +22,10 @@ export default preview; export const decorators = [ (Story) => ( - - + + + + ), ]; diff --git a/frontend/legacy/components/AllSchedules/AllSchdules.utils.ts b/frontend/legacy/components/AllSchedules/AllSchdules.utils.ts index bf6e8781f..d1b16f277 100644 --- a/frontend/legacy/components/AllSchedules/AllSchdules.utils.ts +++ b/frontend/legacy/components/AllSchedules/AllSchdules.utils.ts @@ -1,8 +1,10 @@ +import { DAY_OF_WEEK_KR } from '../../../src/constants/date'; + export const formatDate = (dateString: string) => { const currentDateObj = new Date(dateString); const currentMonth = currentDateObj.getMonth() + 1; const currentDay = currentDateObj.getDate(); - const dayOfWeek = ['일', '월', '화', '수', '목', '금', '토'][currentDateObj.getDay()]; + const dayOfWeek = DAY_OF_WEEK_KR[currentDateObj.getDay()]; return { dayOfWeek, diff --git a/frontend/src/assets/images/logo.svg b/frontend/src/assets/images/logo.svg deleted file mode 100644 index 051997a82..000000000 --- a/frontend/src/assets/images/logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/frontend/src/assets/images/logo.webp b/frontend/src/assets/images/logo.webp new file mode 100644 index 000000000..ba8832aa2 Binary files /dev/null and b/frontend/src/assets/images/logo.webp differ diff --git a/frontend/src/assets/images/logoSunglass.svg b/frontend/src/assets/images/logoSunglass.svg deleted file mode 100644 index 85c0f5bf6..000000000 --- a/frontend/src/assets/images/logoSunglass.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/src/assets/images/logoSunglass.webp b/frontend/src/assets/images/logoSunglass.webp new file mode 100644 index 000000000..71c6ad55f Binary files /dev/null and b/frontend/src/assets/images/logoSunglass.webp differ diff --git a/frontend/src/components/MeetingCalendar/Date/Date.utils.ts b/frontend/src/components/MeetingCalendar/Date/Date.utils.ts index 93a14dad8..be2b39423 100644 --- a/frontend/src/components/MeetingCalendar/Date/Date.utils.ts +++ b/frontend/src/components/MeetingCalendar/Date/Date.utils.ts @@ -3,6 +3,7 @@ import { getHolidayNames } from '@hyunbinseo/holidays-kr'; import { getDate, getDay, getFullDate } from '@utils/date'; import CALENDAR_PROPERTIES from '@constants/calendar'; +import { DAY_OF_WEEK_KR } from '@constants/date'; export const getDateInfo = (targetDate: Date, today: Date) => { const targetDateNumber = getDate(targetDate); @@ -28,6 +29,7 @@ export const getDateInfo = (targetDate: Date, today: Date) => { return { date: targetDateNumber, targetFullDate, + targetDayOfWeekKR: DAY_OF_WEEK_KR[targetDayOfWeek], isHoliday, isToday, isSunday, diff --git a/frontend/src/components/MeetingConfirmCalendar/Header/Header.tsx b/frontend/src/components/MeetingConfirmCalendar/Header/index.tsx similarity index 82% rename from frontend/src/components/MeetingConfirmCalendar/Header/Header.tsx rename to frontend/src/components/MeetingConfirmCalendar/Header/index.tsx index e9bae83d5..82019f1d1 100644 --- a/frontend/src/components/MeetingConfirmCalendar/Header/Header.tsx +++ b/frontend/src/components/MeetingConfirmCalendar/Header/index.tsx @@ -1,3 +1,5 @@ +import type { PropsWithChildren } from 'react'; + import { s_monthNavigation, s_monthNavigationContainer, @@ -23,7 +25,10 @@ export default function Header({ moveToNextMonth, moveToPrevMonth, isCurrentMonth, -}: HeaderProps) { + children, +}: PropsWithChildren) { + const yearMonthText = `${currentYear}년 ${currentMonth + 1}월`; + return (
@@ -35,9 +40,9 @@ export default function Header({ > {'<'} - - - {currentYear}년 {currentMonth + 1}월 + + {yearMonthText} + {children} +
) : (
); diff --git a/frontend/src/components/MeetingConfirmCalendar/SingleDate/SingleDate.tsx b/frontend/src/components/MeetingConfirmCalendar/SingleDate/index.tsx similarity index 100% rename from frontend/src/components/MeetingConfirmCalendar/SingleDate/SingleDate.tsx rename to frontend/src/components/MeetingConfirmCalendar/SingleDate/index.tsx diff --git a/frontend/src/components/MeetingConfirmCalendar/Viewer/index.tsx b/frontend/src/components/MeetingConfirmCalendar/Viewer/index.tsx index 94bde60b5..34c8b18f2 100644 --- a/frontend/src/components/MeetingConfirmCalendar/Viewer/index.tsx +++ b/frontend/src/components/MeetingConfirmCalendar/Viewer/index.tsx @@ -15,17 +15,19 @@ import { import { Button } from '@components/_common/Buttons/Button'; import TabButton from '@components/_common/Buttons/TabButton'; import Calendar from '@components/_common/Calendar'; +import ScreenReaderOnly from '@components/_common/ScreenReaderOnly'; import useRouter from '@hooks/useRouter/useRouter'; import { useGetSchedules } from '@stores/servers/schedule/queries'; -import { getFullDate } from '@utils/date'; +import { formatAriaTab } from '@utils/a11y'; +import { getFullDate, hasSelectableDaysInMonth } from '@utils/date'; import Check from '@assets/images/attendeeCheck.svg'; import Pen from '@assets/images/pen.svg'; -import Header from '../Header/Header'; +import Header from '../Header'; import SingleDateViewer from '../SingleDate/SingleDateViewer'; import WeekDays from '../WeekDays'; @@ -84,6 +86,7 @@ export default function Viewer({ tabButtonVariants="outlinedFloating" onClick={() => setSelectedAttendee('')} isActive={selectedAttendee === ''} + aria-label={formatAriaTab('전체', selectedAttendee === '')} > {selectedAttendee === '' && } 전체 @@ -94,6 +97,7 @@ export default function Viewer({ tabButtonVariants="outlinedFloating" onClick={() => setSelectedAttendee(attendee)} isActive={selectedAttendee === attendee} + aria-label={formatAriaTab(attendee, selectedAttendee === attendee)} > {selectedAttendee === attendee && } {attendee} @@ -102,8 +106,22 @@ export default function Viewer({ -
} /> + ( +
+ + {hasSelectableDaysInMonth( + props.currentMonth, + meetingSchedules.schedules.map(({ date }) => date), + ) + ? '선택 가능한 날이 있습니다.' + : '선택 가능한 날이 없습니다.'} + +
+ )} + /> } /> + ( )} - diff --git a/frontend/src/components/MeetingConfirmCalendar/WeekDays.tsx b/frontend/src/components/MeetingConfirmCalendar/WeekDays.tsx index ef0a1b45b..9bda984c7 100644 --- a/frontend/src/components/MeetingConfirmCalendar/WeekDays.tsx +++ b/frontend/src/components/MeetingConfirmCalendar/WeekDays.tsx @@ -11,7 +11,7 @@ interface WeekDaysProps { export default function WeekDays({ weekdays }: WeekDaysProps) { return ( -
+
{weekdays.map((day, index) => (
{day} diff --git a/frontend/src/components/Schedules/ScheduleViewer/SchedulesViewer.tsx b/frontend/src/components/Schedules/ScheduleViewer/SchedulesViewer.tsx index 2bc93a980..4e8c728f7 100644 --- a/frontend/src/components/Schedules/ScheduleViewer/SchedulesViewer.tsx +++ b/frontend/src/components/Schedules/ScheduleViewer/SchedulesViewer.tsx @@ -11,6 +11,8 @@ import TabButton from '@components/_common/Buttons/TabButton'; import useRouter from '@hooks/useRouter/useRouter'; import useSelectSchedule from '@hooks/useSelectSchedule/useSelectSchedule'; +import { formatAriaTab } from '@utils/a11y'; + import Check from '@assets/images/attendeeCheck.svg'; import Pen from '@assets/images/pen.svg'; @@ -73,6 +75,7 @@ export default function SchedulesViewer({ tabButtonVariants="outlinedFloating" onClick={() => handleAttendeeChange('')} isActive={selectedAttendee === ''} + aria-label={formatAriaTab('전체', selectedAttendee === '')} > {selectedAttendee === '' && } 전체 @@ -83,6 +86,7 @@ export default function SchedulesViewer({ tabButtonVariants="outlinedFloating" onClick={() => handleAttendeeChange(attendee)} isActive={selectedAttendee === attendee} + aria-label={formatAriaTab(attendee, selectedAttendee === attendee)} > {selectedAttendee === attendee && } {attendee} @@ -127,7 +131,12 @@ export default function SchedulesViewer({ )}
- diff --git a/frontend/src/components/Schedules/Schedules.util.ts b/frontend/src/components/Schedules/Schedules.util.ts index 0b3aeb462..65a3d3d35 100644 --- a/frontend/src/components/Schedules/Schedules.util.ts +++ b/frontend/src/components/Schedules/Schedules.util.ts @@ -6,11 +6,13 @@ import type { } from 'types/schedule'; import type { TooltipPosition } from 'types/tooltip'; +import { DAY_OF_WEEK_KR } from '@constants/date'; + export const formatDate = (dateString: string) => { const currentDateObj = new Date(dateString); const currentMonth = currentDateObj.getMonth() + 1; const currentDay = currentDateObj.getDate(); - const dayOfWeek = ['일', '월', '화', '수', '목', '금', '토'][currentDateObj.getDay()]; + const dayOfWeek = DAY_OF_WEEK_KR[currentDateObj.getDay()]; return { dayOfWeek, diff --git a/frontend/src/components/_common/Buttons/BackButton/index.tsx b/frontend/src/components/_common/Buttons/BackButton/index.tsx index 024cb3d77..65f9aa007 100644 --- a/frontend/src/components/_common/Buttons/BackButton/index.tsx +++ b/frontend/src/components/_common/Buttons/BackButton/index.tsx @@ -17,7 +17,7 @@ export default function BackButton({ path }: BackButtonProps) { }; return ( - ); diff --git a/frontend/src/components/_common/Buttons/Button/index.tsx b/frontend/src/components/_common/Buttons/Button/index.tsx index 746c7471e..01bfec83f 100644 --- a/frontend/src/components/_common/Buttons/Button/index.tsx +++ b/frontend/src/components/_common/Buttons/Button/index.tsx @@ -15,6 +15,7 @@ interface ButtonProps extends ButtonHTMLAttributes { variant?: ButtonVariant; isLoading?: boolean; customCss?: SerializedStyles; + ariaLabel?: string; } export function Button({ @@ -27,13 +28,20 @@ export function Button({ customCss, type = 'button', onClick, + 'aria-label': ariaLabel, }: ButtonProps) { const cssProps = [s_baseButton(borderRadius), s_size(size)]; if (variant) cssProps.push(s_variant[variant]); return ( - diff --git a/frontend/src/components/_common/Calendar/Body/index.tsx b/frontend/src/components/_common/Calendar/Body/index.tsx index d46cb1a12..6d82c5452 100644 --- a/frontend/src/components/_common/Calendar/Body/index.tsx +++ b/frontend/src/components/_common/Calendar/Body/index.tsx @@ -1,5 +1,3 @@ -// import 하지 않으면 스토리북에서 캘린더 컴포넌트가 렌더링 되지 않아 일단 추가(@해리) -import React from 'react'; import type { DateInfo } from 'types/calendar'; import { useCalendarContext } from '@hooks/useCalendarContext/useCalendarContext'; diff --git a/frontend/src/components/_common/Calendar/Calendar.stories.tsx b/frontend/src/components/_common/Calendar/Calendar.stories.tsx index 5edd4e008..b028992b7 100644 --- a/frontend/src/components/_common/Calendar/Calendar.stories.tsx +++ b/frontend/src/components/_common/Calendar/Calendar.stories.tsx @@ -16,7 +16,6 @@ import Calendar from '.'; const meta: Meta = { title: 'Components/Calendar', component: Calendar, - tags: ['autodocs'], parameters: { layout: 'centered', }, diff --git a/frontend/src/components/_common/Calendar/index.tsx b/frontend/src/components/_common/Calendar/index.tsx index a9c7f6217..1655d0f05 100644 --- a/frontend/src/components/_common/Calendar/index.tsx +++ b/frontend/src/components/_common/Calendar/index.tsx @@ -1,6 +1,4 @@ import type { PropsWithChildren } from 'react'; -// import 하지 않으면 스토리북에서 캘린더 컴포넌트가 렌더링 되지 않아 일단 추가(@해리) -import React from 'react'; import CalendarProvider from '@contexts/CalendarProvider'; diff --git a/frontend/src/components/_common/Header/Header.styles.ts b/frontend/src/components/_common/Header/Header.styles.ts index f7a38155f..d5a8851f0 100644 --- a/frontend/src/components/_common/Header/Header.styles.ts +++ b/frontend/src/components/_common/Header/Header.styles.ts @@ -23,8 +23,15 @@ export const s_header = css` `; export const s_title = css` + pointer-events: none; + position: absolute; left: 50%; transform: translateX(-50%); + font-weight: ${theme.typography.bodyBold}; + + &:focus { + outline: none; + } `; diff --git a/frontend/src/components/_common/Header/index.tsx b/frontend/src/components/_common/Header/index.tsx index e8c7134db..c3b737103 100644 --- a/frontend/src/components/_common/Header/index.tsx +++ b/frontend/src/components/_common/Header/index.tsx @@ -1,4 +1,4 @@ -import type { PropsWithChildren } from 'react'; +import { type PropsWithChildren, useEffect, useRef } from 'react'; import { s_header, s_title } from './Header.styles'; @@ -7,10 +7,18 @@ interface HeaderProps { } export default function Header({ title, children }: PropsWithChildren) { + const titleRef = useRef(null); + + useEffect(() => { + titleRef.current?.focus(); + }, []); + return (
{children} -

{title}

+

+ {title} +

); } diff --git a/frontend/src/components/_common/ScreenReaderOnly/ScreenReaderOnly.styles.ts b/frontend/src/components/_common/ScreenReaderOnly/ScreenReaderOnly.styles.ts new file mode 100644 index 000000000..2846ed020 --- /dev/null +++ b/frontend/src/components/_common/ScreenReaderOnly/ScreenReaderOnly.styles.ts @@ -0,0 +1,15 @@ +import { css } from '@emotion/react'; + +export const s_visuallyHidden = css` + position: absolute; + + overflow: hidden; + + width: 1px; + height: 1px; + + white-space: nowrap; + + clip: rect(0 0 0 0); + clip-path: inset(50%); +`; diff --git a/frontend/src/components/_common/ScreenReaderOnly/index.tsx b/frontend/src/components/_common/ScreenReaderOnly/index.tsx new file mode 100644 index 000000000..1c6d8e19f --- /dev/null +++ b/frontend/src/components/_common/ScreenReaderOnly/index.tsx @@ -0,0 +1,14 @@ +import type { HTMLAttributes, PropsWithChildren } from 'react'; + +import { s_visuallyHidden } from './ScreenReaderOnly.styles'; + +export default function ScreenReaderOnly({ + children, + ...props +}: PropsWithChildren>) { + return ( + + {children} + + ); +} diff --git a/frontend/src/components/_common/Text/Accent/index.tsx b/frontend/src/components/_common/Text/Accent/index.tsx index e62912beb..a8424597d 100644 --- a/frontend/src/components/_common/Text/Accent/index.tsx +++ b/frontend/src/components/_common/Text/Accent/index.tsx @@ -5,5 +5,5 @@ interface AccentProps { } export default function Accent({ text }: AccentProps) { - return {text}; + return {text}; } diff --git a/frontend/src/components/_common/Text/index.tsx b/frontend/src/components/_common/Text/index.tsx index 518e39ec6..fb2d6d0c5 100644 --- a/frontend/src/components/_common/Text/index.tsx +++ b/frontend/src/components/_common/Text/index.tsx @@ -10,7 +10,11 @@ interface TextProps extends PropsWithChildren { } export default function Text({ variant = 'default', typo = 'bodyMedium', children }: TextProps) { - return

{children}

; + return ( +

+ {children} +

+ ); } Text.Accent = Accent; diff --git a/frontend/src/constants/date.ts b/frontend/src/constants/date.ts index 4b81f5904..4d5ca2af0 100644 --- a/frontend/src/constants/date.ts +++ b/frontend/src/constants/date.ts @@ -1 +1,11 @@ export const DATES_PER_PAGE = 5; + +export const DAY_OF_WEEK_KR: Array<'일' | '월' | '화' | '수' | '목' | '금' | '토'> = [ + '일', + '월', + '화', + '수', + '목', + '금', + '토', +]; diff --git a/frontend/src/hooks/useCalendar/useCalendar.ts b/frontend/src/hooks/useCalendar/useCalendar.ts index 62c4d876e..6e03e1def 100644 --- a/frontend/src/hooks/useCalendar/useCalendar.ts +++ b/frontend/src/hooks/useCalendar/useCalendar.ts @@ -5,6 +5,7 @@ import useToast from '@hooks/useToast/useToast'; import { getFullDate, getMonth, getYear } from '@utils/date'; +import { DAY_OF_WEEK_KR } from '@constants/date'; import { TOAST_MESSAGES } from '@constants/toasts'; import { getMonthlyCalendarDate } from './useCalendar.utils'; @@ -68,7 +69,7 @@ const useCalendar = (): useCalendarReturn => { headers: { currentYear, currentMonth, - weekDays: ['일', '월', '화', '수', '목', '금', '토'], + weekDays: DAY_OF_WEEK_KR, }, body: { today: TODAY, diff --git a/frontend/src/mocks/meeting/data/meetingAllSchedules.json b/frontend/src/mocks/meeting/data/meetingAllSchedules.json index da9d5d2f6..7ba73336c 100644 --- a/frontend/src/mocks/meeting/data/meetingAllSchedules.json +++ b/frontend/src/mocks/meeting/data/meetingAllSchedules.json @@ -34,7 +34,7 @@ { "date": "2024-10-27", "time": "17:00", - "attendeeNames": ["빙봉"] + "attendeeNames": [] } ] } diff --git a/frontend/src/pages/MeetingEntrancePage/index.tsx b/frontend/src/pages/MeetingEntrancePage/index.tsx index 0d15ae830..ccc494c60 100644 --- a/frontend/src/pages/MeetingEntrancePage/index.tsx +++ b/frontend/src/pages/MeetingEntrancePage/index.tsx @@ -12,7 +12,7 @@ import useRouter from '@hooks/useRouter/useRouter'; import { useMeetingEntranceDetailQuery } from '@stores/servers/meeting/queries'; -import Logo from '@assets/images/logo.svg'; +import logoImg from '@assets/images/logo.webp'; import { s_buttonContainer, @@ -56,9 +56,11 @@ export default function MeetingEntrancePage() {
- +
-

{meetingName}

+

+ {meetingName} +

{`일정 조율을 위해 약속에 참여할 수 있는 \n${type ? MEETING_TYPE[type] : MEETING_TYPE.DATETIME} 알려주세요.`}
diff --git a/frontend/src/pages/MeetingLinkSharePage/index.tsx b/frontend/src/pages/MeetingLinkSharePage/index.tsx index e15176064..52138ddc6 100644 --- a/frontend/src/pages/MeetingLinkSharePage/index.tsx +++ b/frontend/src/pages/MeetingLinkSharePage/index.tsx @@ -14,7 +14,7 @@ import useKakaoTalkShare from '@hooks/useKakaoTalkShare/useKakaoTalkShare'; import useRouter from '@hooks/useRouter/useRouter'; import KakaoIcon from '@assets/images/kakao.svg'; -import LogoSunglass from '@assets/images/logoSunglass.svg'; +import logoSunglass from '@assets/images/logoSunglass.webp'; import { MEETING_INVITE_TEMPLATE_ID } from '@constants/kakao'; @@ -56,7 +56,7 @@ export default function MeetingLinkSharePage() {
- +
diff --git a/frontend/src/pages/MeetingViewerPage/index.tsx b/frontend/src/pages/MeetingViewerPage/index.tsx index 2ea766edf..4bb999f6e 100644 --- a/frontend/src/pages/MeetingViewerPage/index.tsx +++ b/frontend/src/pages/MeetingViewerPage/index.tsx @@ -121,7 +121,11 @@ export default function MeetingViewerPage() { {!isTimePickerUpdate && ( <> - diff --git a/frontend/src/types/calendar.ts b/frontend/src/types/calendar.ts index db690cd74..977d346f8 100644 --- a/frontend/src/types/calendar.ts +++ b/frontend/src/types/calendar.ts @@ -1,3 +1,5 @@ +import type { DAY_OF_WEEK_KR } from '@constants/date'; + export type DateSelectMode = 'single' | 'range'; export type MonthStatus = 'prev' | 'current' | 'next'; @@ -12,3 +14,5 @@ export type MonthlyDays = { key: number; value: DateInfo[]; }[]; + +export type DayOfWeekKR = (typeof DAY_OF_WEEK_KR)[number]; diff --git a/frontend/src/types/images.d.ts b/frontend/src/types/images.d.ts index df36c3c36..097f5509d 100644 --- a/frontend/src/types/images.d.ts +++ b/frontend/src/types/images.d.ts @@ -2,4 +2,5 @@ declare module '*.png'; declare module '*.jpg'; declare module '*.jpeg'; declare module '*.svg'; +declare module '*.webp'; declare module 'react-lottie'; diff --git a/frontend/src/utils/a11y.ts b/frontend/src/utils/a11y.ts new file mode 100644 index 000000000..fb12e04cf --- /dev/null +++ b/frontend/src/utils/a11y.ts @@ -0,0 +1,23 @@ +import type { DayOfWeekKR } from 'types/calendar'; + +export const formatAriaTab = (text: string, isSelected: boolean) => { + return `${text} 참여자가 선택한 일정 확인하기. ${isSelected ? '선택됨' : ''}`; +}; + +export const formatAriaFullDate = (date: string, dayOfWeek: DayOfWeekKR, attendees?: string[]) => { + if (!attendees) { + return ''; + } + + const [year, month, day] = date.split('-'); + + const fullDateText = `${year}년 ${month}월 ${day}일 ${dayOfWeek}요일.`; + + const totalAttendeeCount = attendees.length; + + if (totalAttendeeCount !== 0) { + return `${fullDateText} 총 참여 인원은 ${totalAttendeeCount}명 입니다. 참여 인원은 ${attendees.join(', ')}입니다.`; + } + + return `${fullDateText} 현재 참여 인원이 없습니다.`; +}; diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts index a3236a82a..543404419 100644 --- a/frontend/src/utils/date.ts +++ b/frontend/src/utils/date.ts @@ -21,8 +21,8 @@ export const formatTime = (time: string): string => { return `${hourPrefix} ${formattedHour}시`; }; -export const getMonth = (date: Date) => date.getMonth(); export const getYear = (date: Date) => date.getFullYear(); +export const getMonth = (date: Date) => date.getMonth(); export const getDay = (date: Date) => date.getDay(); export const getDate = (date: Date) => date.getDate(); export const getFullDate = (date: Date) => { @@ -32,3 +32,9 @@ export const getFullDate = (date: Date) => { return `${year}-${month}-${day}`; }; + +export const hasSelectableDaysInMonth = (currentMonth: number, schedules: string[]) => { + const availableMonths = schedules.map((schedule) => Number(schedule.split('-')[1])); + + return availableMonths.includes(currentMonth + 1); +}; diff --git a/frontend/webpack.common.js b/frontend/webpack.common.js index 9f806e5ea..e6bd1b987 100644 --- a/frontend/webpack.common.js +++ b/frontend/webpack.common.js @@ -22,7 +22,7 @@ module.exports = () => ({ exclude: /node_modules/, }, { - test: /\.(png|jpe?g|gif)$/i, + test: /\.(png|jpe?g|gif|webp)$/i, type: 'asset/resource', generator: { filename: 'assets/images/[name][hash][ext][query]',