= {},
+) =>
+ render(
+
+
+
+
+ ,
+ );
+
+describe('UnsupportedAttachment', () => {
+ it('renders attachment title when title is set', () => {
+ renderUnsupported({
+ mime_type: 'application/x-custom',
+ title: 'Custom payload',
+ type: 'unknown',
+ } as Attachment);
+
+ expect(screen.getByTestId('unsupported-attachment-title')).toHaveTextContent(
+ 'Custom payload',
+ );
+ });
+
+ it('falls back to translated label when title is missing', () => {
+ renderUnsupported({ type: 'weird' } as Attachment);
+
+ expect(screen.getByTestId('unsupported-attachment-title')).toHaveTextContent(
+ 'Unsupported attachment',
+ );
+ });
+
+ it('uses AttachmentFileIcon from context when provided', () => {
+ const CustomAttachmentFileIcon = ({ fileName, mimeType }: FileIconProps) => (
+
+ );
+
+ renderUnsupported(
+ {
+ mime_type: 'application/octet-stream',
+ title: 'data.bin',
+ type: 'file',
+ } as Attachment,
+ { AttachmentFileIcon: CustomAttachmentFileIcon },
+ );
+
+ const icon = screen.getByTestId('custom-attachment-file-icon');
+ expect(icon).toHaveAttribute('data-file-name', 'data.bin');
+ expect(icon).toHaveAttribute('data-mime-type', 'application/octet-stream');
+ });
+});
diff --git a/src/components/Attachment/styling/Attachment.scss b/src/components/Attachment/styling/Attachment.scss
index 4239c2761..3edbb7c9b 100644
--- a/src/components/Attachment/styling/Attachment.scss
+++ b/src/components/Attachment/styling/Attachment.scss
@@ -338,34 +338,6 @@
}
}
- .str-chat__message-attachment-unsupported {
- @include utils.component-layer-overrides('file-attachment');
- display: flex;
- align-items: center;
- justify-content: center;
- padding: var(--space-8);
- column-gap: var(--space-16);
- //margin: var(--str-chat__attachment-margin);
-
- .str-chat__file-icon {
- width: calc(var(--str-chat__spacing-px) * 30);
- }
-
- .str-chat__message-attachment-unsupported__metadata {
- min-width: 0;
- flex: 1;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- justify-content: center;
- }
-
- .str-chat__message-attachment-unsupported__title {
- @include utils.ellipsis-text;
- max-width: 100%;
- }
- }
-
.str-chat__message-attachment-file--item,
.str-chat__message-attachment-audio-widget {
@include utils.flex-row-center;
diff --git a/src/components/Attachment/styling/UnsupportedAttachment.scss b/src/components/Attachment/styling/UnsupportedAttachment.scss
new file mode 100644
index 000000000..21b9bd638
--- /dev/null
+++ b/src/components/Attachment/styling/UnsupportedAttachment.scss
@@ -0,0 +1,66 @@
+@use '../../../styling/utils';
+@use '../../../styling/variables/font' as font;
+
+.str-chat {
+ /* The border radius used for the borders of file attachments */
+ --str-chat__unsupported-attachment-border-radius: calc(
+ var(--str-chat__message-bubble-border-radius) - var(--str-chat__attachment-margin)
+ );
+
+ /* The text/icon color of file attachments */
+ --str-chat__unsupported-attachment-color: var(--str-chat__text-color);
+
+ /* The text/icon color of file attachments for low emphasis texts (for example file size) */
+ --str-chat__unsupported-attachment-secondary-color: var(
+ --str-chat__text-low-emphasis-color
+ );
+
+ /* The background color of file attachments */
+ --str-chat__unsupported-attachment-background-color: transparent;
+
+ /* Top border of file attachments */
+ --str-chat__unsupported-attachment-border-block-start: none;
+
+ /* Bottom border of file attachments */
+ --str-chat__unsupported-attachment-border-block-end: none;
+
+ /* Left (right in RTL layout) border of file attachments */
+ --str-chat__unsupported-attachment-border-inline-start: none;
+
+ /* Right (left in RTL layout) border of file attachments */
+ --str-chat__unsupported-attachment-border-inline-end: none;
+
+ /* Box shadow applied to file attachments */
+ --str-chat__unsupported-attachment-box-shadow: none;
+}
+
+.str-chat__message-attachment-unsupported {
+ @include utils.component-layer-overrides('unsupported-attachment');
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: var(--spacing-sm);
+ column-gap: var(--spacing-sm);
+ // todo: keep a single variable for attachment min width
+ min-width: 300px;
+
+ .str-chat__file-icon {
+ width: calc(var(--str-chat__spacing-px) * 30);
+ }
+
+ .str-chat__message-attachment-unsupported__metadata {
+ min-width: 0;
+ flex: 1;
+ height: stretch;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-start;
+ }
+
+ .str-chat__message-attachment-unsupported__title {
+ @include utils.ellipsis-text;
+ @include font.text-caption-emphasis;
+ max-width: 100%;
+ }
+}
diff --git a/src/components/Attachment/styling/index.scss b/src/components/Attachment/styling/index.scss
index 13187343a..f30dbc237 100644
--- a/src/components/Attachment/styling/index.scss
+++ b/src/components/Attachment/styling/index.scss
@@ -6,3 +6,4 @@
@use 'Giphy';
@use 'LinkPreview';
@use 'ModalGallery';
+@use 'UnsupportedAttachment';
diff --git a/src/styling/index.scss b/src/styling/index.scss
index 6ee705ed7..e0bb678f7 100644
--- a/src/styling/index.scss
+++ b/src/styling/index.scss
@@ -4,7 +4,8 @@
@use 'global-layout-variables';
@use 'global-theme-variables';
@use 'palette-variables';
-@use './variables.css';
+@use './variables-tokens.css';
+@use 'variables/font';
@use 'base';
@use 'fonts';
diff --git a/src/styling/variables.css b/src/styling/variables-tokens.css
similarity index 100%
rename from src/styling/variables.css
rename to src/styling/variables-tokens.css
diff --git a/src/styling/variables/font.scss b/src/styling/variables/font.scss
new file mode 100644
index 000000000..7af868e36
--- /dev/null
+++ b/src/styling/variables/font.scss
@@ -0,0 +1,249 @@
+// HEADING
+// ================================================================================= //
+@mixin text-heading-xs {
+ font: var(--str-chat__font-body-default);
+ color: var(--text-primary);
+}
+
+@mixin text-heading-sm {
+ font: var(--str-chat__font-body-emphasis);
+ color: var(--text-primary);
+}
+
+@mixin text-heading-md {
+ font: var(--str-chat__font-body-link);
+ color: var(--text-link);
+}
+
+@mixin text-heading-lg {
+ font: var(--str-chat__font-body-link-emphasis);
+ color: var(--text-link);
+}
+
+// BODY
+// ================================================================================= //
+@mixin text-body-default {
+ font: var(--str-chat__font-body-default);
+ color: var(--text-primary);
+}
+
+@mixin text-body-emphasis {
+ font: var(--str-chat__font-body-emphasis);
+ color: var(--text-primary);
+}
+
+@mixin text-body-link {
+ font: var(--str-chat__font-body-link);
+ color: var(--text-link);
+}
+
+@mixin text-body-link-emphasis {
+ font: var(--str-chat__font-body-link-emphasis);
+ color: var(--text-link);
+}
+
+// CAPTION
+// ================================================================================= //
+@mixin text-caption-default {
+ font: var(--str-chat__font-caption-default);
+ color: var(--text-primary);
+}
+
+@mixin text-caption-emphasis {
+ font: var(--str-chat__font-caption-emphasis);
+ color: var(--text-primary);
+}
+
+@mixin text-caption-link {
+ font: var(--str-chat__font-caption-link);
+ color: var(--text-link);
+}
+
+@mixin text-caption-link-emphasis {
+ font: var(--str-chat__font-caption-link-emphasis);
+ color: var(--text-link);
+}
+
+// METADATA
+// ================================================================================= //
+@mixin text-metadata-default {
+ font: var(--str-chat__font-metadata-default);
+ color: var(--text-primary);
+}
+
+@mixin text-metadata-emphasis {
+ font: var(--str-chat__font-metadata-emphasis);
+ color: var(--text-primary);
+}
+
+@mixin text-metadata-link {
+ font: var(--str-chat__font-metadata-link);
+ color: var(--text-link);
+}
+
+@mixin text-metadata-link-emphasis {
+ font: var(--str-chat__font-metadata-link-emphasis);
+ color: var(--text-link);
+}
+
+// NUMERIC
+/* Numeric styles are used for compact, layout-critical UI elements such as:
+ - badge counts,
+ - avatar initials,
+ - keyboard key labels, and
+ - numeric labels inside pills.
+ Numeric tokens are classified as layout-stable UI indicators, not content text. */
+// ================================================================================= //
+@mixin text-numeric-sm {
+ font: var(--str-chat__font-numeric-sm);
+ color: var(--text-primary);
+}
+
+@mixin text-numeric-md {
+ font: var(--str-chat__font-numeric-md);
+ color: var(--text-primary);
+}
+
+@mixin text-numeric-lg {
+ font: var(--str-chat__font-numeric-lg);
+ color: var(--text-primary);
+}
+
+@mixin text-numeric-xl {
+ font: var(--str-chat__font-numeric-xl);
+ color: var(--text-primary);
+}
+
+.str-chat {
+ /* The font used in the chat, by default, we use [preinstalled OS fonts](https://systemfontstack.com/) */
+ --str-chat__font-family:
+ var(--typography-font-family-sans), system-ui, -apple-system, BlinkMacSystemFont,
+ Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
+
+ // HEADING
+ // ================================================================================= //
+ --str-chat__font-heading-xs: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-sm) / var(--typography-line-height-normal)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-heading-sm: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-md) / var(--typography-line-height-normal)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-heading-md: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-lg) / var(--typography-line-height-relaxed)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-heading-lg: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-xl) / var(--typography-line-height-relaxed)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ // BODY
+ // ================================================================================= //
+ --str-chat__font-body-default: normal var(--typography-font-weight-regular)
+ var(--typography-font-size-md) / var(--typography-line-height-normal)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-body-emphasis: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-md) / var(--typography-line-height-normal)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-body-link: normal var(--typography-font-weight-regular)
+ var(--typography-font-size-md) / var(--typography-line-height-normal)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-body-link-emphasis: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-md) / var(--typography-line-height-normal)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ // CAPTION
+ // ================================================================================= //
+ --str-chat__font-caption-default: normal var(--typography-font-weight-regular)
+ var(--typography-font-size-sm) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-caption-emphasis: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-sm) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-caption-link: normal var(--typography-font-weight-regular)
+ var(--typography-font-size-sm) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-caption-link-emphasis: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-sm) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ // METADATA
+ // ================================================================================= //
+ --str-chat__font-metadata-default: normal var(--typography-font-weight-regular)
+ var(--typography-font-size-xs) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-metadata-emphasis: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-xs) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-metadata-link: normal var(--typography-font-weight-regular)
+ var(--typography-font-size-xs) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-metadata-link-emphasis: normal var(--typography-font-weight-semi-bold)
+ var(--typography-font-size-xs) / var(--typography-line-height-tight)
+ var(--str-chat__font-family);
+
+ // --------------------
+
+ // NUMERIC
+ // ================================================================================= //
+ --str-chat__font-numeric-sm: normal var(--typography-font-weight-bold)
+ var(--typography-font-size-micro) / 100% var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-numeric-md: normal var(--typography-font-weight-bold)
+ var(--typography-font-size-xxs) / 100% var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-numeric-lg: normal var(--typography-font-weight-bold)
+ var(--typography-font-size-xs) / 100% var(--str-chat__font-family);
+
+ // --------------------
+
+ --str-chat__font-numeric-xl: normal var(--typography-font-weight-bold)
+ var(--typography-font-size-sm) / var(--line-height-line-height-14)
+ var(--str-chat__font-family);
+
+ // --------------------
+}