Skip to content
Draft
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
f7caa2b
[ellipsis] fixed trim=middle behavior
ilyabrower Jul 2, 2025
336813b
[ellipsis] fixed trim=middle with different font-size
ilyabrower Jul 2, 2025
12468ee
[ellipsis, typography] init ellipsis as text property
ilyabrower Jul 2, 2025
35f42c5
[chore] added new hint component
ilyabrower Jul 3, 2025
9dcc69c
[ellipsis, typography] init ellipsis as text property
ilyabrower Jul 4, 2025
a73ed87
Merge remote-tracking branch 'origin/release/v16' into UIK-3879/fixed…
slizhevskyv-semrush Jul 7, 2025
63b47af
[stories] added more props in ellipsis stories
Valeria-Zimnitskaya Jul 7, 2025
3000289
[stories] added test story with specific text size
Valeria-Zimnitskaya Jul 7, 2025
a05494e
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-38…
ilyabrower Jul 24, 2025
6b34a84
[chore] Merge branch 'UIK-3879/fixed-middel-trim-in-ellipsis' into UI…
ilyabrower Jul 24, 2025
307b314
[ellipsis] UIK-3917 added conditional args to stories
ilyabrower Jul 25, 2025
3c299d5
[ellipsis] UIK-3917 added comment in docs
ilyabrower Jul 25, 2025
70dd5d6
[UIK-3879][ellipsis] fixed trim=middle behavior (#2304)
ilyabrower Jul 25, 2025
8ca531b
[ellipsis] the same behavior as on prod - with trim middle - always o…
ilyabrower Jul 25, 2025
3b787e3
[chore] Merge branch 'UIK-2194/ellipsis-middle-diff-font-size' of git…
ilyabrower Jul 25, 2025
f102c6d
[ellipsis] even displayedSymbols
ilyabrower Jul 25, 2025
9fdd71b
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Jul 25, 2025
d1ef679
[chore] Merge branch 'UIK-2194/ellipsis-middle-diff-font-size' into U…
ilyabrower Jul 25, 2025
891350b
[base-components] added new Hint component and useEllipsis hook
ilyabrower Jul 28, 2025
abaa758
[chore] typo fixes after review
ilyabrower Jul 29, 2025
38b8a4d
[website] added docs about new useEllipsis and Hint
ilyabrower Jul 29, 2025
1ffb06e
[chore] updated stories with new useEllipsis
ilyabrower Jul 30, 2025
6450ee6
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Jul 30, 2025
bfda6b4
[chore] added hintProps for components with new ellipsis
ilyabrower Jul 30, 2025
3854d9f
[chore] fixed deps
ilyabrower Jul 30, 2025
33fb56a
[chore] fixed build
ilyabrower Jul 30, 2025
d774b3f
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Jul 31, 2025
c5368a7
[chore] updated snapshots
ilyabrower Jul 31, 2025
a4f9165
[breadcrumbs] fixed tests
ilyabrower Aug 1, 2025
1ac27a6
[fullscreen-modal] fixed tests
ilyabrower Aug 1, 2025
69aa581
[data-table] fixed tests with ellipsis
ilyabrower Aug 1, 2025
deced57
[card] fixed tests
ilyabrower Aug 1, 2025
3662c1a
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Aug 1, 2025
ec2feb4
[base-components] ellipsis animations
ilyabrower Aug 1, 2025
9d13920
[chore] Merge branch 'release/v16' into UIK-2976/ellipsis-improvements
ilyabrower Aug 4, 2025
4b1f00e
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Aug 5, 2025
4a5a357
[breadcrumbs] update some snapshots
Valeria-Zimnitskaya Aug 6, 2025
5110dc4
[breadcrumbs] update some snapshots
Valeria-Zimnitskaya Aug 6, 2025
964c26a
[ellipsis] fixed trim=middle with different font-size
ilyabrower Aug 8, 2025
46d7231
[ellipsis] hint styles and timeout
sheila-semrush Aug 11, 2025
2a73a9c
Update semcore/base-components/src/components/hint/Hint.tsx
ilyabrower Aug 12, 2025
8c26a1f
[ellipsis] updated changelog
sheila-semrush Aug 14, 2025
5bcfc8f
[docs] ellipsis draft docs update
sheila-semrush Aug 14, 2025
f142fb1
[breadcrumbs] update test and snapshots for new ellipsis
Valeria-Zimnitskaya Aug 18, 2025
247c3cc
[ellipsis] added base components story foldes and update base trigger…
Valeria-Zimnitskaya Aug 18, 2025
48e653d
[docs] separated old and new Multiple Use examples for ellipsis
sheila-semrush Aug 18, 2025
225c371
[fullscreen-modal] update tests and snapshots
Valeria-Zimnitskaya Aug 19, 2025
e85eba6
[input-tags] update snapshots
Valeria-Zimnitskaya Aug 19, 2025
306875c
[base-components] added ellipsis test stories
Valeria-Zimnitskaya Aug 20, 2025
2571b40
[data-table] upd story
Valeria-Zimnitskaya Aug 20, 2025
54de8ca
[base-components] hint test story
Valeria-Zimnitskaya Aug 20, 2025
94a76bf
[docs] restored old examples to ellipsis-code and interlinked all pages
sheila-semrush Aug 20, 2025
47a62a9
[docs] added hint examples and docs
sheila-semrush Aug 22, 2025
cca58d2
[docs] removed Hint playground
sheila-semrush Aug 22, 2025
351cb35
[stories] UIK-4097
ilyabrower Aug 25, 2025
e0f4acc
[stories] UIK-4101
ilyabrower Aug 25, 2025
8fb3582
[base-components] not set display by default
ilyabrower Aug 25, 2025
49646e7
[base-components] fixed ellipsis for multi=line
ilyabrower Aug 25, 2025
b56532f
[base-components] fixed hint arrow
ilyabrower Aug 25, 2025
3929e80
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Aug 26, 2025
4b902e0
[base-components] update ellipsis test story
Valeria-Zimnitskaya Aug 26, 2025
ba958a3
[stories] UIK-4015
ilyabrower Aug 26, 2025
dca4dda
[chore] Merge branch 'UIK-2976/ellipsis-improvements' of github.com:s…
ilyabrower Aug 26, 2025
8fda3c1
[stories] UIK-4096 serp-filter ellipsis issue
ilyabrower Aug 26, 2025
8b631c1
[docs] fixed double Hint in examples
sheila-semrush Aug 26, 2025
8fa062c
[base-trigger] update snapshots
Valeria-Zimnitskaya Aug 27, 2025
95bed85
Merge branch 'release/v16' into UIK-2976/ellipsis-improvements
Valeria-Zimnitskaya Aug 27, 2025
4732f40
[base-components] update snapshots with new allipsis
Valeria-Zimnitskaya Aug 27, 2025
5b6e5fb
[stories] fixed UIK-4130
ilyabrower Aug 27, 2025
b142a7a
[base-components] added some tests for hint
Valeria-Zimnitskaya Aug 27, 2025
87c2a31
[base-components] fixed ellipsis after GH comments
ilyabrower Aug 27, 2025
95081b8
[chore] Merge branch 'UIK-2976/ellipsis-improvements' of github.com:s…
ilyabrower Aug 27, 2025
f4a5713
[stories] base ellipsis and hint - fixed types
ilyabrower Aug 28, 2025
f5f1855
[base-components] update story
Valeria-Zimnitskaya Aug 28, 2025
4d6b30e
[stories] fixed ellipsis example
ilyabrower Aug 28, 2025
de46914
[chore] Merge branch 'release/v16' into UIK-2976/ellipsis-improvements
ilyabrower Aug 29, 2025
a1ba4fd
[stories] changed hint placement in multiple use example
sheila-semrush Aug 29, 2025
10d4787
[chore] Merge branch 'release/v16' into UIK-2976/ellipsis-improvements
ilyabrower Sep 1, 2025
b86b35a
[typography] fixed types for hintProps
ilyabrower Sep 1, 2025
6bd7955
[stories] added constols for test ellipsis stories
Valeria-Zimnitskaya Sep 1, 2025
9fc8378
[base-components] ellipsis and hint tests
Valeria-Zimnitskaya Sep 1, 2025
eb1844d
[base-components] update tests for ellipsis and hint
Valeria-Zimnitskaya Sep 1, 2025
0357981
[chore] Merge remote-tracking branch 'origin/release/v16' into UIK-29…
ilyabrower Sep 30, 2025
b3d5163
[chore] Merge branch 'release/v16' into UIK-2976/ellipsis-improvements
ilyabrower Oct 10, 2025
989a594
[base-components] update ellipsis tests and snapshots
Valeria-Zimnitskaya Oct 10, 2025
a982134
[ellipsis] update tests
Valeria-Zimnitskaya Oct 10, 2025
49012d7
[base-components] update tests
Valeria-Zimnitskaya Oct 10, 2025
41b1912
[base-components] update test
Valeria-Zimnitskaya Oct 10, 2025
e6041c9
[side-panel] upd snapshots
Valeria-Zimnitskaya Oct 10, 2025
8e330a9
[tag] upd snapshots
Valeria-Zimnitskaya Oct 10, 2025
4bdd2a0
[select] fixed deps
ilyabrower Oct 13, 2025
0da769c
[website] added info about select.option.text
ilyabrower Oct 13, 2025
898895b
[ellipsis] update test
Valeria-Zimnitskaya Oct 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions semcore/base-components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

CHANGELOG.md standards are inspired by [keepachangelog.com](https://keepachangelog.com/en/1.0.0/).

## [16.2.0] - 2025-08-08

### Added

- `useEllipsis` hook.
- `Hint` component.

## [16.1.2] - 2025-07-23

### Changed
Expand Down
1 change: 1 addition & 0 deletions semcore/base-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
}
},
"dependencies": {
"@floating-ui/dom": "1.7.2",
"@popperjs/core": "2.11.5",
"classnames": "2.2.6",
"csstype": "3.1.3",
Expand Down
12 changes: 12 additions & 0 deletions semcore/base-components/src/components/ellipsis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useEllipsis, isTextOverflowing } from './useEllipsis';
import type { EllipsisSettings } from './useEllipsis';
import { useResizeObserver } from './useResizeObserver';

