Skip to content

FEAT: development helper in env hint #537

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
46 changes: 46 additions & 0 deletions src/components/DarkModeSwitch/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useId } from 'react';

import {
FormControl,
FormLabel,
HStack,
Switch,
useColorMode,
} from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';

export const DarkModeSwitch = () => {
const { t } = useTranslation(['account']);
const { colorMode, setColorMode } = useColorMode();
const id = useId();

return (
<FormControl display="flex" alignItems="center">
<HStack>
<FormLabel
as={colorMode === 'light' ? 'span' : undefined}
opacity={colorMode !== 'light' ? 0.5 : undefined}
htmlFor={id}
mb="0"
mr={0}
>
{t('account:preferences.theme.light')}
</FormLabel>
<Switch
colorScheme="brand"
id={id}
isChecked={colorMode === 'dark'}
onChange={(e) => setColorMode(e.target.checked ? 'dark' : 'light')}
/>
<FormLabel
as={colorMode === 'dark' ? 'span' : undefined}
opacity={colorMode !== 'dark' ? 0.5 : undefined}
htmlFor={id}
mb="0"
>
{t('account:preferences.theme.dark')}
</FormLabel>
</HStack>
</FormControl>
);
};
44 changes: 2 additions & 42 deletions src/features/account/PageAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import React, { useId } from 'react';
import React from 'react';

import {
Alert,
AlertTitle,
Box,
Button,
Divider,
FormControl,
FormLabel,
HStack,
Heading,
Link,
LinkBox,
LinkOverlay,
Stack,
Switch,
useColorMode,
} from '@chakra-ui/react';
import { useRouter } from 'next/navigation';
import { useTranslation } from 'react-i18next';
import { LuArrowRight, LuLogOut, LuUser } from 'react-icons/lu';

import { ConfirmModal } from '@/components/ConfirmModal';
import { DarkModeSwitch } from '@/components/DarkModeSwitch';
import { Icon } from '@/components/Icons';
import { AccountDeleteButton } from '@/features/account/AccountDeleteButton';
import { AccountEmailForm } from '@/features/account/AccountEmailForm';
Expand Down Expand Up @@ -117,39 +113,3 @@ export default function PageHome() {
</AppLayoutPage>
);
}

const DarkModeSwitch = () => {
const { t } = useTranslation(['account']);
const { colorMode, setColorMode } = useColorMode();
const id = useId();

return (
<FormControl display="flex" alignItems="center">
<HStack>
<FormLabel
as={colorMode === 'light' ? 'span' : undefined}
opacity={colorMode !== 'light' ? 0.5 : undefined}
htmlFor={id}
mb="0"
mr={0}
>
{t('account:preferences.theme.light')}
</FormLabel>
<Switch
colorScheme="brand"
id={id}
isChecked={colorMode === 'dark'}
onChange={(e) => setColorMode(e.target.checked ? 'dark' : 'light')}
/>
<FormLabel
as={colorMode === 'dark' ? 'span' : undefined}
opacity={colorMode !== 'dark' ? 0.5 : undefined}
htmlFor={id}
mb="0"
>
{t('account:preferences.theme.dark')}
</FormLabel>
</HStack>
</FormControl>
);
};
39 changes: 24 additions & 15 deletions src/features/devtools/EnvHint.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Box, Text } from '@chakra-ui/react';

import { env } from '@/env.mjs';
import { EnvHintDevPopover } from '@/features/devtools/EnvHintDevPopover';

export const getEnvHintTitlePrefix = () => {
if (env.NEXT_PUBLIC_ENV_EMOJI) return `${env.NEXT_PUBLIC_ENV_EMOJI} `;
Expand All @@ -13,6 +14,24 @@ export const EnvHint = () => {
return null;
}

const hintContent = (
<Text
position="fixed"
top="0"
insetStart="4"
bg={`${env.NEXT_PUBLIC_ENV_COLOR_SCHEME}.400`}
color={`${env.NEXT_PUBLIC_ENV_COLOR_SCHEME}.900`}
fontSize="0.6rem"
fontWeight="bold"
px="1"
borderBottomStartRadius="sm"
borderBottomEndRadius="sm"
textTransform="uppercase"
>
{env.NEXT_PUBLIC_ENV_NAME}
</Text>
);

return (
<Box
zIndex="9999"
Expand All @@ -23,21 +42,11 @@ export const EnvHint = () => {
h="2px"
bg={`${env.NEXT_PUBLIC_ENV_COLOR_SCHEME}.400`}
>
<Text
position="fixed"
top="0"
insetStart="4"
bg={`${env.NEXT_PUBLIC_ENV_COLOR_SCHEME}.400`}
color={`${env.NEXT_PUBLIC_ENV_COLOR_SCHEME}.900`}
fontSize="0.6rem"
fontWeight="bold"
px="1"
borderBottomStartRadius="sm"
borderBottomEndRadius="sm"
textTransform="uppercase"
>
{env.NEXT_PUBLIC_ENV_NAME}
</Text>
{env.NEXT_PUBLIC_NODE_ENV === 'development' ? (
<EnvHintDevPopover>{hintContent}</EnvHintDevPopover>
) : (
hintContent
)}
</Box>
);
};
40 changes: 40 additions & 0 deletions src/features/devtools/EnvHintDevPopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use client';

import { cloneElement } from 'react';

import {
Popover,
PopoverArrow,
PopoverBody,
PopoverCloseButton,
PopoverContent,
PopoverHeader,
PopoverTrigger,
} from '@chakra-ui/react';

import { DarkModeSwitch } from '@/components/DarkModeSwitch';
import { env } from '@/env.mjs';

export const EnvHintDevPopover: React.FC<{ children: React.ReactElement }> = ({
children,
}) => {
if (!env.NEXT_PUBLIC_ENV_NAME || !children) {
return null;
}

const childrenAsButton = cloneElement(children, { as: 'button' });
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider preserving existing properties when cloning children.

While converting the child to a button is a good approach for consistency, it might override existing properties. Consider merging the new properties with the existing ones:

- const childrenAsButton = cloneElement(children, { as: 'button' });
+ const childrenAsButton = cloneElement(children, { ...children.props, as: 'button' });

This change ensures that any existing properties or event handlers on the child element are preserved while still applying the as: 'button' property.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const childrenAsButton = cloneElement(children, { as: 'button' });
const childrenAsButton = cloneElement(children, { ...children.props, as: 'button' });

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, cloneElement already takes care of merging children props with the ones passed as the second parameter. This code is ok

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DecampsRenan, thank you for the clarification. You're correct; cloneElement automatically merges the existing child's props with the new props. I'll keep that in mind for future reviews.

(_/)

(•_•)

Curious rabbit is learning!


✏️ Learnings added
Learnt from: DecampsRenan
PR: BearStudio/start-ui-web#537
File: src/features/devtools/EnvHintDevPopover.tsx:0-0
Timestamp: 2024-10-11T14:57:52.868Z
Learning: When using `React.cloneElement`, remember that it automatically merges the child's existing `props` with the new props provided, so manually spreading `children.props` is unnecessary.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


return (
<Popover closeOnBlur closeOnEsc>
<PopoverTrigger>{childrenAsButton}</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader mb={2}>Development helper</PopoverHeader>
<PopoverBody>
<DarkModeSwitch />
</PopoverBody>
</PopoverContent>
</Popover>
);
};
Loading