Skip to content

Commit 73ca4af

Browse files
authored
feat(Text): add hyphenated and emptyIndicator prop (#5255)
1 parent 3cc43dd commit 73ca4af

File tree

3 files changed

+75
-3
lines changed

3 files changed

+75
-3
lines changed

packages/main/src/components/Text/Text.cy.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ describe('Text', () => {
5959
cy.findByTestId('text').invoke('outerHeight').should('equal', 64);
6060
});
6161

62+
it('emptyIndicator', () => {
63+
cy.mount(<Text data-testid="text" />);
64+
cy.findByTestId('text').children().should('have.length', 0);
65+
cy.mount(<Text data-testid="text" emptyIndicator />);
66+
cy.findByTestId('text').children().should('have.length', 2);
67+
cy.findByText('–').should('be.visible');
68+
});
69+
70+
it('hyphenated', () => {
71+
cy.mount(<Text>Text</Text>);
72+
cy.findByText('Text').should('not.have.css', 'hyphens', 'auto');
73+
cy.mount(<Text hyphenated>Text</Text>);
74+
cy.findByText('Text').should('have.css', 'hyphens', 'auto');
75+
});
76+
6277
cypressPassThroughTestsFactory(Text);
6378
});
6479

packages/main/src/components/Text/Text.jss.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,19 @@ export const TextStyles = {
3434
WebkitBoxOrient: 'vertical',
3535
overflow: 'hidden',
3636
WebkitLineClamp: 'var(--_ui5wcr_maxLines)'
37+
},
38+
hyphenated: {
39+
hyphens: 'auto'
40+
},
41+
emptyIndicator: {
42+
lineHeight: 'normal',
43+
color: ThemingParameters.sapTextColor
44+
},
45+
pseudoInvisibleText: {
46+
fontSize: 0,
47+
position: 'absolute',
48+
userSelect: 'none',
49+
left: 0,
50+
top: 0
3751
}
3852
};

packages/main/src/components/Text/index.tsx

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use client';
22

3+
import { useI18nBundle } from '@ui5/webcomponents-react-base';
34
import { clsx } from 'clsx';
45
import type { CSSProperties, ReactNode } from 'react';
56
import React, { forwardRef } from 'react';
67
import { createUseStyles } from 'react-jss';
8+
import { EMPTY_VALUE } from '../../i18n/i18n-defaults.js';
79
import type { CommonProps } from '../../interfaces/index.js';
810
import { TextStyles } from './Text.jss.js';
911

@@ -24,32 +26,73 @@ export interface TextPropTypes extends CommonProps {
2426
* Limits the number of lines for wrapping texts.
2527
*/
2628
maxLines?: number;
29+
/**
30+
* Specifies if an empty indicator should be displayed when there is no text.
31+
*
32+
* @since 1.23.0
33+
*/
34+
emptyIndicator?: boolean;
35+
/**
36+
* Defines the type of text wrapping to be used (hyphenated or normal).
37+
*
38+
* __Note:__ This prop only takes effect if the `wrapping` prop is set to `true`.
39+
*
40+
* @since 1.23.0
41+
*/
42+
hyphenated?: boolean;
2743
}
2844

2945
const useStyles = createUseStyles(TextStyles, { name: 'Text' });
3046
/**
3147
* The `Text` component can be used for embedding text into your app. You can hyphenate the text with the use of the `wrapping` prop.
32-
* <br />__Note:__ Line breaks will always be visualized except when the wrapping property is set to false. In addition, tabs and whitespace can be preserved by setting the renderWhitespace property to true.
48+
*
49+
* __Note:__ Line breaks will always be visualized except when the wrapping property is set to false. In addition, tabs and whitespace can be preserved by setting the renderWhitespace property to true.
3350
*/
3451
const Text = forwardRef<HTMLSpanElement, TextPropTypes>((props, ref) => {
35-
const { children, renderWhitespace, wrapping = true, className, style, maxLines, ...rest } = props;
52+
const {
53+
children,
54+
renderWhitespace,
55+
wrapping = true,
56+
className,
57+
style,
58+
maxLines,
59+
hyphenated,
60+
emptyIndicator,
61+
...rest
62+
} = props;
3663
const classes = useStyles();
64+
const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
3765
const classNameString = clsx(
3866
classes.text,
3967
wrapping === false && classes.noWrap,
4068
renderWhitespace && classes.renderWhitespace,
4169
typeof maxLines === 'number' && classes.maxLines,
70+
hyphenated && classes.hyphenated,
4271
className
4372
);
4473

74+
const showEmptyIndicator = emptyIndicator && !children;
75+
const computedChildren = showEmptyIndicator ? (
76+
<span aria-hidden={showEmptyIndicator} data-component-name="TextEmptyIndicator" className={classes.emptyIndicator}>
77+
78+
</span>
79+
) : (
80+
children
81+
);
82+
4583
return (
4684
<span
4785
ref={ref}
4886
style={{ '--_ui5wcr_maxLines': typeof maxLines === 'number' ? maxLines : undefined, ...style } as CSSProperties}
4987
className={classNameString}
5088
{...rest}
5189
>
52-
{children}
90+
{computedChildren}
91+
{showEmptyIndicator && (
92+
<span className={classes.pseudoInvisibleText} data-component-name="TextEmptyTextContainer">
93+
{i18nBundle.getText(EMPTY_VALUE)}
94+
</span>
95+
)}
5396
</span>
5497
);
5598
});

0 commit comments

Comments
 (0)