export {
useEllipsis,
isTextOverflowing,
useResizeObserver,
};
export type {
EllipsisSettings,
};
117 changes: 117 additions & 0 deletions semcore/base-components/src/components/ellipsis/useEllipsis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React from 'react';

import { useResizeObserver } from './useResizeObserver';

export type EllipsisSettings = {
trim?: 'end' | 'middle';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about calling it "position" or "placement"? I'm not sure "trim" is a correct term in this context. Or do we want to keep the old names?

maxLine?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems we need an ability to disable hint for multiline cases (paragraphs of text)
maybe we could just disable it automatically when maxLine > 1 for now?
and see if anyone requests a property to disable it manually in the future

};

function createMeasurerElement(element: HTMLElement, text?: string) {
const styleElement = window.getComputedStyle(element, null);
const temporaryElement = document.createElement('temporary-block');
temporaryElement.style.display = styleElement.getPropertyValue('display');
temporaryElement.style.padding = styleElement.getPropertyValue('padding');
temporaryElement.style.position = 'absolute';
temporaryElement.style.right = '0%';
temporaryElement.style.bottom = '0%';
temporaryElement.style.visibility = 'hidden';
temporaryElement.style.fontFamily = styleElement.getPropertyValue('font-family');
temporaryElement.style.fontSize = styleElement.getPropertyValue('font-size');
temporaryElement.style.fontWeight = styleElement.getPropertyValue('font-weight');
temporaryElement.style.lineHeight = styleElement.getPropertyValue('line-height');
temporaryElement.style.whiteSpace = styleElement.getPropertyValue('white-space');
temporaryElement.style.wordWrap = styleElement.getPropertyValue('word-wrap');

temporaryElement.style.fontFeatureSettings =
styleElement.getPropertyValue('font-feature-settings');
temporaryElement.style.fontVariantNumeric = styleElement.getPropertyValue('font-variant-numeric');

temporaryElement.innerHTML = text ?? element.innerHTML;
return temporaryElement;
}

