Skip to content

Commit 5d690b3

Browse files
committed
feat(bottom-bar): show what is in your hands and preparing spell
1 parent b00ddfb commit 5d690b3

File tree

2 files changed

+91
-16
lines changed

2 files changed

+91
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { useEuiTheme } from '@elastic/eui';
2-
import { useState } from 'react';
2+
import type { ReactNode } from 'react';
3+
import { useMemo, useState } from 'react';
34
import type { GameEvent } from '../../../common/game/types.js';
45
import { GameEventType } from '../../../common/game/types.js';
56
import { useSubscribe } from '../../hooks/pubsub.jsx';
7+
import { TextTruncate } from '../text/text-truncate.jsx';
68

7-
export const GameHands: React.FC = () => {
9+
export const GameHands: React.FC = (): ReactNode => {
810
const { euiTheme } = useEuiTheme();
911

1012
const [leftHand, setLeftHand] = useState<string>('Empty');
@@ -25,29 +27,68 @@ export const GameHands: React.FC = () => {
2527
}
2628
});
2729

30+
const leftHandCmp = useMemo((): ReactNode => {
31+
return <GameHand label="Left" value={leftHand} />;
32+
}, [leftHand]);
33+
34+
const rightHandCmp = useMemo((): ReactNode => {
35+
return <GameHand label="Right" value={rightHand} />;
36+
}, [rightHand]);
37+
38+
const spellCmp = useMemo((): ReactNode => {
39+
return <GameHand label="Spell" value={spell} />;
40+
}, [spell]);
41+
2842
return (
2943
<div
3044
css={{
31-
display: 'block',
32-
justifyContent: 'center',
45+
display: 'flex',
46+
alignItems: 'center',
3347
alignContent: 'center',
34-
width: '300px',
35-
height: '100%',
48+
gap: '5px',
49+
width: '100%',
50+
height: '25px',
3651
fontSize: euiTheme.size.m,
3752
}}
3853
>
39-
{[
40-
{ label: 'Left', value: leftHand },
41-
{ label: 'Right', value: rightHand },
42-
{ label: 'Spell', value: spell },
43-
].map(({ label, value }) => (
44-
<div key={label} css={{ display: 'flex', gap: '5px' }}>
45-
<b css={{ textAlign: 'right', minWidth: '45px' }}>{label}:</b>
46-
{value}
47-
</div>
48-
))}
54+
{leftHandCmp}
55+
{rightHandCmp}
56+
{spellCmp}
4957
</div>
5058
);
5159
};
5260

5361
GameHands.displayName = 'GameHands';
62+
63+
interface GameHandProps {
64+
label: string;
65+
value: string;
66+
}
67+
68+
const GameHand: React.FC<GameHandProps> = (props: GameHandProps): ReactNode => {
69+
const { label, value } = props;
70+
71+
const { euiTheme } = useEuiTheme();
72+
73+
return (
74+
<div
75+
css={{
76+
display: 'flex',
77+
gap: '5px',
78+
width: '250px',
79+
height: '100%',
80+
padding: '5px',
81+
border: '1px solid',
82+
borderColor: euiTheme.border.color,
83+
borderRadius: '5px',
84+
}}
85+
>
86+
<div css={{ userSelect: 'none' }}>
87+
<b>{label}:</b>
88+
</div>
89+
<TextTruncate text={value} />
90+
</div>
91+
);
92+
};
93+
94+
GameHand.displayName = 'GameHand';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { ReactNode } from 'react';
2+
3+
export interface TextTruncateProps {
4+
/**
5+
* Text to potentially truncate.
6+
*/
7+
text: string;
8+
/**
9+
* Max width (pixels) of the text before truncating.
10+
* By default, truncates based on the width of the parent container.
11+
*/
12+
maxWidth?: number;
13+
}
14+
15+
export const TextTruncate: React.FC<TextTruncateProps> = (
16+
props: TextTruncateProps
17+
): ReactNode => {
18+
const { text, maxWidth } = props;
19+
20+
return (
21+
<div
22+
style={{
23+
maxWidth,
24+
whiteSpace: 'nowrap',
25+
overflow: 'hidden',
26+
textOverflow: 'ellipsis',
27+
}}
28+
>
29+
{text}
30+
</div>
31+
);
32+
};
33+
34+
TextTruncate.displayName = 'TextTruncate';

0 commit comments

Comments
 (0)