Skip to content

Commit b4ed464

Browse files
authored
feat: add EmojiPicker plugin stylesheet (#3108)
1 parent b284802 commit b4ed464

10 files changed

Lines changed: 89 additions & 16 deletions

File tree

examples/vite/src/App.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,15 @@ const EmojiPickerWithCustomOptions = (
159159
) => {
160160
const { mode } = useAppSettingsSelector((state) => state.theme);
161161

162-
return <EmojiPicker {...props} pickerProps={{ theme: mode }} />;
162+
return (
163+
<EmojiPicker
164+
{...props}
165+
pickerProps={{
166+
...props.pickerProps,
167+
theme: mode,
168+
}}
169+
/>
170+
);
163171
};
164172

165173
const ConfigurableNotificationList = (props: NotificationListProps) => {

examples/vite/src/index.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
@layer stream-new, stream-overrides, stream-app-overrides;
1+
@layer stream-new, stream-new-plugins, stream-overrides, stream-app-overrides;
22

33
// v3 CSS import
44
@import url('stream-chat-react/dist/css/index.css') layer(stream-new);
55
@import url('./AppSettings/AppSettings.scss') layer(stream-app-overrides);
66
@import url('./SystemNotification/SystemNotification.scss') layer(stream-app-overrides);
7+
@import url('stream-chat-react/dist/css/emoji-picker.css') layer(stream-new-plugins);
78

89
:root {
910
font-synthesis: none;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
"scripts": {
187187
"clean": "rm -rf dist",
188188
"build": "yarn clean && concurrently 'yarn build-translations' 'vite build' 'tsc --project tsconfig.lib.json' 'yarn build-styling'",
189-
"build-styling": "sass src/styling/index.scss:dist/css/index.css src/styling/_emoji-replacement.scss:dist/css/emoji-replacement.css; cp -r src/styling/assets dist/css/assets",
189+
"build-styling": "sass src/styling/index.scss:dist/css/index.css src/styling/_emoji-replacement.scss:dist/css/emoji-replacement.css src/plugins/Emojis/styling/index.scss:dist/css/emoji-picker.css; cp -r src/styling/assets dist/css/assets",
190190
"build-translations": "i18next-cli extract",
191191
"coverage": "vitest run --coverage",
192192
"lint": "yarn prettier --list-different && yarn eslint && yarn validate-translations",

scripts/watch-styling.mjs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@ import { fileURLToPath } from 'node:url';
66
import { compileAsync } from 'sass';
77

88
const SRC_DIR = path.resolve('src');
9-
const ENTRY_FILE = path.join(SRC_DIR, 'styling/index.scss');
10-
const OUTPUT_FILE = path.resolve('dist/css/index.css');
9+
const STYLE_ENTRYPOINTS = [
10+
{
11+
entryFile: path.join(SRC_DIR, 'styling/index.scss'),
12+
outputFile: path.resolve('dist/css/index.css'),
13+
},
14+
{
15+
entryFile: path.join(SRC_DIR, 'styling/_emoji-replacement.scss'),
16+
outputFile: path.resolve('dist/css/emoji-replacement.css'),
17+
},
18+
{
19+
entryFile: path.join(SRC_DIR, 'plugins/Emojis/styling/index.scss'),
20+
outputFile: path.resolve('dist/css/emoji-picker.css'),
21+
},
22+
];
1123
const SCSS_EXTENSION = '.scss';
1224
const BUILD_DELAY_MS = 150;
1325
const SCAN_INTERVAL_MS = 500;
@@ -29,9 +41,9 @@ const log = (message) => {
2941

3042
const isScssFile = (filename) => filename.endsWith(SCSS_EXTENSION);
3143

32-
const toOutputRelativePath = (source) =>
44+
const toOutputRelativePath = (source, outputFile) =>
3345
path
34-
.relative(path.dirname(OUTPUT_FILE), fileURLToPath(source))
46+
.relative(path.dirname(outputFile), fileURLToPath(source))
3547
.split(path.sep)
3648
.join('/');
3749

@@ -86,23 +98,29 @@ const flushQueuedBuild = () => {
8698
void runBuild(trigger);
8799
};
88100

89-
const buildStyling = async () => {
90-
const { css, sourceMap } = await compileAsync(ENTRY_FILE, {
101+
const buildStyleEntry = async ({ entryFile, outputFile }) => {
102+
const { css, sourceMap } = await compileAsync(entryFile, {
91103
sourceMap: true,
92104
style: 'expanded',
93105
});
94-
const sourceMapFile = `${path.basename(OUTPUT_FILE)}.map`;
106+
const sourceMapFile = `${path.basename(outputFile)}.map`;
95107
const normalizedSourceMap = {
96108
...sourceMap,
97-
file: path.basename(OUTPUT_FILE),
109+
file: path.basename(outputFile),
98110
sources: sourceMap.sources.map((source) =>
99-
source.startsWith('file://') ? toOutputRelativePath(source) : source,
111+
source.startsWith('file://') ? toOutputRelativePath(source, outputFile) : source,
100112
),
101113
};
102114

103-
await mkdir(path.dirname(OUTPUT_FILE), { recursive: true });
104-
await writeFile(OUTPUT_FILE, `${css}\n\n/*# sourceMappingURL=${sourceMapFile} */\n`);
105-
await writeFile(`${OUTPUT_FILE}.map`, JSON.stringify(normalizedSourceMap));
115+
await mkdir(path.dirname(outputFile), { recursive: true });
116+
await writeFile(outputFile, `${css}\n\n/*# sourceMappingURL=${sourceMapFile} */\n`);
117+
await writeFile(`${outputFile}.map`, JSON.stringify(normalizedSourceMap));
118+
};
119+
120+
const buildStyling = async () => {
121+
for (const entry of STYLE_ENTRYPOINTS) {
122+
await buildStyleEntry(entry);
123+
}
106124
};
107125

108126
const runBuild = async (trigger) => {

src/plugins/Emojis/EmojiPicker.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export const EmojiPicker = (props: EmojiPickerProps) => {
6464
const { pickerContainerClassName, wrapperClassName } = classNames;
6565

6666
const { ButtonIconComponent = IconEmoji } = props;
67+
const pickerStyle = props.pickerProps?.style as React.CSSProperties | undefined;
6768

6869
useEffect(() => {
6970
if (!popperElement || !referenceElement) return;
@@ -107,6 +108,7 @@ export const EmojiPicker = (props: EmojiPickerProps) => {
107108
}
108109
}}
109110
{...props.pickerProps}
111+
style={{ ...pickerStyle, '--shadow': 'none' }}
110112
/>
111113
</div>
112114
)}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.str-chat__message-textarea-emoji-picker-container {
2+
--str-chat__emoji-picker-border-radius: 10px;
3+
4+
border-radius: var(--str-chat__emoji-picker-border-radius);
5+
box-shadow: var(--str-chat__box-shadow-3);
6+
overflow: hidden;
7+
8+
em-emoji-picker {
9+
--border-radius: var(--str-chat__emoji-picker-border-radius);
10+
}
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@use 'EmojiPicker';

src/styling/index.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
@use 'global-theme-variables';
66
@use 'palette-variables';
77
@use './variables-tokens.css';
8-
@use 'variables/font';
8+
@use 'variables';
99
@use 'base';
1010
@use 'fonts';
1111

src/styling/variables/index.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@use 'font';
2+
@use 'shadows';

src/styling/variables/shadows.scss

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Shadows on Web communicate visual separation and hierarchy through composed box-shadow layers.
3+
4+
Unlike iOS (single shadow token) and Android (dp elevation), web elevation is constructed
5+
from multiple shadow layers to simulate depth and ambient light.
6+
7+
Each shadow level consists of predefined layered shadows.
8+
Components must use these tokens instead of defining custom box-shadow values.
9+
10+
Higher levels combine stronger blur, increased offset, and additional ambient layers
11+
to create clearer separation from the base surface.
12+
*/
13+
14+
.str-chat,
15+
.str-chat__theme-light {
16+
--str-chat__box-shadow-1: var(--light-elevation-1);
17+
--str-chat__box-shadow-2: var(--light-elevation-2);
18+
--str-chat__box-shadow-3: var(--light-elevation-3);
19+
--str-chat__box-shadow-4: var(--light-elevation-4);
20+
}
21+
22+
.str-chat__theme-dark,
23+
.str-chat:not(.str-chat__theme-dark)
24+
*:not(.str-chat__theme-dark)
25+
.str-chat__theme-inverse {
26+
--str-chat__box-shadow-1: var(--dark-elevation-1);
27+
--str-chat__box-shadow-2: var(--dark-elevation-2);
28+
--str-chat__box-shadow-3: var(--dark-elevation-3);
29+
--str-chat__box-shadow-4: var(--dark-elevation-4);
30+
}

0 commit comments

Comments
 (0)