diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx
index 7fc814deee..9eb1a5b88f 100644
--- a/packages/component/src/Composer.tsx
+++ b/packages/component/src/Composer.tsx
@@ -53,14 +53,14 @@ type ComposerCoreUIProps = {
};
const ComposerCoreUI = memo(({ children }: ComposerCoreUIProps) => {
- const [{ cssVariables }] = useStyleSet();
+ const [{ cssCustomProperties }] = useStyleSet();
const dictationOnError = useCallback(err => {
console.error(err);
}, []);
return (
-
+
{/* When is finalized, it will be using an independent instance that lives inside . */}
diff --git a/packages/component/src/Styles/CSSTokens.ts b/packages/component/src/Styles/CSSTokens.ts
new file mode 100644
index 0000000000..2710c63a5a
--- /dev/null
+++ b/packages/component/src/Styles/CSSTokens.ts
@@ -0,0 +1,18 @@
+import CustomPropertyNames from './CustomPropertyNames';
+
+type CustomPropertyNamesType = typeof CustomPropertyNames;
+
+type CSSTokensType>> = {
+ [K in keyof T]: `var(${T[K]})`;
+};
+
+// To add/remove/update a token, go to `CustomPropertyName.ts`.
+const CSSTokens = new Proxy>({} as CSSTokensType, {
+ get(_, key: keyof CustomPropertyNamesType) {
+ // We already checked in the `CustomPropertyName`.
+ // eslint-disable-next-line security/detect-object-injection
+ return `var(${CustomPropertyNames[key]})`;
+ }
+});
+
+export default CSSTokens;
diff --git a/packages/component/src/Styles/CustomPropertyName.ts b/packages/component/src/Styles/CustomPropertyName.ts
deleted file mode 100644
index 9f75471c28..0000000000
--- a/packages/component/src/Styles/CustomPropertyName.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-type WebChatCustomPropertyName = `--webchat__${string}`;
-
-const ColorAccent: WebChatCustomPropertyName = '--webchat__color--accent';
-const ColorTimestamp: WebChatCustomPropertyName = '--webchat__color--timestamp';
-const FontPrimary: WebChatCustomPropertyName = '--webchat__font--primary';
-const FontSizeSmall: WebChatCustomPropertyName = '--webchat__font-size--small';
-const IconURLExternalLink: WebChatCustomPropertyName = '--webchat__icon-url--external-link';
-const MaxWidthBubble: WebChatCustomPropertyName = '--webchat__max-width--bubble';
-const MinHeightBubble: WebChatCustomPropertyName = '--webchat__min-height--bubble';
-const PaddingRegular: WebChatCustomPropertyName = '--webchat__padding--regular';
-
-// TODO: Unsure if we should export this type.
-// This is because web devs are going to use CSS stylesheet to override us,
-// they are working on CSS rather than JS.
-
-export {
- ColorAccent,
- ColorTimestamp,
- FontPrimary,
- FontSizeSmall,
- IconURLExternalLink,
- MaxWidthBubble,
- MinHeightBubble,
- PaddingRegular
-};
diff --git a/packages/component/src/Styles/CustomPropertyNames.ts b/packages/component/src/Styles/CustomPropertyNames.ts
new file mode 100644
index 0000000000..7bae2a59a0
--- /dev/null
+++ b/packages/component/src/Styles/CustomPropertyNames.ts
@@ -0,0 +1,16 @@
+const CustomPropertyNames = Object.freeze({
+ // Make sure key names does not have JavaScript forbidden names.
+ ColorAccent: '--webchat__color--accent',
+ ColorTimestamp: '--webchat__color--timestamp',
+ FontPrimary: '--webchat__font--primary',
+ FontSizeSmall: '--webchat__font-size--small',
+ IconURLExternalLink: '--webchat__icon-url--external-link',
+ MaxWidthBubble: '--webchat__max-width--bubble',
+ MinHeightBubble: '--webchat__min-height--bubble',
+ PaddingRegular: '--webchat__padding--regular'
+} as const);
+
+// This is for type-checking only to make sure the CSS custom property names is `--webchat__${string}`.
+const _TypeChecking: Readonly> = CustomPropertyNames;
+
+export default CustomPropertyNames;
diff --git a/packages/component/src/Styles/StyleSet/CSSVariables.ts b/packages/component/src/Styles/StyleSet/CSSCustomProperties.ts
similarity index 61%
rename from packages/component/src/Styles/StyleSet/CSSVariables.ts
rename to packages/component/src/Styles/StyleSet/CSSCustomProperties.ts
index 7aaedb7ec2..a97816d6e6 100644
--- a/packages/component/src/Styles/StyleSet/CSSVariables.ts
+++ b/packages/component/src/Styles/StyleSet/CSSCustomProperties.ts
@@ -1,7 +1,8 @@
import { StrictStyleOptions } from 'botframework-webchat-api';
-import * as CustomPropertyName from '../CustomPropertyName';
-export default function createCSSVariablesStyle({
+import CustomPropertyNames from '../CustomPropertyNames';
+
+export default function createCSSCustomPropertiesStyle({
accent,
bubbleMaxWidth,
bubbleMinHeight,
@@ -13,7 +14,7 @@ export default function createCSSVariablesStyle({
timestampColor
}: StrictStyleOptions) {
return {
- '&.webchat__css-variables': {
+ '&.webchat__css-custom-properties': {
display: 'contents',
// TODO: Should we register the CSS property for inheritance, type checking, and initial value?
@@ -31,14 +32,14 @@ export default function createCSSVariablesStyle({
// - We should put styling varibles here, e.g. paddingRegular
// - We MUST NOT put runtime variables here, e.g. sendTimeout
// - This is because we cannot programmatically know when the sendTimeout change
- [CustomPropertyName.ColorAccent]: accent,
- [CustomPropertyName.ColorTimestamp]: timestampColor || subtle, // Maybe we should not need this if we allow web devs to override CSS variables for certain components.
- [CustomPropertyName.FontPrimary]: primaryFont,
- [CustomPropertyName.FontSizeSmall]: fontSizeSmall,
- [CustomPropertyName.IconURLExternalLink]: markdownExternalLinkIconImage,
- [CustomPropertyName.MaxWidthBubble]: bubbleMaxWidth + 'px',
- [CustomPropertyName.MinHeightBubble]: bubbleMinHeight + 'px',
- [CustomPropertyName.PaddingRegular]: paddingRegular + 'px'
+ [CustomPropertyNames.ColorAccent]: accent,
+ [CustomPropertyNames.ColorTimestamp]: timestampColor || subtle, // Maybe we should not need this if we allow web devs to override CSS variables for certain components.
+ [CustomPropertyNames.FontPrimary]: primaryFont,
+ [CustomPropertyNames.FontSizeSmall]: fontSizeSmall,
+ [CustomPropertyNames.IconURLExternalLink]: markdownExternalLinkIconImage,
+ [CustomPropertyNames.MaxWidthBubble]: bubbleMaxWidth + 'px',
+ [CustomPropertyNames.MinHeightBubble]: bubbleMinHeight + 'px',
+ [CustomPropertyNames.PaddingRegular]: paddingRegular + 'px'
}
};
}
diff --git a/packages/component/src/Styles/StyleSet/LinkDefinitions.ts b/packages/component/src/Styles/StyleSet/LinkDefinitions.ts
index 11a02b68cd..9186ccdddc 100644
--- a/packages/component/src/Styles/StyleSet/LinkDefinitions.ts
+++ b/packages/component/src/Styles/StyleSet/LinkDefinitions.ts
@@ -5,7 +5,8 @@ import {
NOT_FORCED_COLORS_SELECTOR
} from './Constants';
-// TODO: Fix CSS var.
+import CSSTokens from '../CSSTokens';
+
export default function createLinkDefinitionsStyleSet() {
return {
'&.webchat__link-definitions': {
@@ -28,10 +29,6 @@ export default function createLinkDefinitionsStyleSet() {
}
},
- // '.webchat__link-definitions__header-chevron': {
- // verticalAlign: 'middle'
- // },
-
'&:not([open]) .webchat__link-definitions__header-chevron': {
marginBottom: '-0.1em',
transform: 'rotate(-180deg)'
@@ -130,7 +127,7 @@ export default function createLinkDefinitionsStyleSet() {
padding: 4,
[NOT_FORCED_COLORS_SELECTOR]: {
- color: 'var(--webchat__color--accent)'
+ color: CSSTokens.ColorAccent
}
},
diff --git a/packages/component/src/Styles/StyleSet/ModalDialog.ts b/packages/component/src/Styles/StyleSet/ModalDialog.ts
index ceac1f2e6a..be7a5e2ee2 100644
--- a/packages/component/src/Styles/StyleSet/ModalDialog.ts
+++ b/packages/component/src/Styles/StyleSet/ModalDialog.ts
@@ -5,10 +5,12 @@ import {
NOT_FORCED_COLORS_SELECTOR
} from './Constants';
+import CSSTokens from '../CSSTokens';
+
export default function createModalDialogStyleSet() {
return {
'&.webchat__modal-dialog': {
- fontFamily: 'var(--webchat__font--primary)',
+ fontFamily: CSSTokens.FontPrimary,
width: '100%',
[NOT_FORCED_COLORS_SELECTOR]: {
@@ -18,11 +20,11 @@ export default function createModalDialogStyleSet() {
'& .webchat__modal-dialog__box': {
borderRadius: 2,
- height: 'calc(100% - var(--webchat__padding--regular) * 2)',
+ height: `calc(100% - ${CSSTokens.PaddingRegular} * 2)`,
overflow: 'hidden',
margin: 'auto',
maxWidth: '60%',
- width: 'calc(100% - var(--webchat__padding--regular) * 2)',
+ width: `calc(100% - ${CSSTokens.PaddingRegular} * 2)`,
[LIGHT_THEME_SELECTOR]: {
// From Power BI:
@@ -49,7 +51,7 @@ export default function createModalDialogStyleSet() {
'& .webchat__modal-dialog__close-button-layout': {
float: 'right',
- padding: 'var(--webchat__padding--regular)'
+ padding: CSSTokens.PaddingRegular
},
'& .webchat__modal-dialog__close-button': {
@@ -112,7 +114,7 @@ export default function createModalDialogStyleSet() {
},
'& .webchat__modal-dialog__body': {
- margin: 'calc(var(--webchat__padding--regular) * 2)'
+ margin: `calc(${CSSTokens.PaddingRegular} * 2)`
}
}
};
diff --git a/packages/component/src/Styles/StyleSet/OriginatorActivityStatus.ts b/packages/component/src/Styles/StyleSet/OriginatorActivityStatus.ts
deleted file mode 100644
index 12483eef42..0000000000
--- a/packages/component/src/Styles/StyleSet/OriginatorActivityStatus.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export default function createOriginatorActivityStatusStyle() {
- return {
- '&.webchat__originator-activity-status': {
- alignItems: 'center',
- /* These are the fonts used in Web Chat default style options. */
- fontFamily: 'var(--webchat__font--primary)',
- fontSize: '80%',
-
- '&.webchat__originator-activity-status--link': {
- color: 'var(--webchat__color--accent)'
- }
- }
- };
-}
diff --git a/packages/component/src/Styles/StyleSet/RenderMarkdown.ts b/packages/component/src/Styles/StyleSet/RenderMarkdown.ts
index 92058a335f..152cddc2f3 100644
--- a/packages/component/src/Styles/StyleSet/RenderMarkdown.ts
+++ b/packages/component/src/Styles/StyleSet/RenderMarkdown.ts
@@ -1,6 +1,5 @@
-/* eslint no-magic-numbers: "off" */
-
import { FORCED_COLORS_SELECTOR, NOT_FORCED_COLORS_SELECTOR } from './Constants';
+import CSSTokens from '../CSSTokens';
// This style is for accompanying result of `renderMarkdown()`.
// Mostly, it should only styles elements that are generated/modified during `renderMarkdown()`.
@@ -9,7 +8,7 @@ export default function createMarkdownStyle() {
return {
'&.webchat__render-markdown': {
'& .webchat__render-markdown__external-link-icon': {
- backgroundImage: 'var(--webchat__icon-url--external-link)',
+ backgroundImage: CSSTokens.IconURLExternalLink,
height: '.75em',
marginLeft: '.25em'
},
@@ -27,7 +26,7 @@ export default function createMarkdownStyle() {
},
[NOT_FORCED_COLORS_SELECTOR]: {
- color: 'var(--webchat__color--accent)'
+ color: CSSTokens.ColorAccent
}
},
diff --git a/packages/component/src/Styles/StyleSet/SendStatus.ts b/packages/component/src/Styles/StyleSet/SendStatus.ts
index 0b26232b2d..7d585747a9 100644
--- a/packages/component/src/Styles/StyleSet/SendStatus.ts
+++ b/packages/component/src/Styles/StyleSet/SendStatus.ts
@@ -1,10 +1,12 @@
+import CSSTokens from '../CSSTokens';
+
export default function createSendStatusStyle() {
return {
'&.webchat__activity-status': {
- color: 'var(--webchat__color--timestamp)',
- fontFamily: 'var(--webchat__font--primary)',
- fontSize: 'var(--webchat__font-size--small)',
- marginTop: 'calc(var(--webchat__padding--regular) / 2)'
+ color: CSSTokens.ColorTimestamp,
+ fontFamily: CSSTokens.FontPrimary,
+ fontSize: CSSTokens.FontSizeSmall,
+ marginTop: `calc(${CSSTokens.PaddingRegular} / 2)`
},
'&.webchat__activity-status--slotted': {
@@ -16,7 +18,7 @@ export default function createSendStatusStyle() {
alignItems: 'center',
'&.webchat__activity-status__originator--has-link': {
- color: 'var(--webchat__color--accent)'
+ color: CSSTokens.ColorAccent
}
}
};
diff --git a/packages/component/src/Styles/StyleSet/SlottedActivityStatus.ts b/packages/component/src/Styles/StyleSet/SlottedActivityStatus.ts
index cc6feff4c9..df5f000e59 100644
--- a/packages/component/src/Styles/StyleSet/SlottedActivityStatus.ts
+++ b/packages/component/src/Styles/StyleSet/SlottedActivityStatus.ts
@@ -1,13 +1,15 @@
+import CSSTokens from '../CSSTokens';
+
export default function createSlottedActivityStatus() {
return {
'&.webchat__slotted-activity-status': {
alignItems: 'center',
display: 'inline-flex',
gap: 4,
- marginTop: 'calc(var(--webchat__padding--regular) / 2)',
+ marginTop: `calc(${CSSTokens.PaddingRegular} / 2)`,
'& .webchat__slotted-activity-status__pipe': {
- fontSize: 'var(--webchat__font-size--small)'
+ fontSize: CSSTokens.FontSizeSmall
}
}
};
diff --git a/packages/component/src/Styles/StyleSet/TextContent.ts b/packages/component/src/Styles/StyleSet/TextContent.ts
index 6fa8195ea2..f871c522d2 100644
--- a/packages/component/src/Styles/StyleSet/TextContent.ts
+++ b/packages/component/src/Styles/StyleSet/TextContent.ts
@@ -1,17 +1,17 @@
-/* eslint no-magic-numbers: "off" */
+import CSSTokens from '../CSSTokens';
export default function createTextContentStyle() {
return {
'&.webchat__text-content': {
- fontFamily: 'var(--webchat__font--primary)',
+ fontFamily: CSSTokens.FontPrimary,
margin: 0,
- minHeight: 'calc(var(--webchat__min-height--bubble) - var(--webchat__padding--regular) * 2)',
- padding: 'var(--webchat__padding--regular)',
+ minHeight: `calc(${CSSTokens.MinHeightBubble} - ${CSSTokens.PaddingRegular} * 2)`,
+ padding: CSSTokens.PaddingRegular,
'&.webchat__text-content--is-markdown': {
display: 'flex',
flexDirection: 'column',
- gap: 'var(--webchat__padding--regular)'
+ gap: CSSTokens.PaddingRegular
},
'& .webchat__text-content__markdown > :first-child': {
@@ -23,7 +23,7 @@ export default function createTextContentStyle() {
},
'& .webchat__text-content__markdown img:not(.webchat__render-markdown__external-link-icon)': {
- maxWidth: 'var(--webchat__max-width--bubble)',
+ maxWidth: CSSTokens.MaxWidthBubble,
width: '100%'
},
diff --git a/packages/component/src/Styles/StyleSet/ThumbButton.ts b/packages/component/src/Styles/StyleSet/ThumbButton.ts
index 54ee9d3c7e..7f5eba727e 100644
--- a/packages/component/src/Styles/StyleSet/ThumbButton.ts
+++ b/packages/component/src/Styles/StyleSet/ThumbButton.ts
@@ -1,3 +1,5 @@
+import CSSTokens from '../CSSTokens';
+
export default function () {
return {
'&.webchat__thumb-button': {
@@ -21,7 +23,7 @@ export default function () {
},
'& .webchat__thumb-button__image': {
- color: 'var(--webchat__color--accent)',
+ color: CSSTokens.ColorAccent,
width: 14
},
diff --git a/packages/component/src/Styles/createStyleSet.ts b/packages/component/src/Styles/createStyleSet.ts
index 74907fb81c..8039614d0a 100644
--- a/packages/component/src/Styles/createStyleSet.ts
+++ b/packages/component/src/Styles/createStyleSet.ts
@@ -11,7 +11,7 @@ import createCarouselFilmStrip from './StyleSet/CarouselFilmStrip';
import createCarouselFilmStripAttachment from './StyleSet/CarouselFilmStripAttachment';
import createCarouselFlipper from './StyleSet/CarouselFlipper';
import createConnectivityNotification from './StyleSet/ConnectivityNotification';
-import createCSSVariablesStyle from './StyleSet/CSSVariables';
+import createCSSCustomPropertiesStyle from './StyleSet/CSSCustomProperties';
import createDictationInterimsStyle from './StyleSet/DictationInterims';
import createErrorBoxStyle from './StyleSet/ErrorBox';
import createErrorNotificationStyle from './StyleSet/ErrorNotification';
@@ -99,7 +99,7 @@ export default function createStyleSet(styleOptions: StyleOptions) {
// Following styles follows new house rules:
// - Use CSS var instead of strictStyleOptions
- cssVariables: createCSSVariablesStyle(strictStyleOptions),
+ cssCustomProperties: createCSSCustomPropertiesStyle(strictStyleOptions),
linkDefinitions: createLinkDefinitionsStyle(),
modalDialog: createModalDialogStyle(),
renderMarkdown: createRenderMarkdownStyle(),