@revikornmann/muka-ui 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/manifest.json +10 -0
- package/dist/cjs/components/AgentTaskList/AgentTaskList.js +1 -1
- package/dist/cjs/components/BadgeNumber/BadgeNumber.css +105 -0
- package/dist/cjs/components/BadgeNumber/BadgeNumber.js +19 -0
- package/dist/cjs/components/BadgeNumber/BadgeNumber.js.map +1 -0
- package/dist/cjs/components/BadgeNumber/index.js +11 -0
- package/dist/cjs/components/BadgeNumber/index.js.map +1 -0
- package/dist/cjs/components/ChatMessage/ChatMessage.css +324 -0
- package/dist/cjs/components/ChatMessage/ChatMessage.js +138 -0
- package/dist/cjs/components/ChatMessage/ChatMessage.js.map +1 -0
- package/dist/cjs/components/ChatMessage/index.js +7 -0
- package/dist/cjs/components/ChatMessage/index.js.map +1 -0
- package/dist/cjs/components/ChatMessageList/ChatMessageList.js +1 -1
- package/dist/cjs/components/ChatMessageStack/ChatMessageStack.css +51 -0
- package/dist/cjs/components/ChatMessageStack/ChatMessageStack.js +49 -0
- package/dist/cjs/components/ChatMessageStack/ChatMessageStack.js.map +1 -0
- package/dist/cjs/components/ChatMessageStack/index.js +6 -0
- package/dist/cjs/components/ChatMessageStack/index.js.map +1 -0
- package/dist/cjs/components/ChatPhotoGrid/ChatPhotoGrid.css +8 -2
- package/dist/cjs/components/ChatPhotoGrid/ChatPhotoGrid.js +1 -1
- package/dist/cjs/components/Menu/Menu.js +5 -4
- package/dist/cjs/components/Menu/Menu.js.map +1 -1
- package/dist/cjs/components/index.js +9 -5
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/cjs/utils/useLongPress.js +71 -0
- package/dist/cjs/utils/useLongPress.js.map +1 -0
- package/dist/esm/components/AgentTaskList/AgentTaskList.js +1 -1
- package/dist/esm/components/BadgeNumber/BadgeNumber.css +105 -0
- package/dist/esm/components/BadgeNumber/BadgeNumber.js +15 -0
- package/dist/esm/components/BadgeNumber/BadgeNumber.js.map +1 -0
- package/dist/esm/components/BadgeNumber/index.js +3 -0
- package/dist/esm/components/BadgeNumber/index.js.map +1 -0
- package/dist/esm/components/ChatMessage/ChatMessage.css +324 -0
- package/dist/esm/components/ChatMessage/ChatMessage.js +134 -0
- package/dist/esm/components/ChatMessage/ChatMessage.js.map +1 -0
- package/dist/esm/components/ChatMessage/index.js +2 -0
- package/dist/esm/components/ChatMessage/index.js.map +1 -0
- package/dist/esm/components/ChatMessageList/ChatMessageList.js +1 -1
- package/dist/esm/components/ChatMessageStack/ChatMessageStack.css +51 -0
- package/dist/esm/components/ChatMessageStack/ChatMessageStack.js +42 -0
- package/dist/esm/components/ChatMessageStack/ChatMessageStack.js.map +1 -0
- package/dist/esm/components/ChatMessageStack/index.js +2 -0
- package/dist/esm/components/ChatMessageStack/index.js.map +1 -0
- package/dist/esm/components/ChatPhotoGrid/ChatPhotoGrid.css +8 -2
- package/dist/esm/components/ChatPhotoGrid/ChatPhotoGrid.js +1 -1
- package/dist/esm/components/Menu/Menu.js +5 -4
- package/dist/esm/components/Menu/Menu.js.map +1 -1
- package/dist/esm/components/index.js +3 -1
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/utils/useLongPress.js +68 -0
- package/dist/esm/utils/useLongPress.js.map +1 -0
- package/dist/styles/components/BadgeNumber.css +105 -0
- package/dist/styles/components/ChatMessage.css +324 -0
- package/dist/styles/components/ChatMessageStack.css +51 -0
- package/dist/styles/components/ChatPhotoGrid.css +8 -2
- package/dist/styles/index.css +2694 -2475
- package/dist/styles/muka-dark.css +2694 -2475
- package/dist/styles/muka-light.css +2694 -2475
- package/dist/styles/tokens-bouwplan-dark.css +32 -5
- package/dist/styles/tokens-bouwplan-light.css +32 -5
- package/dist/styles/tokens-fscl-dark.css +32 -5
- package/dist/styles/tokens-fscl-light.css +32 -5
- package/dist/styles/tokens-grip-dark.css +32 -5
- package/dist/styles/tokens-grip-light.css +32 -5
- package/dist/styles/tokens-muka-dark.css +32 -5
- package/dist/styles/tokens-muka-light.css +32 -5
- package/dist/styles/tokens-wireframe-dark.css +31 -4
- package/dist/styles/tokens-wireframe-light.css +31 -4
- package/dist/styles/wireframe-dark.css +2693 -2474
- package/dist/styles/wireframe-light.css +2693 -2474
- package/dist/types/components/AgentTaskList/AgentTaskList.d.ts +1 -1
- package/dist/types/components/BadgeNumber/BadgeNumber.d.ts +17 -0
- package/dist/types/components/BadgeNumber/BadgeNumber.d.ts.map +1 -0
- package/dist/types/components/BadgeNumber/index.d.ts +3 -0
- package/dist/types/components/BadgeNumber/index.d.ts.map +1 -0
- package/dist/types/components/ChatMessage/ChatMessage.d.ts +127 -0
- package/dist/types/components/ChatMessage/ChatMessage.d.ts.map +1 -0
- package/dist/types/components/ChatMessage/index.d.ts +2 -0
- package/dist/types/components/ChatMessage/index.d.ts.map +1 -0
- package/dist/types/components/ChatMessageList/ChatMessageList.d.ts +2 -2
- package/dist/types/components/ChatMessageList/ChatMessageList.d.ts.map +1 -1
- package/dist/types/components/ChatMessageStack/ChatMessageStack.d.ts +46 -0
- package/dist/types/components/ChatMessageStack/ChatMessageStack.d.ts.map +1 -0
- package/dist/types/components/ChatMessageStack/index.d.ts +2 -0
- package/dist/types/components/ChatMessageStack/index.d.ts.map +1 -0
- package/dist/types/components/ChatPhotoGrid/ChatPhotoGrid.d.ts +1 -1
- package/dist/types/components/Menu/Menu.d.ts +12 -0
- package/dist/types/components/Menu/Menu.d.ts.map +1 -1
- package/dist/types/components/index.d.ts +3 -1
- package/dist/types/components/index.d.ts.map +1 -1
- package/dist/types/utils/useLongPress.d.ts +28 -0
- package/dist/types/utils/useLongPress.d.ts.map +1 -0
- package/package.json +1 -1
- package/tokens/t3-semantics/ui.json +29 -0
- package/tokens/t4-components/badge-number.json +48 -0
- package/tokens/t4-components/chatbubble.json +33 -7
- package/tokens/t4-components/chatphotogrid.json +2 -2
- package/dist/cjs/components/ChatBubble/ChatBubble.css +0 -300
- package/dist/cjs/components/ChatBubble/ChatBubble.js +0 -37
- package/dist/cjs/components/ChatBubble/ChatBubble.js.map +0 -1
- package/dist/cjs/components/ChatBubble/index.js +0 -6
- package/dist/cjs/components/ChatBubble/index.js.map +0 -1
- package/dist/esm/components/ChatBubble/ChatBubble.css +0 -300
- package/dist/esm/components/ChatBubble/ChatBubble.js +0 -33
- package/dist/esm/components/ChatBubble/ChatBubble.js.map +0 -1
- package/dist/esm/components/ChatBubble/index.js +0 -2
- package/dist/esm/components/ChatBubble/index.js.map +0 -1
- package/dist/styles/components/ChatBubble.css +0 -300
- package/dist/types/components/ChatBubble/ChatBubble.d.ts +0 -85
- package/dist/types/components/ChatBubble/ChatBubble.d.ts.map +0 -1
- package/dist/types/components/ChatBubble/index.d.ts +0 -2
- package/dist/types/components/ChatBubble/index.d.ts.map +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* BadgeNumber Component Styles - Using Muka Design Tokens */
|
|
2
|
+
|
|
3
|
+
.muka-badge-number {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
border-radius: var(--border-radius-full);
|
|
8
|
+
white-space: nowrap;
|
|
9
|
+
user-select: none;
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* Sizes — fixed height, matching min-width (so a single digit renders as a
|
|
15
|
+
* circle), horizontal padding, and bold label typography. Vertical centering
|
|
16
|
+
* is handled by the fixed height + align-items: center.
|
|
17
|
+
*/
|
|
18
|
+
.muka-badge-number--2xs {
|
|
19
|
+
height: var(--badge-number-size-2xs);
|
|
20
|
+
min-width: var(--badge-number-size-2xs);
|
|
21
|
+
padding: 0 var(--badge-number-padding-2xs);
|
|
22
|
+
font-family: var(--text-label-xs-bold-fontFamily);
|
|
23
|
+
font-weight: var(--text-label-xs-bold-fontWeight);
|
|
24
|
+
font-size: var(--text-label-xs-bold-fontSize);
|
|
25
|
+
line-height: var(--text-label-xs-bold-lineHeight);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.muka-badge-number--xs {
|
|
29
|
+
height: var(--badge-number-size-xs);
|
|
30
|
+
min-width: var(--badge-number-size-xs);
|
|
31
|
+
padding: 0 var(--badge-number-padding-xs);
|
|
32
|
+
font-family: var(--text-label-sm-bold-fontFamily);
|
|
33
|
+
font-weight: var(--text-label-sm-bold-fontWeight);
|
|
34
|
+
font-size: var(--text-label-sm-bold-fontSize);
|
|
35
|
+
line-height: var(--text-label-sm-bold-lineHeight);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.muka-badge-number--sm {
|
|
39
|
+
height: var(--badge-number-size-sm);
|
|
40
|
+
min-width: var(--badge-number-size-sm);
|
|
41
|
+
padding: 0 var(--badge-number-padding-sm);
|
|
42
|
+
font-family: var(--text-label-md-bold-fontFamily);
|
|
43
|
+
font-weight: var(--text-label-md-bold-fontWeight);
|
|
44
|
+
font-size: var(--text-label-md-bold-fontSize);
|
|
45
|
+
line-height: var(--text-label-md-bold-lineHeight);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.muka-badge-number--md {
|
|
49
|
+
height: var(--badge-number-size-md);
|
|
50
|
+
min-width: var(--badge-number-size-md);
|
|
51
|
+
padding: 0 var(--badge-number-padding-md);
|
|
52
|
+
font-family: var(--text-label-lg-bold-fontFamily);
|
|
53
|
+
font-weight: var(--text-label-lg-bold-fontWeight);
|
|
54
|
+
font-size: var(--text-label-lg-bold-fontSize);
|
|
55
|
+
line-height: var(--text-label-lg-bold-lineHeight);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.muka-badge-number--lg {
|
|
59
|
+
height: var(--badge-number-size-lg);
|
|
60
|
+
min-width: var(--badge-number-size-lg);
|
|
61
|
+
padding: 0 var(--badge-number-padding-lg);
|
|
62
|
+
font-family: var(--text-label-2xl-bold-fontFamily);
|
|
63
|
+
font-weight: var(--text-label-2xl-bold-fontWeight);
|
|
64
|
+
font-size: var(--text-label-2xl-bold-fontSize);
|
|
65
|
+
line-height: var(--text-label-2xl-bold-lineHeight);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.muka-badge-number__label {
|
|
69
|
+
/*
|
|
70
|
+
* The badge sets a tight line-height for compact sizing, which would clip
|
|
71
|
+
* glyph descenders; give the label a roomier line-height. Vertical centering
|
|
72
|
+
* is unaffected because the badge height is fixed and content is centered.
|
|
73
|
+
*/
|
|
74
|
+
line-height: normal;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Neutral variant */
|
|
78
|
+
.muka-badge-number--neutral {
|
|
79
|
+
background-color: var(--color-surface-level1);
|
|
80
|
+
color: var(--color-text-default-default);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Info variant */
|
|
84
|
+
.muka-badge-number--info {
|
|
85
|
+
background-color: var(--color-state-info-contrast);
|
|
86
|
+
color: var(--color-text-default-inverse);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Success variant */
|
|
90
|
+
.muka-badge-number--success {
|
|
91
|
+
background-color: var(--color-state-success-contrast);
|
|
92
|
+
color: var(--color-text-default-inverse);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Warning variant */
|
|
96
|
+
.muka-badge-number--warning {
|
|
97
|
+
background-color: var(--color-state-warning-contrast);
|
|
98
|
+
color: var(--color-text-default-inverse);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Error variant */
|
|
102
|
+
.muka-badge-number--error {
|
|
103
|
+
background-color: var(--color-state-error-contrast);
|
|
104
|
+
color: var(--color-text-default-inverse);
|
|
105
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import './BadgeNumber.css';
|
|
3
|
+
export const BadgeNumber = ({ children, variant = 'neutral', size = '2xs', className = '', 'aria-label': ariaLabel, ...props }) => {
|
|
4
|
+
const classes = [
|
|
5
|
+
'muka-badge-number',
|
|
6
|
+
`muka-badge-number--${variant}`,
|
|
7
|
+
`muka-badge-number--${size}`,
|
|
8
|
+
className,
|
|
9
|
+
]
|
|
10
|
+
.filter(Boolean)
|
|
11
|
+
.join(' ');
|
|
12
|
+
return (_jsx("span", { className: classes, role: "status", "aria-label": ariaLabel, ...props, children: _jsx("span", { className: "muka-badge-number__label", children: children }) }));
|
|
13
|
+
};
|
|
14
|
+
export default BadgeNumber;
|
|
15
|
+
//# sourceMappingURL=BadgeNumber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BadgeNumber.js","sourceRoot":"","sources":["../../../../components/BadgeNumber/BadgeNumber.tsx"],"names":[],"mappings":";AACA,OAAO,mBAAmB,CAAC;AAe3B,MAAM,CAAC,MAAM,WAAW,GAA+B,CAAC,EACtD,QAAQ,EACR,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,KAAK,EACZ,SAAS,GAAG,EAAE,EACd,YAAY,EAAE,SAAS,EACvB,GAAG,KAAK,EACT,EAAE,EAAE;IACH,MAAM,OAAO,GAAG;QACd,mBAAmB;QACnB,sBAAsB,OAAO,EAAE;QAC/B,sBAAsB,IAAI,EAAE;QAC5B,SAAS;KACV;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,OAAO,CACL,eAAM,SAAS,EAAE,OAAO,EAAE,IAAI,EAAC,QAAQ,gBAAa,SAAS,KAAM,KAAK,YACtE,eAAM,SAAS,EAAC,0BAA0B,YAAE,QAAQ,GAAQ,GACvD,CACR,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../components/BadgeNumber/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/* ChatMessage Component Styles */
|
|
2
|
+
|
|
3
|
+
.muka-chat-message {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
width: 100%;
|
|
7
|
+
max-width: 100%;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* ─── Row: avatar rail + bubble ────────────────────────── */
|
|
11
|
+
|
|
12
|
+
.muka-chat-message__row {
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-columns: minmax(0, 1fr);
|
|
15
|
+
grid-template-areas: 'bubble';
|
|
16
|
+
column-gap: var(--chatbubble-row-gap);
|
|
17
|
+
width: 100%;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.muka-chat-message--has-avatar .muka-chat-message__row {
|
|
21
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
22
|
+
grid-template-areas: 'rail bubble';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.muka-chat-message__rail {
|
|
26
|
+
grid-area: rail;
|
|
27
|
+
/* Sits on the bubble's baseline (Figma 5355:44091) */
|
|
28
|
+
align-self: end;
|
|
29
|
+
display: flex;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
min-width: var(--chatbubble-avatar-size);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The Small size in Figma (5373:44702) halves the avatar to 32px and tightens
|
|
36
|
+
* the gap to the bubble. Size the avatar itself, not just the rail, so the
|
|
37
|
+
* bubbles keep their alignment. The header row keeps its own gap.
|
|
38
|
+
*/
|
|
39
|
+
@media (max-width: 1023px) {
|
|
40
|
+
.muka-chat-message__row {
|
|
41
|
+
column-gap: var(--chatbubble-row-gap-compact);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.muka-chat-message__rail {
|
|
45
|
+
min-width: var(--chatbubble-avatar-size-compact);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Outweighs the avatar's own size class, which sets width/height directly */
|
|
49
|
+
.muka-chat-message .muka-chat-message__rail > * {
|
|
50
|
+
width: var(--chatbubble-avatar-size-compact);
|
|
51
|
+
height: var(--chatbubble-avatar-size-compact);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* ─── Bubble surface ───────────────────────────────────── */
|
|
56
|
+
|
|
57
|
+
.muka-chat-message__bubble {
|
|
58
|
+
grid-area: bubble;
|
|
59
|
+
/*
|
|
60
|
+
* Width follows the content: a single line hugs, and once the text wraps the
|
|
61
|
+
* bubble fills to the shared max width. Robust to string or rich children —
|
|
62
|
+
* no length measuring needed (Figma `Text length` on 5355:44091).
|
|
63
|
+
*/
|
|
64
|
+
width: fit-content;
|
|
65
|
+
max-width: var(--chatbubble-max-width);
|
|
66
|
+
position: relative;
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: var(--chatbubble-gap);
|
|
70
|
+
padding: var(--chatbubble-padding-block) var(--chatbubble-padding-inline);
|
|
71
|
+
border-radius: var(--chatbubble-radius);
|
|
72
|
+
border: var(--border-width-regular) solid transparent;
|
|
73
|
+
box-shadow: var(--shadow-level2);
|
|
74
|
+
word-break: break-word;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Media, an embed or an action stack always run the full bubble width. */
|
|
78
|
+
.muka-chat-message--has-blocks .muka-chat-message__bubble {
|
|
79
|
+
width: 100%;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.muka-chat-message--own .muka-chat-message__bubble {
|
|
83
|
+
justify-self: end;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.muka-chat-message--own .muka-chat-message__bubble {
|
|
87
|
+
background-color: var(--chatbubble-color-own-background);
|
|
88
|
+
border-color: var(--chatbubble-color-own-border);
|
|
89
|
+
color: var(--chatbubble-color-own-foreground);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.muka-chat-message--peer .muka-chat-message__bubble {
|
|
93
|
+
background-color: var(--chatbubble-color-peer-background);
|
|
94
|
+
border-color: var(--chatbubble-color-peer-border);
|
|
95
|
+
color: var(--chatbubble-color-peer-foreground);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.muka-chat-message--agent .muka-chat-message__bubble {
|
|
99
|
+
background-color: var(--chatbubble-color-agent-background);
|
|
100
|
+
border-color: var(--chatbubble-color-agent-border);
|
|
101
|
+
color: var(--chatbubble-color-agent-foreground);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* ─── Header row (author · meta · time · badge) ────────── */
|
|
105
|
+
|
|
106
|
+
.muka-chat-message__header {
|
|
107
|
+
display: flex;
|
|
108
|
+
flex-flow: row wrap;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: var(--chatbubble-row-gap);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.muka-chat-message__author {
|
|
114
|
+
font-family: var(--text-body-base-bold-fontFamily);
|
|
115
|
+
font-weight: var(--text-body-base-bold-fontWeight);
|
|
116
|
+
font-size: var(--text-body-base-bold-fontSize);
|
|
117
|
+
line-height: var(--text-body-base-bold-lineHeight);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.muka-chat-message__author-meta {
|
|
121
|
+
/* Inherits the variant's body colour from the bubble */
|
|
122
|
+
color: inherit;
|
|
123
|
+
font-family: var(--text-body-base-regular-fontFamily);
|
|
124
|
+
font-weight: var(--text-body-base-regular-fontWeight);
|
|
125
|
+
font-size: var(--text-body-base-regular-fontSize);
|
|
126
|
+
line-height: var(--text-body-base-regular-lineHeight);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.muka-chat-message__badge {
|
|
130
|
+
display: inline-flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/*
|
|
135
|
+
* Keep the first line of content clear of the absolutely positioned menu
|
|
136
|
+
* button in the bubble's top-right corner.
|
|
137
|
+
*/
|
|
138
|
+
.muka-chat-message--has-menu .muka-chat-message__header,
|
|
139
|
+
.muka-chat-message--has-menu.muka-chat-message--no-header .muka-chat-message__message {
|
|
140
|
+
padding-right: var(--spacing-10);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* …and the last line clear of the inset timestamp in the bottom-right corner */
|
|
144
|
+
.muka-chat-message--has-timestamp .muka-chat-message__message {
|
|
145
|
+
padding-right: var(--spacing-10);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* ─── Body ─────────────────────────────────────────────── */
|
|
149
|
+
|
|
150
|
+
.muka-chat-message__body {
|
|
151
|
+
display: flex;
|
|
152
|
+
flex-direction: column;
|
|
153
|
+
gap: var(--chatbubble-gap);
|
|
154
|
+
min-width: 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.muka-chat-message__media {
|
|
158
|
+
min-width: 0;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.muka-chat-message__message {
|
|
162
|
+
font-family: var(--text-body-base-regular-fontFamily);
|
|
163
|
+
font-weight: var(--text-body-base-regular-fontWeight);
|
|
164
|
+
font-size: var(--text-body-base-regular-fontSize);
|
|
165
|
+
line-height: var(--text-body-base-regular-lineHeight);
|
|
166
|
+
white-space: pre-wrap;
|
|
167
|
+
word-break: break-word;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Empty message block should not add a gap of its own */
|
|
171
|
+
.muka-chat-message__message:empty {
|
|
172
|
+
display: none;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* ─── Embedded card ────────────────────────────────────── */
|
|
176
|
+
|
|
177
|
+
.muka-chat-message__embed {
|
|
178
|
+
position: relative;
|
|
179
|
+
display: flex;
|
|
180
|
+
flex-direction: column;
|
|
181
|
+
gap: var(--chatbubble-embed-gap);
|
|
182
|
+
/* The card is inset from the blocks above and below it (Figma 5289:40562) */
|
|
183
|
+
margin-block: var(--chatbubble-embed-margin-block);
|
|
184
|
+
padding: var(--chatbubble-embed-padding-block) var(--chatbubble-embed-padding-inline);
|
|
185
|
+
border-radius: var(--chatbubble-embed-radius);
|
|
186
|
+
border: var(--border-width-regular) solid transparent;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/*
|
|
190
|
+
* The embed sits on the raised surface of its author's role, one step apart
|
|
191
|
+
* from the bubble it is nested in, and reuses that role's border colour.
|
|
192
|
+
*/
|
|
193
|
+
.muka-chat-message--own .muka-chat-message__embed {
|
|
194
|
+
background-color: var(--chatbubble-embed-color-own-background);
|
|
195
|
+
border-color: var(--chatbubble-embed-color-own-border);
|
|
196
|
+
color: var(--chatbubble-embed-color-own-foreground);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.muka-chat-message--peer .muka-chat-message__embed {
|
|
200
|
+
background-color: var(--chatbubble-embed-color-peer-background);
|
|
201
|
+
border-color: var(--chatbubble-embed-color-peer-border);
|
|
202
|
+
color: var(--chatbubble-embed-color-peer-foreground);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.muka-chat-message--agent .muka-chat-message__embed {
|
|
206
|
+
background-color: var(--chatbubble-embed-color-agent-background);
|
|
207
|
+
border-color: var(--chatbubble-embed-color-agent-border);
|
|
208
|
+
color: var(--chatbubble-embed-color-agent-foreground);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.muka-chat-message__embed-content {
|
|
212
|
+
display: flex;
|
|
213
|
+
flex-direction: column;
|
|
214
|
+
gap: var(--chatbubble-embed-gap);
|
|
215
|
+
min-width: 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.muka-chat-message__embed-copy {
|
|
219
|
+
position: absolute;
|
|
220
|
+
top: var(--chatbubble-embed-padding-block);
|
|
221
|
+
right: var(--chatbubble-embed-padding-inline);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* ─── Stacked full-width action buttons ────────────────── */
|
|
225
|
+
|
|
226
|
+
.muka-chat-message__action-stack {
|
|
227
|
+
display: flex;
|
|
228
|
+
flex-direction: column;
|
|
229
|
+
gap: var(--chatbubble-action-stack-gap);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* ─── Inset timestamp ──────────────────────────────────── */
|
|
233
|
+
|
|
234
|
+
/*
|
|
235
|
+
* Every author puts its timestamp in the bubble's bottom-right corner, below
|
|
236
|
+
* the message — never in the header row (Figma 5355:44091).
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
.muka-chat-message__timestamp {
|
|
240
|
+
color: var(--chatbubble-color-timestamp);
|
|
241
|
+
font-family: var(--text-body-xs-regular-fontFamily);
|
|
242
|
+
font-weight: var(--text-body-xs-regular-fontWeight);
|
|
243
|
+
font-size: var(--text-body-xs-regular-fontSize);
|
|
244
|
+
line-height: var(--text-body-xs-regular-lineHeight);
|
|
245
|
+
white-space: nowrap;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/*
|
|
249
|
+
* Pinned to the corner rather than stacked below the message, so a one-line
|
|
250
|
+
* message stays one line tall. The message reserves the width it needs.
|
|
251
|
+
*/
|
|
252
|
+
.muka-chat-message__timestamp--inset {
|
|
253
|
+
position: absolute;
|
|
254
|
+
right: var(--spacing-2);
|
|
255
|
+
bottom: var(--spacing-1);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/*
|
|
259
|
+
* When the last block in the body is media, an embed or an action stack (not
|
|
260
|
+
* trailing text), it runs the full width, so reserve a line below for the inset
|
|
261
|
+
* timestamp. A message that ends in text clears the corner inline instead (see
|
|
262
|
+
* `__message` padding-right above), so it needs no extra bottom space.
|
|
263
|
+
*/
|
|
264
|
+
.muka-chat-message--has-timestamp.muka-chat-message--trailing-block .muka-chat-message__body {
|
|
265
|
+
padding-bottom: var(--text-body-xs-regular-lineHeight);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* ─── Menu affordance ──────────────────────────────────── */
|
|
269
|
+
|
|
270
|
+
/*
|
|
271
|
+
* Hidden at rest. Revealed on hover on pointer devices, on keyboard focus
|
|
272
|
+
* everywhere, and pinned while its menu is open. On touch the equivalent
|
|
273
|
+
* affordance is a long-press on the bubble, which opens an ActionSheet.
|
|
274
|
+
*/
|
|
275
|
+
.muka-chat-message__menu {
|
|
276
|
+
position: absolute;
|
|
277
|
+
top: var(--spacing-1);
|
|
278
|
+
right: var(--spacing-1);
|
|
279
|
+
opacity: 0;
|
|
280
|
+
pointer-events: none;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.muka-chat-message__menu:focus-within,
|
|
284
|
+
.muka-chat-message--menu-open .muka-chat-message__menu {
|
|
285
|
+
opacity: 1;
|
|
286
|
+
pointer-events: auto;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@media (hover: hover) and (pointer: fine) and (min-width: 1024px) {
|
|
290
|
+
.muka-chat-message__bubble:hover .muka-chat-message__menu {
|
|
291
|
+
opacity: 1;
|
|
292
|
+
pointer-events: auto;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Suppress iOS Safari's own callout so the long-press sheet can take over */
|
|
297
|
+
@media (pointer: coarse) {
|
|
298
|
+
.muka-chat-message--has-menu .muka-chat-message__bubble {
|
|
299
|
+
-webkit-touch-callout: none;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* ─── Print ────────────────────────────────────────────── */
|
|
304
|
+
|
|
305
|
+
@media print {
|
|
306
|
+
.muka-chat-message__bubble {
|
|
307
|
+
box-shadow: none;
|
|
308
|
+
break-inside: avoid;
|
|
309
|
+
print-color-adjust: exact;
|
|
310
|
+
-webkit-print-color-adjust: exact;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.muka-chat-message__embed {
|
|
314
|
+
break-inside: avoid;
|
|
315
|
+
print-color-adjust: exact;
|
|
316
|
+
-webkit-print-color-adjust: exact;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.muka-chat-message__menu,
|
|
320
|
+
.muka-chat-message__embed-copy,
|
|
321
|
+
.muka-chat-message__action-stack {
|
|
322
|
+
display: none;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { Button } from '../Button';
|
|
5
|
+
import { Icon } from '../Icon';
|
|
6
|
+
import { Menu, MenuTrigger, MenuContent, MenuItem, MenuCheckboxItem } from '../Menu';
|
|
7
|
+
import { ActionSheet } from '../ActionSheet';
|
|
8
|
+
import { useLongPress } from '../../utils/useLongPress';
|
|
9
|
+
import './ChatMessage.css';
|
|
10
|
+
/**
|
|
11
|
+
* Set by `ChatMessageStack` so its children inherit the author without every
|
|
12
|
+
* message repeating it. Exported for the stack; not part of the public API.
|
|
13
|
+
*/
|
|
14
|
+
export const ChatMessageVariantContext = createContext(null);
|
|
15
|
+
/**
|
|
16
|
+
* ChatMessage — a single chat message.
|
|
17
|
+
*
|
|
18
|
+
* Composes with `ChatMessageList`, and with `ChatMessageStack` for consecutive
|
|
19
|
+
* messages from one author. Pass `<ChatPhotoGrid />` to `media`, an
|
|
20
|
+
* `<AgentTaskList />` above the bubble for tool progress, and a `<Badge />` to
|
|
21
|
+
* `badge` for visibility scope.
|
|
22
|
+
*
|
|
23
|
+
* Secondary actions (copy, feedback, regenerate, plus anything in `menuItems`)
|
|
24
|
+
* live behind one options menu: a dropdown revealed on hover on pointer
|
|
25
|
+
* devices, and a bottom sheet opened by long-pressing the bubble on touch.
|
|
26
|
+
*/
|
|
27
|
+
export const ChatMessage = ({ variant, children, avatar, reserveAvatar = false, author, authorMeta, badge, timestamp, media, embed, onEmbedCopy, embedCopyLabel = 'Copy', actionStack, onCopy, copyLabel = 'Copy', onFeedback, feedback = null, feedbackUpLabel = 'Helpful', feedbackDownLabel = 'Not helpful', onRefresh, refreshLabel = 'Regenerate', menuItems, menuLabel = 'Message options', menuCancelLabel = 'Cancel', className = '', }) => {
|
|
28
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
29
|
+
const [sheetOpen, setSheetOpen] = useState(false);
|
|
30
|
+
// The trigger is revealed on hover, so focus must not linger on it after a
|
|
31
|
+
// pointer-driven close — Radix restores focus on close, and the browser marks
|
|
32
|
+
// that programmatic focus `:focus-visible`, which would pin the button open.
|
|
33
|
+
// Keyboard users still get focus back, since for them the reveal is correct.
|
|
34
|
+
const openedWithKeyboard = useRef(false);
|
|
35
|
+
const stackVariant = useContext(ChatMessageVariantContext);
|
|
36
|
+
const resolvedVariant = variant ?? stackVariant ?? 'peer';
|
|
37
|
+
// The visibility badge hangs off the author line, so it goes when the author does.
|
|
38
|
+
const showBadge = Boolean(author && badge);
|
|
39
|
+
const hasHeader = Boolean(author || authorMeta || showBadge);
|
|
40
|
+
// `own` never shows an avatar, so it never reserves the rail either.
|
|
41
|
+
const hasRail = resolvedVariant !== 'own' && Boolean(avatar || reserveAvatar);
|
|
42
|
+
const hasBlocks = Boolean(media || embed || actionStack);
|
|
43
|
+
// The inset timestamp needs a clear bottom-right corner. When the last block
|
|
44
|
+
// in the body is text it reserves that space inline (see `__message`
|
|
45
|
+
// padding-right); when it is media/embed/action-stack, the body reserves a
|
|
46
|
+
// line below instead. Render order is media → text → embed → action-stack.
|
|
47
|
+
const hasText = typeof children === 'string' ? children.trim().length > 0 : Boolean(children);
|
|
48
|
+
const trailingBlock = Boolean(actionStack || embed || (media && !hasText));
|
|
49
|
+
const items = useMemo(() => {
|
|
50
|
+
const resolved = [];
|
|
51
|
+
if (onCopy) {
|
|
52
|
+
resolved.push({
|
|
53
|
+
id: 'copy',
|
|
54
|
+
label: copyLabel,
|
|
55
|
+
icon: _jsx(Icon, { name: "file-copy", size: "sm" }),
|
|
56
|
+
onSelect: onCopy,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (onFeedback) {
|
|
60
|
+
resolved.push({
|
|
61
|
+
id: 'feedback-up',
|
|
62
|
+
label: feedbackUpLabel,
|
|
63
|
+
icon: _jsx(Icon, { name: "thumb-up", size: "sm" }),
|
|
64
|
+
checked: feedback === 'up',
|
|
65
|
+
onSelect: () => onFeedback(feedback === 'up' ? null : 'up'),
|
|
66
|
+
}, {
|
|
67
|
+
id: 'feedback-down',
|
|
68
|
+
label: feedbackDownLabel,
|
|
69
|
+
icon: _jsx(Icon, { name: "thumb-down", size: "sm" }),
|
|
70
|
+
checked: feedback === 'down',
|
|
71
|
+
onSelect: () => onFeedback(feedback === 'down' ? null : 'down'),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (onRefresh) {
|
|
75
|
+
resolved.push({
|
|
76
|
+
id: 'refresh',
|
|
77
|
+
label: refreshLabel,
|
|
78
|
+
icon: _jsx(Icon, { name: "restart", size: "sm" }),
|
|
79
|
+
onSelect: onRefresh,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (menuItems)
|
|
83
|
+
resolved.push(...menuItems);
|
|
84
|
+
return resolved;
|
|
85
|
+
}, [
|
|
86
|
+
onCopy,
|
|
87
|
+
copyLabel,
|
|
88
|
+
onFeedback,
|
|
89
|
+
feedback,
|
|
90
|
+
feedbackUpLabel,
|
|
91
|
+
feedbackDownLabel,
|
|
92
|
+
onRefresh,
|
|
93
|
+
refreshLabel,
|
|
94
|
+
menuItems,
|
|
95
|
+
]);
|
|
96
|
+
const hasMenu = items.length > 0;
|
|
97
|
+
const longPress = useLongPress({
|
|
98
|
+
enabled: hasMenu,
|
|
99
|
+
onLongPress: () => setSheetOpen(true),
|
|
100
|
+
});
|
|
101
|
+
const classes = [
|
|
102
|
+
'muka-chat-message',
|
|
103
|
+
`muka-chat-message--${resolvedVariant}`,
|
|
104
|
+
hasRail && 'muka-chat-message--has-avatar',
|
|
105
|
+
hasMenu && 'muka-chat-message--has-menu',
|
|
106
|
+
timestamp && 'muka-chat-message--has-timestamp',
|
|
107
|
+
hasBlocks && 'muka-chat-message--has-blocks',
|
|
108
|
+
trailingBlock && 'muka-chat-message--trailing-block',
|
|
109
|
+
menuOpen && 'muka-chat-message--menu-open',
|
|
110
|
+
!hasHeader && 'muka-chat-message--no-header',
|
|
111
|
+
className,
|
|
112
|
+
]
|
|
113
|
+
.filter(Boolean)
|
|
114
|
+
.join(' ');
|
|
115
|
+
// Grouped messages set `reserveAvatar` to keep the rail — and so the bubbles —
|
|
116
|
+
// aligned with the one message in the stack that draws the avatar.
|
|
117
|
+
const rail = hasRail ? (_jsx("div", { className: "muka-chat-message__rail", children: avatar })) : null;
|
|
118
|
+
return (_jsxs("div", { className: classes, "data-variant": resolvedVariant, children: [_jsxs("div", { className: "muka-chat-message__row", children: [rail, _jsxs("div", { className: "muka-chat-message__bubble", ...(hasMenu ? longPress : {}), children: [hasHeader && (_jsxs("div", { className: "muka-chat-message__header", children: [author && (_jsx("span", { className: "muka-chat-message__author", children: author })), authorMeta && (_jsx("span", { className: "muka-chat-message__author-meta", children: authorMeta })), showBadge && _jsx("span", { className: "muka-chat-message__badge", children: badge })] })), _jsxs("div", { className: "muka-chat-message__body", children: [media && _jsx("div", { className: "muka-chat-message__media", children: media }), _jsx("div", { className: "muka-chat-message__message", children: children }), embed && (_jsxs("div", { className: "muka-chat-message__embed", children: [_jsx("div", { className: "muka-chat-message__embed-content", children: embed }), onEmbedCopy && (_jsx("div", { className: "muka-chat-message__embed-copy", children: _jsx(Button, { variant: "muted", size: "md", iconOnly: true, type: "button", "aria-label": embedCopyLabel, onClick: onEmbedCopy, children: _jsx(Icon, { name: "file-copy", size: "sm" }) }) }))] })), actionStack && (_jsx("div", { className: "muka-chat-message__action-stack", children: actionStack }))] }), timestamp && (_jsx("span", { className: "muka-chat-message__timestamp muka-chat-message__timestamp--inset", children: timestamp })), hasMenu && (_jsx("div", { className: "muka-chat-message__menu", children: _jsxs(Menu, { open: menuOpen, onOpenChange: setMenuOpen, children: [_jsx(MenuTrigger, { asChild: true, children: _jsx(Button, { variant: "secondary", size: "sm", iconOnly: true, type: "button", "aria-label": menuLabel, onPointerDown: () => {
|
|
119
|
+
openedWithKeyboard.current = false;
|
|
120
|
+
}, onKeyDown: () => {
|
|
121
|
+
openedWithKeyboard.current = true;
|
|
122
|
+
}, children: _jsx(Icon, { name: "arrow-down-s", size: "xs" }) }) }), _jsx(MenuContent, { align: "end", onCloseAutoFocus: (event) => {
|
|
123
|
+
if (!openedWithKeyboard.current)
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
}, children: items.map((item) => item.checked === undefined ? (_jsx(MenuItem, { icon: item.icon, destructive: item.destructive, disabled: item.disabled, onSelect: item.onSelect, children: item.label }, item.id)) : (_jsx(MenuCheckboxItem, { checked: item.checked, disabled: item.disabled, icon: item.icon, onCheckedChange: item.onSelect, children: item.label }, item.id))) })] }) }))] })] }), hasMenu && (_jsx(ActionSheet, { open: sheetOpen, onOpenChange: setSheetOpen, title: menuLabel, cancel: { label: menuCancelLabel }, actions: items.map((item) => ({
|
|
126
|
+
label: item.label,
|
|
127
|
+
icon: item.icon,
|
|
128
|
+
onClick: item.onSelect,
|
|
129
|
+
destructive: item.destructive,
|
|
130
|
+
disabled: item.disabled,
|
|
131
|
+
})) }))] }));
|
|
132
|
+
};
|
|
133
|
+
export default ChatMessage;
|
|
134
|
+
//# sourceMappingURL=ChatMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatMessage.js","sourceRoot":"","sources":["../../../../components/ChatMessage/ChatMessage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../components/ChatMessage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,yBAAyB,GAI1B,MAAM,eAAe,CAAC"}
|
|
@@ -8,7 +8,7 @@ import './ChatMessageList.css';
|
|
|
8
8
|
* Auto-scrolls to bottom when content changes. Pin the list to the bottom of
|
|
9
9
|
* the conversation so new messages stay in view as they arrive.
|
|
10
10
|
*
|
|
11
|
-
* Composes with `
|
|
11
|
+
* Composes with `ChatMessage` and `TypingIndicator`.
|
|
12
12
|
*/
|
|
13
13
|
export const ChatMessageList = ({ children, autoScroll = true, className = '', 'aria-label': ariaLabel = 'Chat messages', }) => {
|
|
14
14
|
const ref = useRef(null);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* ChatMessageStack Component Styles */
|
|
2
|
+
|
|
3
|
+
.muka-chat-message-stack {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: var(--chatbubble-stack-gap);
|
|
7
|
+
width: 100%;
|
|
8
|
+
max-width: 100%;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.muka-chat-message-stack__messages {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: var(--chatbubble-stack-gap);
|
|
15
|
+
width: 100%;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* Reasoning sits above the stack, indented past the avatar rail so it lines up
|
|
20
|
+
* with the bubbles rather than with the avatar (Figma 5379:47300).
|
|
21
|
+
*/
|
|
22
|
+
.muka-chat-message-stack__reasoning {
|
|
23
|
+
min-width: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.muka-chat-message-stack--has-avatar .muka-chat-message-stack__reasoning {
|
|
27
|
+
padding-left: calc(var(--chatbubble-avatar-size) + var(--chatbubble-row-gap));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.muka-chat-message-stack--own.muka-chat-message-stack--has-avatar
|
|
31
|
+
.muka-chat-message-stack__reasoning {
|
|
32
|
+
padding-left: 0;
|
|
33
|
+
padding-right: calc(var(--chatbubble-avatar-size) + var(--chatbubble-row-gap));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Follow the message's compact rail and gap below the desktop breakpoint */
|
|
37
|
+
@media (max-width: 1023px) {
|
|
38
|
+
.muka-chat-message-stack--has-avatar .muka-chat-message-stack__reasoning {
|
|
39
|
+
padding-left: calc(
|
|
40
|
+
var(--chatbubble-avatar-size-compact) + var(--chatbubble-row-gap-compact)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.muka-chat-message-stack--own.muka-chat-message-stack--has-avatar
|
|
45
|
+
.muka-chat-message-stack__reasoning {
|
|
46
|
+
padding-left: 0;
|
|
47
|
+
padding-right: calc(
|
|
48
|
+
var(--chatbubble-avatar-size-compact) + var(--chatbubble-row-gap-compact)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|