diff --git a/tgui/docs/component-reference.md b/tgui/docs/component-reference.md index 02af4e3aee9..af744b61793 100644 --- a/tgui/docs/component-reference.md +++ b/tgui/docs/component-reference.md @@ -29,6 +29,8 @@ Make sure to add new items to this list if you document new components. - [`Grid.Column`](#gridcolumn) - [`Icon`](#icon) - [`Icon.Stack`](#iconstack) + - [`ImageButton`](#imagebutton) + - [`ImageButton.Item`](#imagebuttonitem) - [`Input`](#input) - [`Knob`](#knob) - [`LabeledControls`](#labeledcontrols) @@ -545,6 +547,67 @@ Renders children icons on top of each other in order to make your own icon. - See inherited props: [Box](#box) - `children: Icon` - Icons to stack. +### `ImageButton` + +A Robust button is specifically for sticking a picture in it. +Has support for base64, spritesheets and URLs. + +**Props:** + +- See inherited props: [Box](#box) +- `asset: boolean` - Enables spritesheets support. +- `vertical: boolean` - Makes the button a inlined vertical rectangle. +- `color: string` - By default, the button is semi-transparent. You can change the overall colour, +all colours are available in KitchenSink in the corresponding section. +- `title: string` - The top text, it will always be bold, and also adds a divider between title and content. +Disabled if there is no content. +- `content: string|any` - All main content, usually text, but you can put in other components if you like. +Makes the vertical button square if empty. +- `selected: boolean` - Makes button selected (green) if true. +- `disabled: boolean` - Makes button disabled (red) if true. Also disables onClick. +- `disabledContent: string` - If button disabled and disabledContent filled, it will be used instead content. +- `image: string` - Base64 image, simple. Disabled if asset support enabled. +- `imageUrl: string` - PNG image or other asset. Make sure you use existing simple asset! Example: imageUrl={'image.png'} +- `imageAsset: string` - If you have enabled asset support, write here which spritesheet to use. +Example: imageAsset={'spritesheet_name64x64'} +- `imageSize: string` - Sets the size of the image and adjusts the size of the button itself accordingly. +Example: imageSize={'64px'} +- `tooltip: string` - A fancy, boxy tooltip, which appears when hovering +over the button. +- `tooltipPosition: string` - Position of the tooltip. See [`Popper`](#Popper) for valid options. +- `ellipsis: boolean` - If button width is constrained, button text will +be truncated with an ellipsis. Be careful however, because this prop breaks +the baseline alignment. +- `children: ImageButton.Item|any` - Items that are added to the right of the horizontal button. +- `onClick: function` - Called when element is clicked. Also enables hover effects. + +### `ImageButton.Item` + +Additional button/s for ImageButton. + +> Try not to add ImageButton.Item in large quantities. They reduce rendering speed very much +> Available only in horizontal mode, if you try add it to vertical, you're gonna be disappointed + +**Props:** +- See inherited props: [Box](#box) +- `color: string` - By default, the button is semi-transparent. You can change the overall colour, +all colours are available in KitchenSink in the corresponding section. +- `content: string|any` - All main content, usually text, but you can put in other components if you like. +Try to not make it too long. +- `selected: boolean` - Makes button selected (green) if true. +- `disabled: boolean` - Makes button disabled (red) if true. Also disables onClick. +- `disabledContent: string` - If button disabled and disabledContent filled, it will be used instead content. +- `tooltip: string` - A fancy, boxy tooltip, which appears when hovering +over the button. +- `tooltipPosition: string` - Position of the tooltip. See [`Popper`](#Popper) for valid options. +- `icon: string` - Adds an icon to the button. By default it will be under content. +- `iconColor: string` - Paints icon if it used. +- `iconPosition: string` - You can make an icon above the content. +Example: iconPosition={'top'} +- `iconSize: number` - Adjusts the size of the icon. +- `children: any` - Similar to content. +- `onClick: function` - Called when element is clicked. + ### `Input` A basic text input, which allow users to enter text into a UI. diff --git a/tgui/packages/tgui/components/ImageButton.js b/tgui/packages/tgui/components/ImageButton.js new file mode 100644 index 00000000000..2b7258497fa --- /dev/null +++ b/tgui/packages/tgui/components/ImageButton.js @@ -0,0 +1,234 @@ +/** + * @file + * @copyright 2024 Aylong (https://github.com/AyIong) + * @license MIT + */ + +import { resolveAsset } from '../assets'; +import { classes, pureComponentHooks } from 'common/react'; +import { computeBoxClassName, computeBoxProps } from './Box'; +import { Icon } from './Icon'; +import { Tooltip } from './Tooltip'; + +export const ImageButton = (props) => { + const { + className, + asset, + color, + title, + vertical, + content, + selected, + disabled, + disabledContent, + image, + imageUrl, + imageAsset, + imageSize, + tooltip, + tooltipPosition, + ellipsis, + children, + onClick, + ...rest + } = props; + rest.onClick = (e) => { + if (!disabled && onClick) { + onClick(e); + } + }; + let buttonContent = ( +
+
+ {asset ? ( +
+ ) : ( + + )} +
+ {content && + (vertical ? ( +
+ {disabled && disabledContent ? disabledContent : content} +
+ ) : ( +
+ {title && ( +
+ {title} +
+
+ )} +
+ {content} +
+
+ ))} +
+ ); + + if (tooltip) { + buttonContent = ( + + {buttonContent} + + ); + } + + return ( +
+ {buttonContent} + {children} +
+ ); +}; + +ImageButton.defaultHooks = pureComponentHooks; + +/** + * That's VERY fucking expensive thing! + * Use it only in places, where it really needed. + * Otherwise, the window opening time may increase by a third! + * Most of the blame is on Icon. + * Maybe it's also because I'm a bit crooked. + * (с) Aylong + */ +export const ImageButtonItem = (props) => { + const { + className, + color, + content, + horizontal, + selected, + disabled, + disabledContent, + tooltip, + tooltipPosition, + icon, + iconColor, + iconPosition, + iconRotation, + iconSize, + onClick, + children, + ...rest + } = props; + rest.onClick = (e) => { + if (!disabled && onClick) { + onClick(e); + } + }; + let itemContent = ( +
+
+
+ {icon && (iconPosition === 'top' || iconPosition === 'left') && ( + + )} +
+ {disabled && disabledContent ? disabledContent : content} + {children} +
+ {icon && !(iconPosition === 'top' || iconPosition === 'left') && ( + + )} +
+
+
+ ); + if (tooltip) { + itemContent = ( + + {itemContent} + + ); + } + + return itemContent; +}; + +ImageButton.Item = ImageButtonItem; diff --git a/tgui/packages/tgui/components/index.js b/tgui/packages/tgui/components/index.js index 8d51f2a6d56..8876792dc99 100644 --- a/tgui/packages/tgui/components/index.js +++ b/tgui/packages/tgui/components/index.js @@ -22,6 +22,7 @@ export { Dropdown } from './Dropdown'; export { Flex } from './Flex'; export { Grid } from './Grid'; export { Icon } from './Icon'; +export { ImageButton } from './ImageButton'; export { Input } from './Input'; export { Knob } from './Knob'; export { LabeledControls } from './LabeledControls'; diff --git a/tgui/packages/tgui/interfaces/PrizeCounter.tsx b/tgui/packages/tgui/interfaces/PrizeCounter.tsx index bbb075248c0..448ad1c4216 100644 --- a/tgui/packages/tgui/interfaces/PrizeCounter.tsx +++ b/tgui/packages/tgui/interfaces/PrizeCounter.tsx @@ -1,6 +1,6 @@ import { classes } from 'common/react'; import { useBackend, useLocalState } from '../backend'; -import { Button, Section, Stack, Input } from '../components'; +import { Button, Section, Stack, ImageButton, Input } from '../components'; import { Window } from '../layouts'; type Prize = { @@ -59,41 +59,30 @@ export const PrizeCounter = (props, context) => { {filteredPrizes.map((prize) => { const disabled = prize.cost > tickets; return ( - - -
- - - - - {prize.name} - - - {prize.desc} - - - -