export function isTextOverflowing(element: HTMLElement | null, multiline: boolean, text?: string): boolean {
if (!element) return false;

const { height: currentHeight, width: currentWidth } = element.getBoundingClientRect();
const measuringElement = createMeasurerElement(element, text);
let isOverflowing = false;

document.body.appendChild(measuringElement);
if (multiline) {
measuringElement.style.width = `${currentWidth}px`;

const width = measuringElement.scrollWidth;
const height = measuringElement.getBoundingClientRect().height;

if (Math.ceil(currentHeight) < height || Math.ceil(currentWidth) < width) {
isOverflowing = true;
}
} else {
measuringElement.style.whiteSpace = 'nowrap';
isOverflowing = Math.ceil(currentWidth) < measuringElement.getBoundingClientRect().width;
}

document.body.removeChild(measuringElement);

return isOverflowing;
}

export function useEllipsis(ref: React.RefObject<HTMLElement>, props: EllipsisSettings | false): boolean {
const [isEllipsized, setIsEllipsized] = React.useState(false);

const maxLine = props === false ? undefined : (props.maxLine ?? 1);
const trim = props === false ? undefined : (props.trim ?? 'end');

React.useEffect(() => {
if (!ref.current) return;
if (trim === undefined || maxLine === undefined) {
setIsEllipsized(false);
return;
};
ref.current.style.setProperty('overflow', 'hidden');
ref.current.style.setProperty('text-overflow', 'hidden');
ref.current.style.setProperty('white-space', 'pre');

const isEllipsized = isTextOverflowing(ref.current, maxLine > 1);
setIsEllipsized(isEllipsized);
}, [ref.current, trim, maxLine]);

const blockWidth = useResizeObserver(ref, isEllipsized ? undefined : { width: 0 }).width;

React.useEffect(() => {
if (!ref.current || !isEllipsized) return;
if (trim === undefined || maxLine === undefined) {
return;
}

if (trim === 'end') {
ref.current.style.setProperty('text-overflow', 'ellipsis');
}

if (trim === 'middle') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems we need to always include aria-label with the full text for trim = 'middle', beause otherwise the SR will read the truncated text

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the hint should add aria-label (if not, we will fix it there, what do you think?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it adds aria-label only when visible, i.e. on hover, or no?

Copy link
Contributor

@sheila-semrush sheila-semrush Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not, we will fix it there, what do you think?

yep, sure

ref.current.style.setProperty('display', 'flex');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the height of the parent element changes when switching between trim values
image


const styleElement = window.getComputedStyle(ref.current);
const dateSpan = document.createElement('temporary-block');
dateSpan.style.setProperty('font-size', styleElement.getPropertyValue('font-size'));
dateSpan.innerHTML = 'a';
document.body.appendChild(dateSpan);
const symbolWidth = dateSpan.getBoundingClientRect().width;
dateSpan.remove();

const displayedSymbols = Math.round(blockWidth / symbolWidth);
const evenDisplayedSymbols = displayedSymbols % 2 === 0 ? displayedSymbols : displayedSymbols - 1;

const text = ref.current.textContent ?? '';

const begining = text.substring(0, text.length - evenDisplayedSymbols / 2 - 1);
const tail = text.substring(text.length - evenDisplayedSymbols / 2 - 1);

ref.current.innerHTML = `<span style="overflow: hidden; text-overflow: ellipsis">${begining}</span><span>${tail}</span>`;
}
}, [ref.current, trim, maxLine, isEllipsized, blockWidth]);

return isEllipsized;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const useResizeObserver = (
ro.disconnect();
};
}
}, [hookOverride]);
}, [hookOverride, ref.current]);

if (hookOverride) {
return hookOverride;
Expand Down
Loading
Loading