[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:
Aylong
2024-04-19 20:02:24 +00:00
committed by GitHub
parent a95373f303
commit 9abfe95495
23 changed files with 1088 additions and 276 deletions
+63
View File
@@ -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;
+1
View File
@@ -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';
+25 -36
View File
@@ -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>
</>
);
};
+9 -4
View File
@@ -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%);
}
+1 -1
View File
@@ -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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long