mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 20:47:10 +01:00
[TGUI] ImageButton component (#24730)
* [TGUI] ImageButton component * Gold color * Prize Counter icon size and color * Rebuild * Little color sorting * Better(?) margin * Rebuild TGUI * horizontal icon * Rebuild TGUI * ms-flexbox -> flex 516 compat
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 = (
|
||||
<div
|
||||
className={classes([
|
||||
vertical ? 'ImageButton__vertical' : 'ImageButton__horizontal',
|
||||
selected && 'ImageButton--selected',
|
||||
disabled && 'ImageButton--disabled',
|
||||
color && typeof color === 'string'
|
||||
? onClick
|
||||
? 'ImageButton--color--clickable--' + color
|
||||
: 'ImageButton--color--' + color
|
||||
: onClick
|
||||
? 'ImageButton--color--default--clickable'
|
||||
: 'ImageButton--color--default',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
tabIndex={!disabled && '0'}
|
||||
{...computeBoxProps(rest)}
|
||||
>
|
||||
<div className={classes(['ImageButton__image'])}>
|
||||
{asset ? (
|
||||
<div className={classes([imageAsset, image])} />
|
||||
) : (
|
||||
<img
|
||||
src={
|
||||
imageUrl
|
||||
? resolveAsset(imageUrl)
|
||||
: `data:image/jpeg;base64,${image}`
|
||||
}
|
||||
style={{
|
||||
width: imageSize,
|
||||
height: imageSize,
|
||||
'-ms-interpolation-mode': 'nearest-neighbor', // Remove after 516 release
|
||||
'image-rendering': 'pixelated',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{content &&
|
||||
(vertical ? (
|
||||
<div
|
||||
className={classes([
|
||||
'ImageButton__content__vertical',
|
||||
ellipsis && 'ImageButton__content--ellipsis',
|
||||
selected && 'ImageButton__content--selected',
|
||||
disabled && 'ImageButton__content--disabled',
|
||||
color && typeof color === 'string'
|
||||
? 'ImageButton__content--color--' + color
|
||||
: 'ImageButton__content--color--default',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
>
|
||||
{disabled && disabledContent ? disabledContent : content}
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes(['ImageButton__content__horizontal'])}>
|
||||
{title && (
|
||||
<div
|
||||
className={classes(['ImageButton__content__horizontal--title'])}
|
||||
>
|
||||
{title}
|
||||
<div
|
||||
className={classes([
|
||||
'ImageButton__content__horizontal--divider',
|
||||
])}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={classes(['ImageButton__content__horizontal--content'])}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (tooltip) {
|
||||
buttonContent = (
|
||||
<Tooltip content={tooltip} position={tooltipPosition}>
|
||||
{buttonContent}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
vertical ? 'ImageButton--vertical' : 'ImageButton--horizontal',
|
||||
])}
|
||||
>
|
||||
{buttonContent}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 = (
|
||||
<div>
|
||||
<div
|
||||
className={classes([
|
||||
'ImageButton__item',
|
||||
selected && 'ImageButton__item--selected',
|
||||
disabled && 'ImageButton__item--disabled',
|
||||
color && typeof color === 'string'
|
||||
? 'ImageButton__item--color--' + color
|
||||
: 'ImageButton__item--color--default',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
tabIndex={!disabled && '0'}
|
||||
{...computeBoxProps(rest)}
|
||||
>
|
||||
<div
|
||||
className={classes([
|
||||
horizontal && 'ImageButton__item--icon--horizontal',
|
||||
computeBoxClassName(rest),
|
||||
className,
|
||||
])}
|
||||
>
|
||||
{icon && (iconPosition === 'top' || iconPosition === 'left') && (
|
||||
<Icon
|
||||
mb={0.5}
|
||||
name={icon}
|
||||
color={iconColor}
|
||||
rotation={iconRotation}
|
||||
size={iconSize}
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
{disabled && disabledContent ? disabledContent : content}
|
||||
{children}
|
||||
</div>
|
||||
{icon && !(iconPosition === 'top' || iconPosition === 'left') && (
|
||||
<Icon
|
||||
mt={0.5}
|
||||
name={icon}
|
||||
color={iconColor}
|
||||
rotation={iconRotation}
|
||||
size={iconSize}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
if (tooltip) {
|
||||
itemContent = (
|
||||
<Tooltip content={tooltip} position={tooltipPosition}>
|
||||
{itemContent}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return itemContent;
|
||||
};
|
||||
|
||||
ImageButton.Item = ImageButtonItem;
|
||||
@@ -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';
|
||||
|
||||
@@ -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 (
|
||||
<Stack key={prize.name} className="PrizeCounter__Item">
|
||||
<Stack.Item lineHeight="0" align="center">
|
||||
<div
|
||||
className={classes([
|
||||
'prize_counter64x64',
|
||||
prize.imageID,
|
||||
])}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item width="100%">
|
||||
<Stack vertical textAlign="center">
|
||||
<Stack.Item bold mt={1}>
|
||||
{prize.name}
|
||||
</Stack.Item>
|
||||
<Stack.Divider />
|
||||
<Stack.Item mb={1}>{prize.desc}</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
className={classes([
|
||||
'PrizeCounter__BuyButton',
|
||||
disabled && 'PrizeCounter__BuyButton--disabled',
|
||||
])}
|
||||
icon="ticket"
|
||||
content={prize.cost}
|
||||
tooltip={disabled ? 'Not enough tickets.' : null}
|
||||
tooltipPosition="top-end"
|
||||
onClick={() =>
|
||||
!disabled &&
|
||||
act('purchase', { 'purchase': prize.itemID })
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
<ImageButton
|
||||
key={prize.name}
|
||||
asset
|
||||
imageAsset={'prize_counter64x64'}
|
||||
image={prize.imageID}
|
||||
title={prize.name}
|
||||
content={prize.desc}
|
||||
>
|
||||
<ImageButton.Item
|
||||
bold
|
||||
width={'64px'}
|
||||
fontSize={1.5}
|
||||
textColor={disabled && 'gray'}
|
||||
content={prize.cost}
|
||||
icon={'ticket'}
|
||||
iconSize={1.6}
|
||||
iconColor={disabled ? 'bad' : 'good'}
|
||||
tooltip={disabled && 'Not enough tickets'}
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
act('purchase', { 'purchase': prize.itemID })
|
||||
}
|
||||
/>
|
||||
</ImageButton>
|
||||
);
|
||||
})}
|
||||
</Section>
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2024 Aylong (https://github.com/AyIong)
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { useLocalState } from '../backend';
|
||||
import {
|
||||
Button,
|
||||
LabeledList,
|
||||
ImageButton,
|
||||
Input,
|
||||
Slider,
|
||||
Section,
|
||||
Stack,
|
||||
} from '../components';
|
||||
|
||||
export const meta = {
|
||||
title: 'ImageButton',
|
||||
render: () => <Story />,
|
||||
};
|
||||
|
||||
const COLORS_SPECTRUM = [
|
||||
'red',
|
||||
'orange',
|
||||
'yellow',
|
||||
'olive',
|
||||
'green',
|
||||
'teal',
|
||||
'blue',
|
||||
'violet',
|
||||
'purple',
|
||||
'pink',
|
||||
'brown',
|
||||
'grey',
|
||||
'gold',
|
||||
];
|
||||
|
||||
const COLORS_STATES = ['good', 'average', 'bad', 'black', 'white'];
|
||||
|
||||
const Story = (props, context) => {
|
||||
const [disabled, setDisabled] = useLocalState(context, 'disabled', false);
|
||||
const [onClick, setOnClick] = useLocalState(context, 'onClick', true);
|
||||
const [vertical1, setVertical1] = useLocalState(context, 'vertical1', true);
|
||||
const [vertical2, setVertical2] = useLocalState(context, 'vertical2', true);
|
||||
const [vertical3, setVertical3] = useLocalState(context, 'vertical3', false);
|
||||
const [title, setTitle] = useLocalState(context, 'title', 'Image Button');
|
||||
const [content, setContent] = useLocalState(
|
||||
context,
|
||||
'content',
|
||||
'Image is a LIE!'
|
||||
);
|
||||
const [itemContent, setItemContent] = useLocalState(
|
||||
context,
|
||||
'itemContent',
|
||||
'Second Button'
|
||||
);
|
||||
const [itemIcon, setItemIcon] = useLocalState(
|
||||
context,
|
||||
'itemIcon',
|
||||
'face-smile'
|
||||
);
|
||||
|
||||
const [itemIconPos, setItemIconPos] = useLocalState(
|
||||
context,
|
||||
'itemIconPos',
|
||||
'default'
|
||||
);
|
||||
|
||||
const [itemIconSize, setItemIconSize] = useLocalState(
|
||||
context,
|
||||
'itemIconSize',
|
||||
2
|
||||
);
|
||||
|
||||
const [imageSize, setImageSize] = useLocalState(context, 'imageSize', 64);
|
||||
|
||||
const toggleVertical1 = () => {
|
||||
setVertical1(!vertical1);
|
||||
};
|
||||
|
||||
const toggleVertical2 = () => {
|
||||
setVertical2(!vertical2);
|
||||
};
|
||||
|
||||
const toggleVertical3 = () => {
|
||||
setVertical3(!vertical3);
|
||||
};
|
||||
|
||||
const toggleDisabled = () => {
|
||||
setDisabled(!disabled);
|
||||
};
|
||||
|
||||
const toggleOnClick = () => {
|
||||
setOnClick(!onClick);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Section>
|
||||
<Stack>
|
||||
<Stack.Item basis="50%">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Title">
|
||||
<Input value={title} onInput={(e, value) => setTitle(value)} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Content">
|
||||
<Input
|
||||
value={content}
|
||||
onInput={(e, value) => setContent(value)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Image Size">
|
||||
<Slider
|
||||
animated
|
||||
width={10}
|
||||
value={imageSize}
|
||||
minValue={0}
|
||||
maxValue={256}
|
||||
step={1}
|
||||
stepPixelSize={2}
|
||||
onChange={(e, value) => setImageSize(value)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
<Stack mt={1} mr={2}>
|
||||
<Stack.Item grow>
|
||||
<Button.Checkbox
|
||||
fluid
|
||||
content="onClick"
|
||||
checked={onClick}
|
||||
onClick={toggleOnClick}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Button.Checkbox
|
||||
fluid
|
||||
content="Vertical"
|
||||
checked={vertical3}
|
||||
onClick={toggleVertical3}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item basis="50%">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Item Content">
|
||||
<Input
|
||||
value={itemContent}
|
||||
onInput={(e, value) => setItemContent(value)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Item Icon">
|
||||
<Input
|
||||
value={itemIcon}
|
||||
onInput={(e, value) => setItemIcon(value)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Item IconPos">
|
||||
<Input
|
||||
value={itemIconPos}
|
||||
onInput={(e, value) => setItemIconPos(value)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Item IconSize">
|
||||
<Slider
|
||||
animated
|
||||
width={10}
|
||||
value={itemIconSize}
|
||||
minValue={0}
|
||||
maxValue={20}
|
||||
step={1}
|
||||
stepPixelSize={10}
|
||||
onChange={(e, value) => setItemIconSize(value)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
<Stack.Item mt={1}>
|
||||
<ImageButton
|
||||
width={vertical3 && `${imageSize}px`}
|
||||
ellipsis={vertical3}
|
||||
vertical={vertical3}
|
||||
disabled={disabled}
|
||||
title={title}
|
||||
content={content}
|
||||
tooltip={
|
||||
vertical3
|
||||
? content
|
||||
: 'Cool and simple buttons with images, FOR ALL!!!'
|
||||
}
|
||||
image={
|
||||
'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'
|
||||
}
|
||||
imageSize={`${imageSize}px`}
|
||||
onClick={onClick ? () => 'false' : ''}
|
||||
>
|
||||
{!vertical3 && (
|
||||
<ImageButton.Item
|
||||
bold
|
||||
width={'64px'}
|
||||
selected={disabled}
|
||||
content={itemContent}
|
||||
tooltip="Click to disable main button"
|
||||
tooltipPosition="bottom-end"
|
||||
icon={itemIcon}
|
||||
iconColor={'gold'}
|
||||
iconSize={itemIconSize}
|
||||
iconPosition={itemIconPos}
|
||||
onClick={toggleDisabled}
|
||||
/>
|
||||
)}
|
||||
</ImageButton>
|
||||
</Stack.Item>
|
||||
</Section>
|
||||
<Section
|
||||
title="Color States"
|
||||
buttons={
|
||||
<Button.Checkbox
|
||||
content="Vertical"
|
||||
checked={vertical1}
|
||||
onClick={toggleVertical1}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{COLORS_STATES.map((color) => (
|
||||
<ImageButton
|
||||
m={vertical1 ? 0.5 : 0}
|
||||
vertical={vertical1}
|
||||
key={color}
|
||||
color={color}
|
||||
content={color}
|
||||
image={
|
||||
'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAOVBMVEXAwMDBr16vk0uORiz/o7HyfxiZbDXWzMzhbA3//wD////tHCQAAP/4ior/ADOAgIDAwMAAAAAzmQDdkuRxAAAAAXRSTlMAQObYZgAAAKxJREFUOI3dksESgyAMRG0FE4I22P//2IaAVdB0em3Xy477SJYZhuFfdDO1AXdD4xtwRd77o5t6wKt20wPlN2QVewUgQqAAiD0QYxQCJYc5zCAEtisUcBkgmUAZ6ErGWh9oeSwE6k+3yHNACIIPgMzQONsWYOZ90QXAiRK7g2K7gtNKayXKjdoOcv4pX+IcGoBMqIA26TswSU6HmueSpLlRcjK0AaOpL97rb+gFHckLe1QlljQAAAAASUVORK5CYII='
|
||||
}
|
||||
imageSize={vertical1 ? '48px' : '24px'}
|
||||
onClick={onClick ? () => 'false' : ''}
|
||||
/>
|
||||
))}
|
||||
</Section>
|
||||
<Section
|
||||
title="Available Colors"
|
||||
buttons={
|
||||
<Button.Checkbox
|
||||
content="Vertical"
|
||||
checked={vertical2}
|
||||
onClick={toggleVertical2}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{COLORS_SPECTRUM.map((color) => (
|
||||
<ImageButton
|
||||
m={vertical2 ? 0.5 : 0}
|
||||
vertical={vertical2}
|
||||
key={color}
|
||||
color={color}
|
||||
content={color}
|
||||
image={
|
||||
'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAJ1BMVEUAAABeGFCgXZN2PnKqqqq/vr/T09PycWFIHUFeKlNLHEtVWWOOj5g02k6OAAAAAXRSTlMAQObYZgAAAFdJREFUKJFjYBhEgFEQDATgAkImLkDgrIgQME0vSy8LRhYoBwISBdLLy1HNSCsvT0MWwLDWGAwQAp0rZ+3evXLWDGSBM2dQBWYCAUkCHB1g0IAreAYCAACm2zDykxPL4AAAAABJRU5ErkJggg=='
|
||||
}
|
||||
imageSize={vertical2 ? '48px' : '24px'}
|
||||
onClick={onClick ? () => 'false' : ''}
|
||||
/>
|
||||
))}
|
||||
</Section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -8,8 +8,6 @@
|
||||
@use 'sass:meta';
|
||||
|
||||
// Base colors
|
||||
$black: #000000 !default;
|
||||
$white: #ffffff !default;
|
||||
$red: #db2828 !default;
|
||||
$orange: #f2711c !default;
|
||||
$yellow: #fbd608 !default;
|
||||
@@ -22,12 +20,18 @@ $purple: #a333c8 !default;
|
||||
$pink: #e03997 !default;
|
||||
$brown: #a5673f !default;
|
||||
$grey: #767676 !default;
|
||||
|
||||
$primary: #4972a1 !default;
|
||||
$label: #7e90a7 !default;
|
||||
|
||||
// State colors
|
||||
$good: #5baa27 !default;
|
||||
$average: #f08f11 !default;
|
||||
$bad: #db2828 !default;
|
||||
$label: #7e90a7 !default;
|
||||
$black: #000000 !default;
|
||||
$white: #ffffff !default;
|
||||
|
||||
// Custom colors
|
||||
$gold: #f2a918 !default;
|
||||
|
||||
// Background and foreground color lightness ratios
|
||||
$bg-lightness: -15% !default;
|
||||
@@ -62,6 +66,7 @@ $_gen_map: (
|
||||
'average': $average,
|
||||
'bad': $bad,
|
||||
'label': $label,
|
||||
'gold': $gold,
|
||||
);
|
||||
|
||||
// Foreground color names for which to generate a color map
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Aylong (https://github.com/AyIong)
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
@use '../base.scss';
|
||||
@use '../colors.scss';
|
||||
@use './Divider.scss';
|
||||
@use '../functions.scss' as *;
|
||||
|
||||
$color-default: colors.bg(base.$color-bg-section) !default;
|
||||
$color-disabled: #4d1717 !default;
|
||||
$color-selected: colors.bg(colors.$green) !default;
|
||||
$bg-map: colors.$bg-map !default;
|
||||
|
||||
@mixin button-style($color, $clickable: false) {
|
||||
$luminance: luminance($color);
|
||||
|
||||
background-color: rgba($color, 0.15);
|
||||
border: base.em(1px) solid rgba(lighten($color, 50%), 0.2);
|
||||
|
||||
@if $clickable {
|
||||
transition:
|
||||
color 100ms,
|
||||
background-color 100ms;
|
||||
|
||||
&:focus {
|
||||
transition:
|
||||
color 250ms,
|
||||
background-color 250ms;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(lighten($color, 25%), 0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ImageButton__image {
|
||||
line-height: 0;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.ImageButton__vertical,
|
||||
.ImageButton--vertical {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ImageButton__horizontal {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ImageButton--horizontal {
|
||||
display: flex;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
@each $color-name, $color-value in $bg-map {
|
||||
.ImageButton--color--#{$color-name} {
|
||||
@include button-style($color-value);
|
||||
}
|
||||
|
||||
.ImageButton--color--clickable--#{$color-name} {
|
||||
@include button-style($color-value, true);
|
||||
}
|
||||
}
|
||||
|
||||
.ImageButton--color--default {
|
||||
@include button-style(rgba(lighten($color-default, 100%), 0.2));
|
||||
}
|
||||
|
||||
.ImageButton--color--default--clickable {
|
||||
@include button-style(rgba(lighten($color-default, 100%), 0.2), true);
|
||||
}
|
||||
|
||||
.ImageButton--disabled {
|
||||
background-color: rgba($color-disabled, 0.25) !important;
|
||||
border: base.em(1px) solid rgba(lighten($color-disabled, 100%), 0.15);
|
||||
}
|
||||
|
||||
.ImageButton--selected {
|
||||
@include button-style($color-selected, true);
|
||||
}
|
||||
|
||||
.ImageButton__content__vertical {
|
||||
height: 1.6em;
|
||||
padding-top: 2px;
|
||||
border: 0;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ImageButton__content__horizontal {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.ImageButton__content__horizontal--title {
|
||||
font-weight: bold;
|
||||
padding: base.em(6px);
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.ImageButton__content__horizontal--content {
|
||||
padding: base.em(6px);
|
||||
}
|
||||
|
||||
.ImageButton__content__horizontal--divider {
|
||||
margin: base.em(6px);
|
||||
margin-bottom: 0;
|
||||
border-top: Divider.$thickness solid Divider.$color;
|
||||
}
|
||||
|
||||
.ImageButton__content--ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@mixin content-style($color) {
|
||||
$luminance: luminance($color);
|
||||
$text-color: if($luminance > 0.3, rgba(0, 0, 0, 0.9), rgba(255, 255, 255, 1));
|
||||
|
||||
color: $text-color;
|
||||
background-color: darken($color, 2.5%);
|
||||
border-top: base.em(1px) solid (rgba(lighten($color, 33%), 1));
|
||||
}
|
||||
|
||||
@each $color-name, $color-value in $bg-map {
|
||||
.ImageButton__content--color--#{$color-name} {
|
||||
@include content-style(rgba($color-value, 1));
|
||||
}
|
||||
}
|
||||
|
||||
.ImageButton__content--color--default {
|
||||
@include content-style(rgba(lighten($color-default, 80%), 1));
|
||||
}
|
||||
|
||||
.ImageButton__content--disabled {
|
||||
background-color: $color-disabled !important;
|
||||
color: rgba(200, 200, 200, 0.75);
|
||||
border-top: base.em(1px) solid rgba(lighten($color-disabled, 100%), 0.5);
|
||||
}
|
||||
|
||||
.ImageButton__content--selected {
|
||||
background-color: $color-selected !important;
|
||||
border-top: base.em(1px) solid rgba(lighten($color-selected, 100%), 0.5);
|
||||
}
|
||||
|
||||
.ImageButton__item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ImageButton__item--icon--horizontal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.fa,
|
||||
.fas,
|
||||
.far {
|
||||
margin-left: 0.2em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin item-style($color) {
|
||||
$luminance: luminance($color);
|
||||
|
||||
transition:
|
||||
color 100ms,
|
||||
background-color 100ms;
|
||||
background-color: rgba($color, 0.4);
|
||||
border: base.em(1px) solid rgba(lighten($color, 50%), 0.2);
|
||||
border-left: 0;
|
||||
|
||||
&:focus {
|
||||
transition:
|
||||
color 250ms,
|
||||
background-color 250ms;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(lighten($color, 25%), 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@each $color-name, $color-value in $bg-map {
|
||||
.ImageButton__item--color--#{$color-name} {
|
||||
@include item-style(rgba($color-value, 1));
|
||||
}
|
||||
}
|
||||
|
||||
.ImageButton__item--color--default {
|
||||
@include item-style(rgba(lighten($color-default, 100%), 1));
|
||||
}
|
||||
|
||||
.ImageButton__item--disabled {
|
||||
background-color: rgba($color-disabled, 0.5) !important;
|
||||
border: base.em(1px) solid rgba(lighten($color-disabled, 100%), 0.15);
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.ImageButton__item--selected {
|
||||
@include item-style($color-selected);
|
||||
border-left: 0;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
@use '../base.scss';
|
||||
|
||||
$background-color: rgba(0, 0, 0, 0.33) !default;
|
||||
$text-color: rgba(255, 255, 255) !default;
|
||||
|
||||
.PrizeCounter__BuyButton {
|
||||
width: 64px;
|
||||
height: 100%;
|
||||
padding-top: 0.25em;
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
background-color: lighten($background-color, 25%);
|
||||
color: darken($text-color, 25%);
|
||||
|
||||
transition:
|
||||
color 100ms,
|
||||
background-color 100ms;
|
||||
|
||||
&:hover {
|
||||
background-color: lighten($background-color, 33%);
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.fa,
|
||||
.fas,
|
||||
.far {
|
||||
color: rgba(60, 255, 60, 0.66);
|
||||
transform: scale(1.6);
|
||||
position: absolute;
|
||||
top: 2.1em;
|
||||
left: 1.4em;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
background-color: rgba(255, 50, 50, 0.1);
|
||||
color: darken($text-color, 50%);
|
||||
.fa,
|
||||
.fas,
|
||||
.far {
|
||||
color: rgba(255, 60, 60, 0.66);
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: rgba(255, 50, 50, 0.1);
|
||||
color: darken($text-color, 50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.PrizeCounter__Item {
|
||||
margin-bottom: base.em(6px);
|
||||
background-color: rgba(125, 125, 125, 0.05);
|
||||
border: base.em(1px) solid lighten($background-color, 25%);
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
@include meta.load-css('./components/Dropdown.scss');
|
||||
@include meta.load-css('./components/Flex.scss');
|
||||
@include meta.load-css('./components/Icon.scss');
|
||||
@include meta.load-css('./components/ImageButton.scss');
|
||||
@include meta.load-css('./components/Input.scss');
|
||||
@include meta.load-css('./components/Knob.scss');
|
||||
@include meta.load-css('./components/LabeledList.scss');
|
||||
@@ -59,7 +60,6 @@
|
||||
@include meta.load-css('./interfaces/PDA.scss');
|
||||
@include meta.load-css('./interfaces/PdaPainter.scss');
|
||||
@include meta.load-css('./interfaces/PoolController.scss');
|
||||
@include meta.load-css('./interfaces/PrizeCounter.scss');
|
||||
@include meta.load-css('./interfaces/RndConsole.scss');
|
||||
@include meta.load-css('./interfaces/Roulette.scss');
|
||||
@include meta.load-css('./interfaces/Safe.scss');
|
||||
|
||||
@@ -32,6 +32,14 @@
|
||||
'color-danger': #9a9d00
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(colors.$primary, 20%),
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #465899
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/Input.scss',
|
||||
$with: ('border-color': #404b6e)
|
||||
|
||||
@@ -33,6 +33,14 @@
|
||||
'color-danger': #9a9d00
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': #117039,
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #9d0808
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/NumberInput.scss',
|
||||
$with: ('border-color': #fff)
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
'../components/Button.scss',
|
||||
$with: ('color-default': colors.$primary, 'color-selected': #188552)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(colors.$primary, 20%),
|
||||
'color-selected': #188552
|
||||
)
|
||||
);
|
||||
@include meta.load-css('../components/Section.scss');
|
||||
@include meta.load-css(
|
||||
'../components/Tabs.scss',
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
'color-selected': #00ff00
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(colors.$primary, 25%),
|
||||
'color-disabled': #363636,
|
||||
'color-selected': lighten(colors.$primary, 25%)
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/Input.scss',
|
||||
$with: ('border-color': colors.$primary)
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
'color-danger': #9a9d00
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(colors.$primary, 20%),
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #1e5881
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/Input.scss',
|
||||
$with: ('border-color': #910101)
|
||||
|
||||
@@ -25,6 +25,10 @@ $nanotrasen: #384e68;
|
||||
'color-transparent-text': rgba(227, 240, 255, 0.75)
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: ('color-default': darken($nanotrasen, 15%))
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ProgressBar.scss',
|
||||
$with: (
|
||||
|
||||
@@ -46,6 +46,14 @@ $font-size: 24px;
|
||||
'color-transparent-text': rgba(0, 0, 0, 0.5)
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(#e8e4c9, 40%),
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #9d0808
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ProgressBar.scss',
|
||||
$with: ('color-disabled': #363636)
|
||||
|
||||
@@ -34,6 +34,14 @@
|
||||
'color-danger': #9a9d00
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(#e8e4c9, 40%),
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #9d0808
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ProgressBar.scss',
|
||||
$with: ('background-color': rgba(0, 0, 0, 0.5))
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
'../components/Button.scss',
|
||||
$with: ('color-default': colors.$primary)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: ('color-default': darken(colors.$primary, 23%))
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/Input.scss',
|
||||
$with: ('border-color': #ff8d88)
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
'color-danger': #9a9d00
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/ImageButton.scss',
|
||||
$with: (
|
||||
'color-default': darken(colors.$primary, 20%),
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #9d0808
|
||||
)
|
||||
);
|
||||
@include meta.load-css(
|
||||
'../components/Input.scss',
|
||||
$with: ('border-color': #87ce87)
|
||||
|
||||
File diff suppressed because one or more lines are too long
+110
-102
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+84
-76
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user