Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 22, 2021 03:53 pm GMT

Create a custom theme editor with HyperTheme

In this tutorial you'll learn how to create a custom theme editor and a simple Color Panel Editor.

In this tutorial you'll use:

Prerequisites

You need HyperTheme Editor installed and working on your Chakra UI Project.

If you still not have installed HyperTheme, follow the installation instructions here.

HyperThemeEditor component

In the Installation page we have added the HyperThemeEditor component that gives us a plug&play editor on the page through a Button.

The source code of HyperThemeEditor itself it's very simple as you can see here:

import React, { FC } from 'react'import {  ThemeEditor,  ThemeEditorButton,  ThemeEditorButtonProps,  ThemeEditorDrawer,} from '@hypertheme-editor/chakra-ui-core'import { ThemeEditorColors } from '@hypertheme-editor/chakra-ui-colors'import { ThemeEditorFontSizes } from '@hypertheme-editor/chakra-ui-font-sizes'import { CgColorPicker } from 'react-icons/cg'import { ImFontSize } from 'react-icons/im'export type DefaultThemeEditorProps = ThemeEditorButtonPropsexport const HyperThemeEditor: FC<DefaultThemeEditorProps> = (props) => {  return (    <ThemeEditor>      <ThemeEditorButton {...props} />      <ThemeEditorDrawer>        <ThemeEditorColors icon={CgColorPicker} title="Colors" />        <ThemeEditorFontSizes icon={ImFontSize} title="Font Sizes" />      </ThemeEditorDrawer>    </ThemeEditor>  )}

Read more about HyperThemeEditor component here.

Creating a Custom ThemeEditor

Based on the source code of HyperThemeEditor we can create a custom ThemeEditor.

To do so, create a new MyThemeEditor component with this content:

import React, { FC } from 'react'import {  ThemeEditor,  ThemeEditorButton,  ThemeEditorButtonProps,  ThemeEditorColors,  ThemeEditorFontSizes,} from '@hypertheme-editor/chakra-ui'import { CgColorPicker } from 'react-icons/cg'import { BiText } from 'react-icons/bi'export const MyThemeEditor = (props) => {  return (    <ThemeEditor>      <ThemeEditorButton {...props} />      <ThemeEditorDrawer>        <ThemeEditorColors icon={CgColorPicker} title="Colors" />        <ThemeEditorFontSizes icon={BiText} title="Typography" />      </ThemeEditorDrawer>    </ThemeEditor>  )}

As you can see, you can change the order of the panels, the icons and the labels.

HyperTheme uses react-icons for rendering the icons on the editor, here you can search for the icon you need.

Read more about: ThemeEditor, ThemeEditorDrawer and ThemeEditorButton.

Creating a custom Panel

Now that we have a custom ThemeEditor component we can start creating our custom editor panel.

Create a new MyColorEditor component:

import React from 'react'import { Box } from '@chakra-ui/react'export default function MyCustomPanel(props) {  return <Box>Testing Custom Panel</Box>}

Add it as a new Panel to our MyThemeEditor component:

import React, { FC } from 'react'import {  ThemeEditor,  ThemeEditorButton,  ThemeEditorButtonProps,  ThemeEditorColors,  ThemeEditorFontSizes,} from '@hypertheme-editor/chakra-ui'import { CgColorPicker } from 'react-icons/cg'import { BiText } from 'react-icons/bi'import MyCustomPanel from './MyCustomPanel'export default function MyThemeEditor(props) {  return (    <ThemeEditor>      <ThemeEditorButton {...props} />      <ThemeEditorDrawer>        {/* Add the MyCustomPanel to our theme editor */}        <MyCustomPanel icon={CgColorPicker} title="My Panel" />        <ThemeEditorColors icon={CgColorPicker} title="Colors" />        <ThemeEditorFontSizes icon={BiText} title="Typography" />      </ThemeEditorDrawer>    </ThemeEditor>  )}

Now you have a custom panel inside the ThemeEditorDrawer component, your theme editor should look like the example below:

function MyCustomPanel(props) {  return <Box>Testing Custom Panel</Box>}function MyThemeEditor(props) {  return (    <ThemeEditor>      <ThemeEditorButton {...props} />      <ThemeEditorDrawer>        {/* Add the MyCustomPanel to our theme editor */}        <MyCustomPanel icon={CgColorPicker} title="My Panel" />        <ThemeEditorColors icon={CgColorPicker} title="Colors" />        <ThemeEditorFontSizes icon={BiText} title="Typography" />      </ThemeEditorDrawer>    </ThemeEditor>  )}render(<MyThemeEditor />)

useThemeEditor hook

Now that we have a theme editor with a custom editor panel, it's time to start retrieving and live edit the theme.

HyperTheme Editor provides the useThemeEditor hook to:

  • maintaint the current theme state
  • live edit the current theme
  • manage changes history

Check out more on the documentation.

Retrieving and show the current theme

In this section we're creating a ThemeColorBox that shows a color for the theme.

Create a new ThemeColorBox component with this content:

