mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-13 00:45:47 +01:00
🎨 Info tooltip component + select pop list bugfix
This commit is contained in:
@@ -17,7 +17,7 @@ import {
|
|||||||
useMantineTheme,
|
useMantineTheme,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { ContextModalProps } from '@mantine/modals';
|
import { ContextModalProps } from '@mantine/modals';
|
||||||
import { IconAlertTriangle, IconPlaylistX, IconPlus, IconAlertCircle } from '@tabler/icons-react';
|
import { IconAlertTriangle, IconPlaylistX, IconPlus, IconInfoCircle } from '@tabler/icons-react';
|
||||||
import { Trans, useTranslation } from 'next-i18next';
|
import { Trans, useTranslation } from 'next-i18next';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
|
|
||||||
@@ -136,7 +136,6 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
handleChange: (key: string, value: IntegrationOptionsValueType) => void;
|
handleChange: (key: string, value: IntegrationOptionsValueType) => void;
|
||||||
}> = ({ option, widgetId, propName: key, value, handleChange }) => {
|
}> = ({ option, widgetId, propName: key, value, handleChange }) => {
|
||||||
const { t } = useTranslation([`modules/${widgetId}`, 'common']);
|
const { t } = useTranslation([`modules/${widgetId}`, 'common']);
|
||||||
const { colorScheme } = useMantineTheme();
|
|
||||||
const info = option.info ?? false;
|
const info = option.info ?? false;
|
||||||
|
|
||||||
switch (option.type) {
|
switch (option.type) {
|
||||||
@@ -149,18 +148,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
|
onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
|
||||||
{...option.inputProps}
|
{...option.inputProps}
|
||||||
/>
|
/>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
case 'text':
|
case 'text':
|
||||||
@@ -168,18 +156,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<TextInput
|
<TextInput
|
||||||
value={value as string}
|
value={value as string}
|
||||||
@@ -193,24 +170,14 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
data={option.data}
|
data={option.data}
|
||||||
value={value as string[]}
|
value={value as string[]}
|
||||||
defaultValue={option.defaultValue}
|
defaultValue={option.defaultValue}
|
||||||
onChange={(v) => handleChange(key, v)}
|
onChange={(v) => handleChange(key, v)}
|
||||||
|
withinPortal
|
||||||
{...option.inputProps}
|
{...option.inputProps}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -220,24 +187,14 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={option.defaultValue}
|
defaultValue={option.defaultValue}
|
||||||
data={option.data}
|
data={option.data}
|
||||||
value={value as string}
|
value={value as string}
|
||||||
onChange={(v) => handleChange(key, v ?? option.defaultValue)}
|
onChange={(v) => handleChange(key, v ?? option.defaultValue)}
|
||||||
|
withinPortal
|
||||||
{...option.inputProps}
|
{...option.inputProps}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -247,18 +204,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
value={value as number}
|
value={value as number}
|
||||||
@@ -272,18 +218,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<Slider
|
<Slider
|
||||||
label={value}
|
label={value}
|
||||||
@@ -333,18 +268,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<StaticDraggableList
|
<StaticDraggableList
|
||||||
value={typedVal}
|
value={typedVal}
|
||||||
@@ -373,18 +297,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
data={value.map((name: any) => ({ value: name, label: name }))}
|
data={value.map((name: any) => ({ value: name, label: name }))}
|
||||||
@@ -409,18 +322,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
<Group align="center" spacing="sm">
|
<Group align="center" spacing="sm">
|
||||||
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
{info &&
|
{info && <InfoTooltip label={t(`descriptor.settings.${key}.info`)}/>}
|
||||||
<Tooltip.Floating
|
|
||||||
label={t(`descriptor.settings.${key}.info`)}
|
|
||||||
position="right-start"
|
|
||||||
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
|
||||||
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
|
||||||
styles={{ tooltip: { maxWidth: 300, }, }}
|
|
||||||
multiline
|
|
||||||
>
|
|
||||||
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
|
||||||
</Tooltip.Floating>
|
|
||||||
}
|
|
||||||
</Group>
|
</Group>
|
||||||
<DraggableList
|
<DraggableList
|
||||||
items={Array.from(value).map((v: any) => ({
|
items={Array.from(value).map((v: any) => ({
|
||||||
@@ -462,3 +364,23 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface InfoTooltipProps {
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InfoTooltip = ({ label }: InfoTooltipProps) => {
|
||||||
|
const { colorScheme } =useMantineTheme();
|
||||||
|
return (
|
||||||
|
<Tooltip.Floating
|
||||||
|
label={label}
|
||||||
|
position="right-start"
|
||||||
|
c={ colorScheme === 'light' ? "black" : "dark.0" }
|
||||||
|
color={ colorScheme === 'light' ? "dark.0" : "dark.6" }
|
||||||
|
styles={{ tooltip: { maxWidth: 300, }, }}
|
||||||
|
multiline
|
||||||
|
>
|
||||||
|
<IconInfoCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
|
||||||
|
</Tooltip.Floating>
|
||||||
|
)
|
||||||
|
};
|
||||||
@@ -11,7 +11,6 @@ import React from 'react';
|
|||||||
|
|
||||||
import { AreaType } from '../types/area';
|
import { AreaType } from '../types/area';
|
||||||
import { ShapeType } from '../types/shape';
|
import { ShapeType } from '../types/shape';
|
||||||
import { boolean } from 'zod';
|
|
||||||
|
|
||||||
// Type of widgets which are saved to config
|
// Type of widgets which are saved to config
|
||||||
export type IWidget<TKey extends string, TDefinition extends IWidgetDefinition> = {
|
export type IWidget<TKey extends string, TDefinition extends IWidgetDefinition> = {
|
||||||
|
|||||||
Reference in New Issue
Block a user