Allows TGUI labelled lists to use tooltips, and enables this behavior on preferencelists + adds descs to most character preferences (#79356)

## About The Pull Request

Title.


https://github.com/tgstation/tgstation/assets/59709059/c9fa7d41-6ca4-4b8b-97ec-fdfdd437ce25

## Why It's Good For The Game

The inability to use descriptions in character preferences really limits
the context you can give to readers, which becomes a big problem when
preferences become complicated or laden with policy that must be given
to the reader.
## Changelog
🆑
qol: Character preferences now have descriptions as tooltips - hover
over their names to see them
/🆑
This commit is contained in:
nikothedude
2023-11-03 12:32:51 -04:00
committed by GitHub
parent 29ee0e61bf
commit 4e4e8266ac
9 changed files with 62 additions and 26 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ export const savefile_key_here: Feature<T> = {
// Necessary for game preferences, unused for others
category: "CATEGORY",
// Optional, only shown in game preferences
// Optional, shown as a tooltip
description: "This preference will blow your mind!",
}
```
+51 -23
View File
@@ -8,6 +8,7 @@ import { BooleanLike, classes, pureComponentHooks } from 'common/react';
import { InfernoNode } from 'inferno';
import { Box, unit } from './Box';
import { Divider } from './Divider';
import { Tooltip } from './Tooltip';
type LabeledListProps = {
children?: any;
@@ -20,19 +21,20 @@ export const LabeledList = (props: LabeledListProps) => {
LabeledList.defaultHooks = pureComponentHooks;
type LabeledListItemProps = {
className?: string | BooleanLike;
label?: string | InfernoNode | BooleanLike;
labelColor?: string | BooleanLike;
labelWrap?: boolean;
color?: string | BooleanLike;
textAlign?: string | BooleanLike;
buttons?: InfernoNode;
type LabeledListItemProps = Partial<{
className: string | BooleanLike;
label: string | InfernoNode | BooleanLike;
labelColor: string | BooleanLike;
labelWrap: boolean;
color: string | BooleanLike;
textAlign: string | BooleanLike;
buttons: InfernoNode;
/** @deprecated */
content?: any;
children?: InfernoNode;
verticalAlign?: string;
};
content: any;
children: InfernoNode;
verticalAlign: string;
tooltip: string;
}>;
const LabeledListItem = (props: LabeledListItemProps) => {
const {
@@ -46,20 +48,46 @@ const LabeledListItem = (props: LabeledListItemProps) => {
content,
children,
verticalAlign = 'baseline',
tooltip,
} = props;
let innerLabel;
if (label) {
innerLabel = label;
if (typeof label === 'string') innerLabel += ':';
}
if (tooltip !== undefined) {
innerLabel = (
<Tooltip content={tooltip}>
<Box
as="span"
style={{
'border-bottom': '2px dotted rgba(255, 255, 255, 0.8)',
}}>
{innerLabel}
</Box>
</Tooltip>
);
}
let labelChild = (
<Box
as="td"
color={labelColor}
className={classes([
'LabeledList__cell',
// Kinda flipped because we want nowrap as default. Cleaner CSS this way though.
!labelWrap && 'LabeledList__label--nowrap',
])}
verticalAlign={verticalAlign}>
{innerLabel}
</Box>
);
return (
<tr className={classes(['LabeledList__row', className])}>
<Box
as="td"
color={labelColor}
className={classes([
'LabeledList__cell',
// Kinda flipped because we want nowrap as default. Cleaner CSS this way though.
!labelWrap && 'LabeledList__label--nowrap',
])}
verticalAlign={verticalAlign}>
{label ? (typeof label === 'string' ? label + ':' : label) : null}
</Box>
{labelChild}
<Box
as="td"
color={color}
@@ -378,6 +378,7 @@ const PreferenceList = (props: {
<LabeledList.Item
key={featureId}
label={feature.name}
tooltip={feature.description}
verticalAlign="middle">
<Stack fill>
{randomSetting && (
@@ -2,5 +2,7 @@ import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base';
export const preferred_ai_emote_display: FeatureWithIcons<string> = {
name: 'AI emote display',
description:
'If you are the AI, the default image displayed on all AI displays on station.',
component: FeatureIconnedDropdownInput,
};
@@ -2,5 +2,6 @@ import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base';
export const preferred_ai_hologram_display: FeatureWithIcons<string> = {
name: 'AI hologram display',
description: 'The holographic form you will take when you use a holopad.',
component: FeatureIconnedDropdownInput,
};
@@ -3,12 +3,10 @@ import { Feature, FeatureChoiced, FeatureDropdownInput, FeatureShortTextInput }
export const pda_theme: FeatureChoiced = {
name: 'PDA Theme',
category: 'GAMEPLAY',
description: 'The theme of your PDA.',
component: FeatureDropdownInput,
};
export const pda_ringtone: Feature<string> = {
name: 'PDA Ringtone',
description: "The ringtone you'll hear when someone sends you a PDA message.",
component: FeatureShortTextInput,
};
@@ -2,5 +2,7 @@ import { CheckboxInput, FeatureToggle } from '../base';
export const persistent_scars: FeatureToggle = {
name: 'Persistent Scars',
description:
'If checked, scars will persist across rounds if you survive to the end.',
component: CheckboxInput,
};
@@ -2,5 +2,7 @@ import { CheckboxInput, FeatureToggle } from '../base';
export const playtime_reward_cloak: FeatureToggle = {
name: 'Don gamer cloak',
description:
'Your reward for playing 5k+ hours. Don a fancy cloak only wearable by fellow super-veterans.',
component: CheckboxInput,
};
@@ -2,5 +2,7 @@ import { FeatureChoiced, FeatureDropdownInput } from '../base';
export const prisoner_crime: FeatureChoiced = {
name: 'Prisoner crime',
description:
'When a prisoner, this will be added to your records as the reason for your arrest.',
component: FeatureDropdownInput,
};