fix: Prevent color selector from closing on choosing a color (#2783)
* improv: wrap ColorPicker in memo to prevent unnecessary rerenders * improv appearance: wrap updateColor in useCallback to prevent unnecessary rerenders due to changing reference to the func * improv: define ColorCollection Component as top level, and modify it to prevent unnecessary rerenders
This commit is contained in:
parent
108eda0a6a
commit
e80db09ab1
@ -1,4 +1,4 @@
|
||||
import React, { FC, useContext, useEffect, useState } from 'react';
|
||||
import React, { FC, useContext, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { Button, Col, Collapse, Row, Slider, Space } from 'antd';
|
||||
import Paragraph from 'antd/lib/typography/Paragraph';
|
||||
@ -24,6 +24,11 @@ interface AppearanceVariable {
|
||||
description: string;
|
||||
}
|
||||
|
||||
type ColorCollectionProps = {
|
||||
variables: { name; description; value }[];
|
||||
updateColor: (variable: string, color: string, description: string) => void;
|
||||
};
|
||||
|
||||
const chatColorVariables = [
|
||||
{ name: 'theme-color-users-0', description: '' },
|
||||
{ name: 'theme-color-users-1', description: '' },
|
||||
@ -70,18 +75,18 @@ const allAvailableValues = [...componentColorVariables, ...chatColorVariables, .
|
||||
);
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
function ColorPicker({
|
||||
value,
|
||||
name,
|
||||
description,
|
||||
onChange,
|
||||
}: {
|
||||
value: string;
|
||||
name: string;
|
||||
description: string;
|
||||
onChange: (name: string, value: string, description: string) => void;
|
||||
}) {
|
||||
return (
|
||||
const ColorPicker = React.memo(
|
||||
({
|
||||
value,
|
||||
name,
|
||||
description,
|
||||
onChange,
|
||||
}: {
|
||||
value: string;
|
||||
name: string;
|
||||
description: string;
|
||||
onChange: (name: string, value: string, description: string) => void;
|
||||
}) => (
|
||||
<Col span={3} key={name}>
|
||||
<input
|
||||
type="color"
|
||||
@ -94,8 +99,26 @@ function ColorPicker({
|
||||
/>
|
||||
<div style={{ padding: '2px' }}>{description}</div>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
const ColorCollection: FC<ColorCollectionProps> = ({ variables, updateColor }) => {
|
||||
const cc = variables.map(colorVar => {
|
||||
const { name, description, value } = colorVar;
|
||||
|
||||
return (
|
||||
<ColorPicker
|
||||
key={name}
|
||||
value={value}
|
||||
name={name}
|
||||
description={description}
|
||||
onChange={updateColor}
|
||||
/>
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{cc}</>;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
export default function Appearance() {
|
||||
@ -144,12 +167,12 @@ export default function Appearance() {
|
||||
setCustomValues(c);
|
||||
}, [appearanceVariables]);
|
||||
|
||||
const updateColor = (variable: string, color: string, description: string) => {
|
||||
setCustomValues({
|
||||
...customValues,
|
||||
const updateColor = useCallback((variable: string, color: string, description: string) => {
|
||||
setCustomValues(oldCustomValues => ({
|
||||
...oldCustomValues,
|
||||
[variable]: { value: color, description },
|
||||
});
|
||||
};
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const reset = async () => {
|
||||
await postConfigUpdateToAPI({
|
||||
@ -193,34 +216,18 @@ export default function Appearance() {
|
||||
updateColor(variableName, `${value.toString()}px`, '');
|
||||
};
|
||||
|
||||
type ColorCollectionProps = {
|
||||
variables: { name; description }[];
|
||||
};
|
||||
// eslint-disable-next-line react/no-unstable-nested-components
|
||||
const ColorCollection: FC<ColorCollectionProps> = ({ variables }) => {
|
||||
const cc = variables.map(colorVar => {
|
||||
const source = customValues?.[colorVar.name] ? customValues : defaultValues;
|
||||
const { name, description } = colorVar;
|
||||
const { value } = source[name];
|
||||
|
||||
return (
|
||||
<ColorPicker
|
||||
key={name}
|
||||
value={value}
|
||||
name={name}
|
||||
description={description}
|
||||
onChange={updateColor}
|
||||
/>
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{cc}</>;
|
||||
};
|
||||
|
||||
if (!defaultValues) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
const transformToColorMap = variables =>
|
||||
variables.map(colorVar => {
|
||||
const source = customValues?.[colorVar.name] ? customValues : defaultValues;
|
||||
const { name, description } = colorVar;
|
||||
const { value } = source[name];
|
||||
return { name, description, value };
|
||||
});
|
||||
|
||||
return (
|
||||
<Space direction="vertical">
|
||||
<Title>Customize Appearance</Title>
|
||||
@ -232,15 +239,20 @@ export default function Appearance() {
|
||||
Certain sections of the interface can be customized by selecting new colors for them.
|
||||
</p>
|
||||
<Row gutter={[16, 16]}>
|
||||
<ColorCollection variables={componentColorVariables} />
|
||||
<ColorCollection
|
||||
variables={transformToColorMap(componentColorVariables)}
|
||||
updateColor={updateColor}
|
||||
/>
|
||||
</Row>
|
||||
</Panel>
|
||||
<Panel header={<Title level={3}>Chat User Colors</Title>} key="2">
|
||||
<Row gutter={[16, 16]}>
|
||||
<ColorCollection variables={chatColorVariables} />
|
||||
<ColorCollection
|
||||
variables={transformToColorMap(chatColorVariables)}
|
||||
updateColor={updateColor}
|
||||
/>
|
||||
</Row>
|
||||
</Panel>
|
||||
|
||||
<Panel header={<Title level={3}>Other Settings</Title>} key="4">
|
||||
How rounded should corners be?
|
||||
<Row gutter={[16, 16]}>
|
||||
|
Loading…
x
Reference in New Issue
Block a user