diff --git a/src/frontend/eslint.config.js b/src/frontend/eslint.config.js index a0d6e64b..1a164f64 100644 --- a/src/frontend/eslint.config.js +++ b/src/frontend/eslint.config.js @@ -54,6 +54,13 @@ export default tseslint.config( { allowConstantExport: true }, ], + // React Compiler rules (v7+) — disable until migrated to React 19 + 'react-hooks/react-compiler': 'off', + 'react-hooks/set-state-in-effect': 'off', + 'react-hooks/preserve-manual-memoization': 'off', + 'react-hooks/immutability': 'off', + 'react-hooks/refs': 'off', + // jsx-a11y recommended rules ...jsxA11y.configs.recommended.rules, diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 5b84ae48..9d5b38ee 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -48,11 +48,11 @@ "@types/react-dom": "18.3.1", "@vitejs/plugin-react": "6.0.2", "eslint": "9.39.4", - "eslint-config-prettier": "10.1.5", + "eslint-config-prettier": "10.1.8", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "5.2.0", - "eslint-plugin-react-refresh": "0.4.20", + "eslint-plugin-react-hooks": "7.1.1", + "eslint-plugin-react-refresh": "0.5.2", "globals": "17.6.0", "postcss": "8.5.15", "prettier": "3.8.3", @@ -6932,9 +6932,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", - "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", "bin": { @@ -7035,26 +7035,33 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", - "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz", + "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==", "dev": true, "license": "MIT", "peerDependencies": { - "eslint": ">=8.40" + "eslint": "^9 || ^10" } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { @@ -8079,6 +8086,23 @@ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz", "integrity": "sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==" }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/hono": { "version": "4.12.18", "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", @@ -13873,6 +13897,19 @@ "peerDependencies": { "zod": "^3.25.28 || ^4" } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } } } } diff --git a/src/frontend/package.json b/src/frontend/package.json index 4fda522c..2d899e9c 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -55,11 +55,11 @@ "@types/react-dom": "18.3.1", "@vitejs/plugin-react": "6.0.2", "eslint": "9.39.4", - "eslint-config-prettier": "10.1.5", + "eslint-config-prettier": "10.1.8", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "5.2.0", - "eslint-plugin-react-refresh": "0.4.20", + "eslint-plugin-react-hooks": "7.1.1", + "eslint-plugin-react-refresh": "0.5.2", "globals": "17.6.0", "postcss": "8.5.15", "prettier": "3.8.3", diff --git a/src/frontend/src/features/notifications/components/StyledToast.tsx b/src/frontend/src/features/notifications/components/StyledToast.tsx new file mode 100644 index 00000000..82f75576 --- /dev/null +++ b/src/frontend/src/features/notifications/components/StyledToast.tsx @@ -0,0 +1,11 @@ +import { styled } from '@/styled-system/jsx' + +export const StyledToast = styled('div', { + base: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + gap: '1rem', + padding: '10px', + }, +}) diff --git a/src/frontend/src/features/notifications/components/StyledToastContainer.tsx b/src/frontend/src/features/notifications/components/StyledToastContainer.tsx new file mode 100644 index 00000000..ac97f97f --- /dev/null +++ b/src/frontend/src/features/notifications/components/StyledToastContainer.tsx @@ -0,0 +1,16 @@ +import { styled } from '@/styled-system/jsx' + +export const StyledToastContainer = styled('div', { + base: { + margin: 0.5, + boxShadow: + 'rgba(0, 0, 0, 0.5) 0px 4px 8px 0px, rgba(0, 0, 0, 0.3) 0px 6px 20px 4px', + backgroundColor: 'greyscale.700', + color: 'white', + borderRadius: '8px', + '&[data-entering]': { animation: 'fade 200ms' }, + '&[data-exiting]': { animation: 'fade 150ms reverse ease-in' }, + width: 'fit-content', + marginLeft: 'auto', + }, +}) diff --git a/src/frontend/src/features/notifications/components/Toast.tsx b/src/frontend/src/features/notifications/components/Toast.tsx index bee02c45..bc5ebc61 100644 --- a/src/frontend/src/features/notifications/components/Toast.tsx +++ b/src/frontend/src/features/notifications/components/Toast.tsx @@ -1,36 +1,12 @@ import { useToast } from '@react-aria/toast' import { Button } from '@/primitives' import { RiCloseLine } from '@remixicon/react' -import { styled } from '@/styled-system/jsx' import { useRef } from 'react' import type { ToastState } from '@react-stately/toast' import type { ToastData } from './ToastProvider' import type { QueuedToast } from '@react-stately/toast' - -export const StyledToastContainer = styled('div', { - base: { - margin: 0.5, - boxShadow: - 'rgba(0, 0, 0, 0.5) 0px 4px 8px 0px, rgba(0, 0, 0, 0.3) 0px 6px 20px 4px', - backgroundColor: 'greyscale.700', - color: 'white', - borderRadius: '8px', - '&[data-entering]': { animation: 'fade 200ms' }, - '&[data-exiting]': { animation: 'fade 150ms reverse ease-in' }, - width: 'fit-content', - marginLeft: 'auto', - }, -}) - -export const StyledToast = styled('div', { - base: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - gap: '1rem', - padding: '10px', - }, -}) +import { StyledToastContainer } from './StyledToastContainer' +import { StyledToast } from './StyledToast' export interface ToastProps { key: string diff --git a/src/frontend/src/features/notifications/components/ToastAnyRecording.tsx b/src/frontend/src/features/notifications/components/ToastAnyRecording.tsx index 75c2f44c..113606de 100644 --- a/src/frontend/src/features/notifications/components/ToastAnyRecording.tsx +++ b/src/frontend/src/features/notifications/components/ToastAnyRecording.tsx @@ -1,7 +1,8 @@ import { useToast } from '@react-aria/toast' import { useMemo, useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import type { ToastProps } from './Toast' +import { StyledToastContainer } from './StyledToastContainer' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' import { NotificationType } from '../NotificationType' diff --git a/src/frontend/src/features/notifications/components/ToastJoined.tsx b/src/frontend/src/features/notifications/components/ToastJoined.tsx index f6f8b527..64e09a7e 100644 --- a/src/frontend/src/features/notifications/components/ToastJoined.tsx +++ b/src/frontend/src/features/notifications/components/ToastJoined.tsx @@ -6,10 +6,11 @@ import Source = Track.Source import { useMaybeLayoutContext } from '@livekit/components-react' import { ParticipantTile } from '@/features/rooms/livekit/components/ParticipantTile' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack, styled } from '@/styled-system/jsx' import { Div } from '@/primitives' import { useTranslation } from 'react-i18next' +import { StyledToastContainer } from './StyledToastContainer' const ClickableToast = styled(RACButton, { base: { diff --git a/src/frontend/src/features/notifications/components/ToastLowerHand.tsx b/src/frontend/src/features/notifications/components/ToastLowerHand.tsx index 97a21920..85cf9309 100644 --- a/src/frontend/src/features/notifications/components/ToastLowerHand.tsx +++ b/src/frontend/src/features/notifications/components/ToastLowerHand.tsx @@ -1,11 +1,12 @@ import { useToast } from '@react-aria/toast' import { useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' import { Button } from '@/primitives' import { css } from '@/styled-system/css' +import { StyledToastContainer } from './StyledToastContainer' export function ToastLowerHand({ state, ...props }: Readonly) { const { t } = useTranslation('notifications', { keyPrefix: 'lowerHand' }) diff --git a/src/frontend/src/features/notifications/components/ToastMessageReceived.tsx b/src/frontend/src/features/notifications/components/ToastMessageReceived.tsx index ea954a6d..125c85b1 100644 --- a/src/frontend/src/features/notifications/components/ToastMessageReceived.tsx +++ b/src/frontend/src/features/notifications/components/ToastMessageReceived.tsx @@ -1,13 +1,14 @@ import { useToast } from '@react-aria/toast' import { useEffect, useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { Text } from '@/primitives' import { RiMessage2Line } from '@remixicon/react' import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel' import { Button as RACButton } from 'react-aria-components' import { css } from '@/styled-system/css' import { useTranslation } from 'react-i18next' +import { StyledToastContainer } from './StyledToastContainer' export function ToastMessageReceived({ state, diff --git a/src/frontend/src/features/notifications/components/ToastMuted.tsx b/src/frontend/src/features/notifications/components/ToastMuted.tsx index 76bc8eeb..4706c3fc 100644 --- a/src/frontend/src/features/notifications/components/ToastMuted.tsx +++ b/src/frontend/src/features/notifications/components/ToastMuted.tsx @@ -1,9 +1,10 @@ import { useToast } from '@react-aria/toast' import { useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' +import { StyledToastContainer } from './StyledToastContainer' export function ToastMuted({ state, ...props }: Readonly) { const { t } = useTranslation('notifications') diff --git a/src/frontend/src/features/notifications/components/ToastPermissionsRemoved.tsx b/src/frontend/src/features/notifications/components/ToastPermissionsRemoved.tsx index 090e4768..38220c93 100644 --- a/src/frontend/src/features/notifications/components/ToastPermissionsRemoved.tsx +++ b/src/frontend/src/features/notifications/components/ToastPermissionsRemoved.tsx @@ -1,9 +1,10 @@ import { useToast } from '@react-aria/toast' import { useMemo, useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' +import { StyledToastContainer } from './StyledToastContainer' export function ToastPermissionsRemoved({ state, diff --git a/src/frontend/src/features/notifications/components/ToastRaised.tsx b/src/frontend/src/features/notifications/components/ToastRaised.tsx index 380ddf97..20c9ca41 100644 --- a/src/frontend/src/features/notifications/components/ToastRaised.tsx +++ b/src/frontend/src/features/notifications/components/ToastRaised.tsx @@ -1,13 +1,14 @@ import { useToast } from '@react-aria/toast' import { useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack } from '@/styled-system/jsx' import { Button, Div } from '@/primitives' import { useTranslation } from 'react-i18next' import { RiCloseLine, RiHand } from '@remixicon/react' import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel' import { css } from '@/styled-system/css' +import { StyledToastContainer } from './StyledToastContainer' export function ToastRaised({ state, ...props }: Readonly) { const { t } = useTranslation('notifications') diff --git a/src/frontend/src/features/notifications/components/ToastRecordingRequest.tsx b/src/frontend/src/features/notifications/components/ToastRecordingRequest.tsx index 5ade87ad..85e7fe9d 100644 --- a/src/frontend/src/features/notifications/components/ToastRecordingRequest.tsx +++ b/src/frontend/src/features/notifications/components/ToastRecordingRequest.tsx @@ -1,13 +1,14 @@ import { useToast } from '@react-aria/toast' import { useMemo, useRef } from 'react' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' import { NotificationType } from '../NotificationType' import { Button } from '@/primitives' import { css } from '@/styled-system/css' import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel' +import { StyledToastContainer } from './StyledToastContainer' export function ToastRecordingRequest({ state, diff --git a/src/frontend/src/features/notifications/components/ToastRecordingSaving.tsx b/src/frontend/src/features/notifications/components/ToastRecordingSaving.tsx index d4814f0e..4370a6fe 100644 --- a/src/frontend/src/features/notifications/components/ToastRecordingSaving.tsx +++ b/src/frontend/src/features/notifications/components/ToastRecordingSaving.tsx @@ -2,12 +2,13 @@ import { useToast } from '@react-aria/toast' import { useMemo, useRef } from 'react' import { Text } from '@/primitives' -import { StyledToastContainer, type ToastProps } from './Toast' +import { type ToastProps } from './Toast' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' import { useUser } from '@/features/auth/api/useUser' import { css } from '@/styled-system/css' import { RecordingMode } from '@/features/recording' +import { StyledToastContainer } from './StyledToastContainer' export function ToastRecordingSaving({ state, diff --git a/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx b/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx index a4994c26..80ad8fb2 100644 --- a/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx +++ b/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx @@ -1,4 +1,4 @@ -import { StyledToastContainer } from './Toast' +import { StyledToastContainer } from './StyledToastContainer' import { HStack, VStack } from '@/styled-system/jsx' import { Avatar } from '@/components/Avatar' import { Button, Text } from '@/primitives' diff --git a/src/frontend/src/features/pip/components/PipControlBar.tsx b/src/frontend/src/features/pip/components/PipControlBar.tsx index 6f849db5..1425923f 100644 --- a/src/frontend/src/features/pip/components/PipControlBar.tsx +++ b/src/frontend/src/features/pip/components/PipControlBar.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import { styled } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' import { AudioDevicesControl } from '@/features/rooms/livekit/components/controls/Device/AudioDevicesControl' diff --git a/src/frontend/src/features/pip/components/PipFloatingReactions.tsx b/src/frontend/src/features/pip/components/PipFloatingReactions.tsx index e612d6b0..1bb616f3 100644 --- a/src/frontend/src/features/pip/components/PipFloatingReactions.tsx +++ b/src/frontend/src/features/pip/components/PipFloatingReactions.tsx @@ -1,6 +1,6 @@ import { useSnapshot } from 'valtio' import { reactionsStore } from '@/stores/reactions' -import { useMemo, useRef } from 'react' +import { useRef, useState } from 'react' import { FloatingReaction } from '@/features/reactions/components/ReactionPortals' import { Reaction } from '@/features/reactions/types' import { css } from '@/styled-system/css' @@ -19,8 +19,8 @@ export const PipFloatingReactions = () => { const PipFloatingReaction = ({ reaction }: { reaction: Reaction }) => { const containerRef = useRef(null) - const speed = useMemo(() => Math.random() * 1.5 + 0.5, []) - const scale = useMemo(() => Math.max(Math.random() + 0.5, 1), []) + const [speed] = useState(() => Math.random() * 1.5 + 0.5) + const [scale] = useState(() => Math.max(Math.random() + 0.5, 1)) return (
Math.random() * window.innerWidth * REACTION_SPAWN_WIDTH_RATIO, - [] + const [left] = useState( + () => Math.random() * window.innerWidth * REACTION_SPAWN_WIDTH_RATIO ) useEffect(() => { @@ -115,8 +114,8 @@ export function FloatingReaction({ } const ReactionPortal = ({ reaction }: { reaction: Reaction }) => { - const speed = useMemo(() => Math.random() * 1.5 + 0.5, []) - const scale = useMemo(() => Math.max(Math.random() + 0.5, 1), []) + const [speed] = useState(() => Math.random() * 1.5 + 0.5) + const [scale] = useState(() => Math.max(Math.random() + 0.5, 1)) return createPortal(
{ useSrCountdownAnnouncement(remainingSeconds) useEffect(() => { - setTimeRemaining(IDLE_DISCONNECT_TIMEOUT_MS) const interval = setInterval(() => { setTimeRemaining((prev) => { if (prev <= 1000) { diff --git a/src/frontend/src/features/rooms/livekit/hooks/useCopyRoomToClipboard.ts b/src/frontend/src/features/rooms/livekit/hooks/useCopyRoomToClipboard.ts index 7df70d4d..6f07d80f 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useCopyRoomToClipboard.ts +++ b/src/frontend/src/features/rooms/livekit/hooks/useCopyRoomToClipboard.ts @@ -31,13 +31,14 @@ export const useCopyRoomToClipboard = (room: ApiRoom | undefined) => { } }, [isRoomUrlCopied]) + const roomSlug = room?.slug const roomUrl = useMemo(() => { - return room?.slug ? getRouteUrl('room', room.slug) : '' - }, [room?.slug]) + return roomSlug ? getRouteUrl('room', roomSlug) : '' + }, [roomSlug]) const hasTelephonyInfo = useMemo(() => { return telephony.enabled && room?.pin_code - }, [telephony.enabled, room?.pin_code]) + }, [telephony.enabled, room]) const content = useMemo(() => { if (!roomUrl || !room) return '' diff --git a/src/frontend/src/primitives/Checkbox.tsx b/src/frontend/src/primitives/Checkbox.tsx index 97fdbcfd..06445e94 100644 --- a/src/frontend/src/primitives/Checkbox.tsx +++ b/src/frontend/src/primitives/Checkbox.tsx @@ -10,7 +10,7 @@ import { FieldErrors } from './FieldErrors' import { FieldDescription } from './FieldDescription' // styled taken from example at https://react-spectrum.adobe.com/react-aria/Checkbox.html -export const StyledCheckbox = styled(RACCheckbox, { +const StyledCheckbox = styled(RACCheckbox, { base: { display: 'flex', alignItems: 'center', diff --git a/src/frontend/src/primitives/Menu.tsx b/src/frontend/src/primitives/Menu.tsx index f6008716..86eba76d 100644 --- a/src/frontend/src/primitives/Menu.tsx +++ b/src/frontend/src/primitives/Menu.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react' import { MenuTrigger } from 'react-aria-components' -import { StyledPopover } from './Popover' +import { StyledPopover } from './StyledPopover' import { Box } from './Box' /** diff --git a/src/frontend/src/primitives/Popover.tsx b/src/frontend/src/primitives/Popover.tsx index 5ccd995f..d7ec918e 100644 --- a/src/frontend/src/primitives/Popover.tsx +++ b/src/frontend/src/primitives/Popover.tsx @@ -2,39 +2,12 @@ import { ReactNode } from 'react' import { DialogProps, DialogTrigger, - Popover as RACPopover, Dialog, OverlayArrow, } from 'react-aria-components' import { styled } from '@/styled-system/jsx' import { Box } from './Box' - -export const StyledPopover = styled(RACPopover, { - base: { - minWidth: 'var(--trigger-width)', - '&[data-entering]': { - animation: 'slide 200ms', - }, - '&[data-exiting]': { - animation: 'slide 200ms reverse ease-in', - }, - '&[data-placement="bottom"]': { - marginTop: 0.25, - }, - '&[data-placement=top]': { - '--origin': 'translateY(8px)', - }, - '&[data-placement=bottom]': { - '--origin': 'translateY(-8px)', - }, - '&[data-placement=right]': { - '--origin': 'translateX(-8px)', - }, - '&[data-placement=left]': { - '--origin': 'translateX(8px)', - }, - }, -}) +import { StyledPopover } from './StyledPopover' const StyledOverlayArrow = styled(OverlayArrow, { base: { diff --git a/src/frontend/src/primitives/Radio.tsx b/src/frontend/src/primitives/Radio.tsx index 46822aec..a7cbdd36 100644 --- a/src/frontend/src/primitives/Radio.tsx +++ b/src/frontend/src/primitives/Radio.tsx @@ -6,7 +6,7 @@ import { styled } from '@/styled-system/jsx' import { type StyledVariantProps } from '@/styled-system/types' // styled taken from example at https://react-spectrum.adobe.com/react-aria/Checkbox.html and changed for round radios -export const StyledRadio = styled(RACRadio, { +const StyledRadio = styled(RACRadio, { base: { display: 'flex', alignItems: 'center', diff --git a/src/frontend/src/primitives/Select.tsx b/src/frontend/src/primitives/Select.tsx index ae8a78be..db8b2a5e 100644 --- a/src/frontend/src/primitives/Select.tsx +++ b/src/frontend/src/primitives/Select.tsx @@ -11,7 +11,7 @@ import { } from 'react-aria-components' import { useTranslation } from 'react-i18next' import { Box } from './Box' -import { StyledPopover } from './Popover' +import { StyledPopover } from './StyledPopover' import { menuRecipe } from '@/primitives/menuRecipe.ts' import { css } from '@/styled-system/css' import type { Placement } from '@react-types/overlays' diff --git a/src/frontend/src/primitives/StyledPopover.tsx b/src/frontend/src/primitives/StyledPopover.tsx new file mode 100644 index 00000000..c6c11c29 --- /dev/null +++ b/src/frontend/src/primitives/StyledPopover.tsx @@ -0,0 +1,29 @@ +import { Popover as RACPopover } from 'react-aria-components' +import { styled } from '@/styled-system/jsx' + +export const StyledPopover = styled(RACPopover, { + base: { + minWidth: 'var(--trigger-width)', + '&[data-entering]': { + animation: 'slide 200ms', + }, + '&[data-exiting]': { + animation: 'slide 200ms reverse ease-in', + }, + '&[data-placement="bottom"]': { + marginTop: 0.25, + }, + '&[data-placement=top]': { + '--origin': 'translateY(8px)', + }, + '&[data-placement=bottom]': { + '--origin': 'translateY(-8px)', + }, + '&[data-placement=right]': { + '--origin': 'translateX(-8px)', + }, + '&[data-placement=left]': { + '--origin': 'translateX(8px)', + }, + }, +}) diff --git a/src/frontend/src/primitives/Switch.tsx b/src/frontend/src/primitives/Switch.tsx index fa9dc3c4..c9578b2c 100644 --- a/src/frontend/src/primitives/Switch.tsx +++ b/src/frontend/src/primitives/Switch.tsx @@ -6,7 +6,7 @@ import { styled } from '@/styled-system/jsx' import { type StyledVariantProps } from '@/styled-system/types' import { RiCheckLine, RiCloseFill } from '@remixicon/react' -export const StyledSwitch = styled(RACSwitch, { +const StyledSwitch = styled(RACSwitch, { base: { display: 'flex', alignItems: 'center',