import React from 'react'import { Box } from '@chakra-ui/react'import { useThemeEditor } from '@hypertheme-editor/chakra-ui'export default function ThemeColorBox({ token, paletteIndex = 500, ...props }) {  const { theme } = useThemeEditor()  const color = useMemo(() => {    // in Chakra UI colors could objects    // with an index (100, 200, 300, etc) or a single color    if (theme && theme.colors[token]) {      // if the color is a string, return it      if (typeof theme.colors[token] === 'string') {        return theme.colors[token]        // if it's an object return the current paletteIndex for that color      } else if (theme.colors[token][paletteIndex]) {        return theme.colors[token][paletteIndex]      }    }    return 'gray'  }, [theme, token, paletteIndex])  return <Box w="40px" h="40px" borderRadius="md" bgColor={color} {...props} />}

Let's check our new component with some different theme colors, try to change the colors from the editor to check that is working correctly:

<HStack>  <HyperThemeEditor />  <ThemeColorBox token="blue" paletteIndex={500} />  <ThemeColorBox token="red" paletteIndex={500} />  <ThemeColorBox token="green" paletteIndex={500} />  <ThemeColorBox token="orange" paletteIndex={500} />  <ThemeColorBox token="yellow" paletteIndex={500} />  <ThemeColorBox token="purple" paletteIndex={500} /></HStack>

Live edit the current theme

It's time to live edit the current theme.

Let's create a SimpleColorEditor component that shows the current color and set a new one through an Input:

import React from 'react'import { useThemeEditor } from '@hypertheme-editor/chakra-ui'import { Input } from '@chakra-ui/react'import { useDebouncyEffect } from 'use-debouncy'import { colord } from 'colord'export default function SimpleColorEditor({ token, paletteIndex, ...props }) {  const { theme, setTheme } = useThemeEditor()  const [inputValue, setInputValue] = useState<string>(theme.colors[token][paletteIndex] || '')  const handleOnChange = useCallback((event) => {    setInputValue(event.target.value)  }, [])  // use a debounced effect so the UI is not blocked  // while the value are changed through the Input  useDebouncyEffect(    () => {      // check that the input color is valid      if (colord(inputValue).isValid()) {        // the color token could be a simple color or a palette object,        // so we have to check it.        // We also check that the input value differ from        // the one from the theme, this is necessary        // for undo/redo functionality to work correctly        if (typeof theme.colors[token] === 'string' && theme.colors[token] !== inputValue) {          // live edit the current theme          setTheme({            ...theme,            colors: {              ...theme.colors,              [token]: inputValue,            },          })        } else if (          theme.colors[token][paletteIndex] &&          theme.colors[token][paletteIndex] !== inputValue        ) {          // live edit the current theme          setTheme({            ...theme,            colors: {              ...theme.colors,              [token]: {                ...theme.colors.token,                [paletteIndex]: inputValue,              },            },          })        }      }    },    500,    [inputValue]  )  // update internal state if another panel change this value  useEffect(() => {    if (      theme.colors[token] &&      theme.colors[token][paletteIndex] &&      theme.colors[token][paletteIndex] !== inputValue    ) {      setInputValue(theme.colors[token][paletteIndex])    }    // eslint-disable-next-line react-hooks/exhaustive-deps  }, [theme.colors, token, paletteIndex])  return (    <HStack>      {/* add the ThemeColorBox we've created before */}      <ThemeColorBox token={token} paletteIndex={paletteIndex} />      <Input onChange={handleOnChange} value={inputValue} />    </HStack>  )}

Let's try our new SimpleColorEditor component.

If you change a value (using HEX notation) you should see the new color in current theme.

Compare the edited colors with the value provided by HyperThemeEditor.

<VStack>  <HyperThemeEditor />  <SimpleColorEditor token="blue" paletteIndex={500} />  <SimpleColorEditor token="red" paletteIndex={500} />  <SimpleColorEditor token="green" paletteIndex={500} />  <SimpleColorEditor token="orange" paletteIndex={500} />  <SimpleColorEditor token="yellow" paletteIndex={500} />  <SimpleColorEditor token="purple" paletteIndex={500} /></VStack>

Final mounting

Finally, we can mount our SimpleColorEditor into our custom theme editor.

Edit the MyPanel component like this:

import React from 'react'import { Box } from '@chakra-ui/react'export default function MyCustomPanel(props) {  return (    <VStack>      <SimpleColorEditor token="blue" paletteIndex={500} />      <SimpleColorEditor token="red" paletteIndex={500} />      <SimpleColorEditor token="green" paletteIndex={500} />      <SimpleColorEditor token="orange" paletteIndex={500} />      <SimpleColorEditor token="yellow" paletteIndex={500} />      <SimpleColorEditor token="purple" paletteIndex={500} />    </VStack>  )}

The final result should be like this:

function MyCustomPanel(props) {  return (    <VStack>      <SimpleColorEditor token="blue" paletteIndex={500} />      <SimpleColorEditor token="red" paletteIndex={500} />      <SimpleColorEditor token="green" paletteIndex={500} />      <SimpleColorEditor token="orange" paletteIndex={500} />      <SimpleColorEditor token="yellow" paletteIndex={500} />      <SimpleColorEditor token="purple" paletteIndex={500} />    </VStack>  )}function MyThemeEditor(props) {  return (    <ThemeEditor>      <ThemeEditorButton {...props} />      <ThemeEditorDrawer>        {/* Add the MyCustomPanel to our theme editor */}        <MyCustomPanel icon={CgColorPicker} title="My Panel" />        <ThemeEditorColors icon={CgColorPicker} title="Colors" />        <ThemeEditorFontSizes icon={BiText} title="Typography" />      </ThemeEditorDrawer>    </ThemeEditor>  )}render(<MyThemeEditor />)

Congratulations! You have created your first working custom panel.


Original Link: https://dev.to/angelo_libero/create-a-custom-theme-editor-with-hypertheme-nf1

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To