Skip to content

Commit 57a9edb

Browse files
committed
feat(game): refactor styling to use css prop and add style props for customization
1 parent 27207ec commit 57a9edb

9 files changed

+102
-38
lines changed

electron/renderer/components/game/game-roundtime.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const GameRoundTime: React.FC = (): ReactNode => {
105105
const timerCmps = useMemo((): ReactElement => {
106106
return (
107107
<div
108-
style={{
108+
css={{
109109
display: 'flex',
110110
flexDirection: 'column',
111111
alignContent: 'center',
@@ -152,7 +152,7 @@ const GameTimeDisplay: React.FC<GameTimeDisplayProps> = (
152152
return (
153153
<EuiToolTip content={typeTooltip} position="top">
154154
<div
155-
style={{
155+
css={{
156156
position: 'relative',
157157
width: '100%',
158158
height: '25px',
@@ -162,7 +162,7 @@ const GameTimeDisplay: React.FC<GameTimeDisplayProps> = (
162162
}}
163163
>
164164
<div
165-
style={{
165+
css={{
166166
position: 'absolute',
167167
left: 0,
168168
width: `${fillWidth}%`,
@@ -171,7 +171,7 @@ const GameTimeDisplay: React.FC<GameTimeDisplayProps> = (
171171
}}
172172
/>
173173
<div
174-
style={{
174+
css={{
175175
position: 'absolute',
176176
width: '100%',
177177
height: '100%',

electron/renderer/components/game/game-status-bars.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ const GameStatusBar: React.FC<GameStatusBarProps> = (
158158
}}
159159
>
160160
<div
161-
style={{
161+
css={{
162162
position: 'absolute',
163163
left: 0,
164164
width: `${value}%`,
@@ -169,7 +169,7 @@ const GameStatusBar: React.FC<GameStatusBarProps> = (
169169
}}
170170
/>
171171
<div
172-
style={{
172+
css={{
173173
position: 'absolute',
174174
width: '100%',
175175
height: '100%',

electron/renderer/components/game/game-stream-text.tsx

+43-18
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { EuiText, useEuiTheme } from '@elastic/eui';
22
import { type SerializedStyles, css } from '@emotion/react';
33
import type { ReactNode } from 'react';
44
import { memo, useMemo } from 'react';
5-
import type { GameLogLine } from '../../types/game.types.jsx';
5+
import type { GameLogLine, GameStreamStyle } from '../../types/game.types.jsx';
66

77
export interface GameStreamTextProps {
88
logLine: GameLogLine;
9+
style?: GameStreamStyle;
910
}
1011

1112
/**
@@ -17,46 +18,70 @@ export interface GameStreamTextProps {
1718
*/
1819
export const GameStreamText: React.FC<GameStreamTextProps> = memo(
1920
(props: GameStreamTextProps): ReactNode => {
20-
const { logLine } = props;
21+
const { logLine, style } = props;
2122

2223
const { euiTheme } = useEuiTheme();
2324

24-
const textStyles = useMemo((): SerializedStyles => {
25-
let fontSize = euiTheme.size.m;
26-
let fontFamily = euiTheme.font.family;
27-
let fontWeight = euiTheme.font.weight.regular;
28-
let fontColor = euiTheme.colors.text;
25+
const defaultStyles = useMemo(() => {
26+
const fontSize = style?.fontSize ?? euiTheme.size.m;
27+
const fontFamily = style?.fontFamily ?? euiTheme.font.family;
28+
const fontWeight = euiTheme.font.weight.regular;
29+
const foregroundColor = style?.foregroundColor ?? euiTheme.colors.text;
30+
const backgroundColor = style?.backgroundColor ?? 'inherit';
2931

30-
if (logLine.styles?.outputClass === 'mono') {
31-
fontFamily = euiTheme.font.familyCode ?? fontFamily;
32+
return {
33+
fontSize,
34+
fontFamily,
35+
fontWeight,
36+
foregroundColor,
37+
backgroundColor,
38+
};
39+
}, [euiTheme, style]);
40+
41+
const textStyles = useMemo((): SerializedStyles => {
42+
let fontSize = defaultStyles.fontSize;
43+
let fontFamily = defaultStyles.fontFamily;
44+
let fontWeight = defaultStyles.fontWeight;
45+
let foregroundColor = defaultStyles.foregroundColor;
46+
const backgroundColor = defaultStyles.backgroundColor;
47+
48+
// TODO add to user customizations in game stream style
49+
if (logLine.style?.outputClass === 'mono') {
3250
fontSize = euiTheme.size.m;
51+
fontFamily = euiTheme.font.familyCode ?? fontFamily;
3352
}
3453

35-
if (logLine.styles?.stylePreset === 'roomName') {
36-
fontColor = euiTheme.colors.title;
54+
// TODO add presets to user customizations in game stream style
55+
if (logLine.style?.stylePreset === 'roomName') {
56+
foregroundColor = euiTheme.colors.title;
3757
fontWeight = euiTheme.font.weight.bold;
3858
}
3959

40-
if (logLine.styles?.bold === true) {
60+
if (logLine.style?.bold === true) {
4161
fontWeight = euiTheme.font.weight.bold;
4262
}
4363

44-
if (logLine.styles?.subdued === true) {
45-
fontColor = euiTheme.colors.subduedText;
64+
if (logLine.style?.subdued === true) {
65+
foregroundColor = euiTheme.colors.subduedText;
4666
}
4767

4868
const textStyles = css({
4969
fontSize,
5070
fontFamily,
5171
fontWeight,
52-
color: fontColor,
72+
color: foregroundColor,
73+
backgroundColor,
5374
lineHeight: 'initial',
5475
paddingLeft: euiTheme.size.s,
5576
paddingRight: euiTheme.size.s,
77+
b: {
78+
color: '#FFD200', // TODO add 'monster bold' user customization to game stream style
79+
fontWeight: euiTheme.font.weight.regular,
80+
},
5681
});
5782

5883
return textStyles;
59-
}, [euiTheme, logLine.styles]);
84+
}, [euiTheme, defaultStyles, logLine.style]);
6085

6186
// We output the text using inner html because the text may contain tags.
6287
// For example, tags to highlight a single word or phrases.
@@ -91,8 +116,8 @@ const isSameLogLine = (options: {
91116
}): boolean => {
92117
const { oldLogLine, newLogLine } = options;
93118

94-
const { eventId: oldEventId, styles: oldTheme } = oldLogLine;
95-
const { eventId: newEventId, styles: newTheme } = newLogLine;
119+
const { eventId: oldEventId, style: oldTheme } = oldLogLine;
120+
const { eventId: newEventId, style: newTheme } = newLogLine;
96121

97122
const isSameEventId = oldEventId === newEventId;
98123
const isSameColorMode = oldTheme?.colorMode === newTheme?.colorMode;

electron/renderer/components/game/game-stream.tsx

+17-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { ReactNode } from 'react';
44
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
55
import type * as rxjs from 'rxjs';
66
import { GameContext } from '../../context/game.jsx';
7-
import type { GameLogLine } from '../../types/game.types.jsx';
7+
import type { GameLogLine, GameStreamStyle } from '../../types/game.types.jsx';
88
import { GameStreamText } from './game-stream-text.jsx';
99
import {
1010
excludeDuplicateEmptyLines,
@@ -39,6 +39,12 @@ export interface GameStreamProps {
3939
* Default is 500.
4040
*/
4141
maxLines?: number;
42+
/**
43+
* The default text formatting to apply to the entire stream.
44+
* Styles may be overridden on a line-by-line basis.
45+
* See {@link GameLogLine} for details.
46+
*/
47+
style?: GameStreamStyle;
4248
}
4349

4450
export const GameStream: React.FC<GameStreamProps> = (
@@ -187,6 +193,9 @@ export const GameStream: React.FC<GameStreamProps> = (
187193
css={{
188194
overflowY: 'scroll',
189195
height: '100%',
196+
// Disable the eui scrollbar color as it conflicts with
197+
// user customizations for grid item styling.
198+
backgroundColor: 'inherit',
190199
}}
191200
className="eui-scrollBar"
192201
paddingSize="none"
@@ -201,7 +210,13 @@ export const GameStream: React.FC<GameStreamProps> = (
201210
*/}
202211
<div css={{ overflowAnchor: 'none' }}>
203212
{gameLogLines.map((logLine) => {
204-
return <GameStreamText key={logLine.eventId} logLine={logLine} />;
213+
return (
214+
<GameStreamText
215+
key={logLine.eventId}
216+
logLine={logLine}
217+
style={props.style}
218+
/>
219+
);
205220
})}
206221
</div>
207222
<EuiSpacer size="s" />

electron/renderer/components/grid/grid-item.tsx

+22-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import type {
2525
GridItemBoundary,
2626
GridItemInfo,
2727
GridItemPosition,
28+
GridItemStyle,
2829
} from '../../types/grid.types.js';
2930

3031
export interface GridItemProps {
@@ -37,6 +38,12 @@ export interface GridItemProps {
3738
* If not specified then a default location will be used.
3839
*/
3940
position?: GridItemPosition;
41+
/**
42+
* The default font styling for the grid item.
43+
* It may be overridden on a line-by-line basis
44+
* based on game style presets and user preferences.
45+
*/
46+
style?: GridItemStyle;
4047
/**
4148
* The unique identifier for the grid item.
4249
*/
@@ -81,10 +88,18 @@ const DEFAULT_GRID_ITEM_POSITION: GridItemPosition = {
8188
height: 500,
8289
};
8390

91+
const DEFAULT_GRID_ITEM_STYLE: GridItemStyle = {
92+
fontFamily: 'inherit',
93+
fontSize: 'inherit',
94+
foregroundColor: 'inherit',
95+
backgroundColor: 'inherit',
96+
};
97+
8498
export const GridItem: React.FC<GridItemProps> = memo(
8599
(props: GridItemProps): ReactNode => {
86100
const { itemId, itemTitle, isFocused = false, children } = props;
87101
const { boundary, position = DEFAULT_GRID_ITEM_POSITION } = props;
102+
const { style = DEFAULT_GRID_ITEM_STYLE } = props;
88103
const { onFocus, onClose, onMoveResize } = props;
89104

90105
const { euiTheme } = useEuiTheme();
@@ -104,14 +119,15 @@ export const GridItem: React.FC<GridItemProps> = memo(
104119
itemId,
105120
itemTitle,
106121
isFocused,
122+
style,
107123
position: {
108124
x: x.get(),
109125
y: y.get(),
110126
width: width.get(),
111127
height: height.get(),
112128
},
113129
};
114-
}, [itemId, itemTitle, isFocused, x, y, width, height]);
130+
}, [itemId, itemTitle, isFocused, style, x, y, width, height]);
115131

116132
// Handle when the user clicks the close button in the title bar.
117133
const onCloseClick = useCallback(() => {
@@ -319,9 +335,13 @@ export const GridItem: React.FC<GridItemProps> = memo(
319335
<EuiSplitPanel.Outer
320336
grow={true}
321337
hasBorder={true}
322-
style={{
338+
css={{
323339
height: 'inherit',
324340
width: 'inherit',
341+
fontSize: style.fontSize,
342+
fontFamily: style.fontFamily,
343+
color: style.foregroundColor,
344+
backgroundColor: style.backgroundColor,
325345
}}
326346
>
327347
<EuiSplitPanel.Inner grow={false} color="subdued" paddingSize="none">

electron/renderer/components/grid/grid.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
7373
itemTitle={contentItem.itemTitle}
7474
isFocused={contentItem.itemId === focusedItemId}
7575
position={contentItem.position}
76+
style={contentItem.style}
7677
boundary={boundary}
7778
onFocus={onItemFocus}
7879
onClose={onItemClose}
@@ -93,7 +94,7 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
9394

9495
return (
9596
<div
96-
style={{
97+
css={{
9798
overflowY: 'auto',
9899
overflowX: 'hidden',
99100
position: 'relative',

electron/renderer/components/text/text-truncate.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const TextTruncate: React.FC<TextTruncateProps> = (
2525

2626
return (
2727
<div
28-
style={{
28+
css={{
2929
maxWidth,
3030
whiteSpace: 'nowrap',
3131
overflow: 'hidden',

electron/renderer/types/game.types.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,13 @@ export interface GameStreamStyle {
6464
* The font family to use for the text.
6565
* For example, "Verdana" or "Courier New".
6666
*/
67-
textFont: string;
67+
fontFamily: string;
6868
/**
69-
* The font size to use for the text, in pixels.
70-
* For example, 12.
69+
* The font size to use for the stream content.
70+
* Using a number without unit may not yield desired results.
71+
* Example: '12px' (recommended) vs. '12' (not recommended).
7172
*/
72-
textSize: number;
73+
fontSize: string;
7374
/**
7475
* The color name or hex code to use for the text.
7576
* For example, "red" or "#FF0000".

electron/renderer/types/grid.types.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface GridItemInfo {
1616
itemTitle: string;
1717
isFocused: boolean;
1818
position: GridItemPosition;
19+
style: GridItemStyle;
1920
}
2021

2122
export interface GridItemConfig {
@@ -99,12 +100,13 @@ export interface GridItemStyle {
99100
* The font family to use for the text.
100101
* For example, "Verdana" or "Courier New".
101102
*/
102-
textFont: string;
103+
fontFamily: string;
103104
/**
104-
* The font size to use for the text, in pixels.
105-
* For example, 12.
105+
* The font size to use for the stream content.
106+
* Using a number without unit may not yield desired results.
107+
* Example: '12px' (recommended) vs. '12' (not recommended).
106108
*/
107-
textSize: number;
109+
fontSize: string;
108110
/**
109111
* The color name or hex code to use for the text.
110112
* For example, "red" or "#FF0000".

0 commit comments

Comments
 (0)