mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 06:56:03 +01:00
feat(web/meu): support images as icons in context and list menu (#230)
* feat: Support image Tag in buttons in my server. ox_lib is heavily used. most of sample use cases for this is. Food image, Ingredients, Vehicle Parts, etc.. i believe font awesome is not enough for some use cases. i did suggest this on v3 pending PR. but it seems gets ignored. here i am gonna try to push this PR. to use this. icon must be not existing in the options. if both icon and image is in options, nothing will appear. image in metadata will still appear normaly. * tweak(web/menu): resize render image comparable to FA * refactor(web/context): use icon prop for images * refactor(web/list): use icon prop for images --------- Co-authored-by: Luke <39926192+LukeWasTakenn@users.noreply.github.com>
This commit is contained in:
@@ -6,7 +6,7 @@ interface ContextMenuItem {
|
||||
description?: string;
|
||||
arrow?: boolean;
|
||||
image?: string;
|
||||
icon?: IconName | [IconPrefix, IconName];
|
||||
icon?: IconName | [IconPrefix, IconName] | string;
|
||||
iconColor?: string;
|
||||
progress?: number;
|
||||
colorScheme?: string;
|
||||
|
||||
@@ -5,7 +5,7 @@ type ChangeFunction = (selected: number, scrollIndex?: number, args?: any, check
|
||||
|
||||
interface MenuOptions {
|
||||
label: string;
|
||||
icon?: IconName | [IconPrefix, IconName];
|
||||
icon?: IconName | [IconPrefix, IconName] | string;
|
||||
checked?: boolean;
|
||||
values?: Array<string | { label: string; description: string }>;
|
||||
description?: string;
|
||||
|
||||
@@ -3,6 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { Option, ContextMenuProps } from '../../../../typings';
|
||||
import { fetchNui } from '../../../../utils/fetchNui';
|
||||
import { isIconUrl } from '../../../../utils/isIconUrl';
|
||||
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||
|
||||
const openMenu = (id: string | undefined) => {
|
||||
fetchNui<ContextMenuProps>('openContext', { id: id, back: false });
|
||||
@@ -21,6 +23,9 @@ const useStyles = createStyles((theme, params: { disabled?: boolean }) => ({
|
||||
color: params.disabled ? theme.colors.dark[3] : theme.colors.dark[0],
|
||||
whiteSpace: 'pre-wrap',
|
||||
},
|
||||
iconImage: {
|
||||
maxWidth: '25px',
|
||||
},
|
||||
description: {
|
||||
color: params.disabled ? theme.colors.dark[3] : theme.colors.dark[2],
|
||||
},
|
||||
@@ -63,7 +68,16 @@ const ContextButton: React.FC<{
|
||||
<Group spacing={8} noWrap>
|
||||
{button?.icon && (
|
||||
<Stack w={25} h={25} justify="center" align="center">
|
||||
<FontAwesomeIcon icon={button.icon} fixedWidth size="lg" style={{ color: button.iconColor }} />
|
||||
{typeof button.icon === 'string' && isIconUrl(button.icon) ? (
|
||||
<img src={button.icon} className={classes.iconImage} alt="Missing img" />
|
||||
) : (
|
||||
<FontAwesomeIcon
|
||||
icon={button.icon as IconProp}
|
||||
fixedWidth
|
||||
size="lg"
|
||||
style={{ color: button.iconColor }}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
<Text sx={{ overflowWrap: 'break-word' }}>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Box, Group, Stack, Text, Progress } from '@mantine/core';
|
||||
import { Box, Group, Stack, Text, Progress, Image } from '@mantine/core';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import React, { forwardRef } from 'react';
|
||||
import CustomCheckbox from './CustomCheckbox';
|
||||
import type { MenuItem } from '../../../typings';
|
||||
import { createStyles } from '@mantine/core';
|
||||
import { isIconUrl } from '../../../utils/isIconUrl';
|
||||
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||
|
||||
interface Props {
|
||||
item: MenuItem;
|
||||
@@ -24,6 +26,9 @@ const useStyles = createStyles((theme, params: { iconColor?: string }) => ({
|
||||
outline: 'none',
|
||||
},
|
||||
},
|
||||
iconImage: {
|
||||
maxWidth: 32,
|
||||
},
|
||||
buttonWrapper: {
|
||||
paddingLeft: 5,
|
||||
paddingRight: 12,
|
||||
@@ -32,6 +37,8 @@ const useStyles = createStyles((theme, params: { iconColor?: string }) => ({
|
||||
iconContainer: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
width: 32,
|
||||
height: 32,
|
||||
},
|
||||
icon: {
|
||||
fontSize: 24,
|
||||
@@ -79,7 +86,11 @@ const ListItem = forwardRef<Array<HTMLDivElement | null>, Props>(({ item, index,
|
||||
<Group spacing={15} noWrap className={classes.buttonWrapper}>
|
||||
{item.icon && (
|
||||
<Box className={classes.iconContainer}>
|
||||
<FontAwesomeIcon icon={item.icon} className={classes.icon} fixedWidth />
|
||||
{typeof item.icon === 'string' && isIconUrl(item.icon) ? (
|
||||
<img src={item.icon} alt="Missing image" className={classes.iconImage} />
|
||||
) : (
|
||||
<FontAwesomeIcon icon={item.icon as IconProp} className={classes.icon} fixedWidth />
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{Array.isArray(item.values) ? (
|
||||
|
||||
@@ -6,7 +6,7 @@ export interface Option {
|
||||
description?: string;
|
||||
arrow?: boolean;
|
||||
image?: string;
|
||||
icon?: IconProp;
|
||||
icon?: IconProp | string;
|
||||
iconColor?: string;
|
||||
progress?: number;
|
||||
colorScheme?: string;
|
||||
|
||||
@@ -3,13 +3,14 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||
export type MenuPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
||||
|
||||
export interface MenuItem {
|
||||
image?: string;
|
||||
label: string;
|
||||
progress?: number;
|
||||
colorScheme?: string;
|
||||
checked?: boolean;
|
||||
values?: Array<string | { label: string; description: string }>;
|
||||
description?: string;
|
||||
icon?: IconProp;
|
||||
icon?: IconProp | string;
|
||||
iconColor?: string;
|
||||
defaultIndex?: number;
|
||||
close?: boolean;
|
||||
|
||||
1
web/src/utils/isIconUrl.ts
Normal file
1
web/src/utils/isIconUrl.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const isIconUrl = (icon: string) => icon.includes('://') || icon.includes('.png') || icon.includes('.webp');
|
||||
Reference in New Issue
Block a user