Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c894415
[core, link] added text-width-calculation
ilyabrower May 21, 2026
a75aefa
[base-trigger, fullscreen-modal, side-panel] replaces old css-ellipsi…
ilyabrower May 21, 2026
84058d6
[chore] Merge remote-tracking branch 'origin/release/v17' into UIK-50…
ilyabrower May 29, 2026
fa93fd3
[chore] update test stpries and tests
Valeria-Zimnitskaya Jun 1, 2026
4960f89
Merge branch 'release/v17' into UIK-5017/ellipsis-cleanup
Valeria-Zimnitskaya Jun 1, 2026
12e6b93
[chore] fix test story
Valeria-Zimnitskaya Jun 1, 2026
64ed87d
[stories] changed backWMax type to text in FullscreenModal
sheila-semrush Jun 1, 2026
978e0e0
[fullscreen-modal] update snapshots
Valeria-Zimnitskaya Jun 2, 2026
16ba63e
[base-trigger] fixed text-align
ilyabrower Jun 2, 2026
b827ef7
Merge branch 'release/v17' into UIK-5017/ellipsis-cleanup
Valeria-Zimnitskaya Jun 2, 2026
f3bbd1b
[base-trigger] fixed text-align
ilyabrower Jun 2, 2026
90c9500
[chore] upd snapshots
Valeria-Zimnitskaya Jun 2, 2026
3b088c2
[chore] update snapshots and fullscreen-modal test
Valeria-Zimnitskaya Jun 3, 2026
c6157d6
[chore] update snapshots and fullscreen-modal test
Valeria-Zimnitskaya Jun 3, 2026
69d32e0
[base-trigger] rollbacked styles
ilyabrower Jun 3, 2026
b585498
[chore] Merge branch 'UIK-5017/ellipsis-cleanup' of github.com:semrus…
ilyabrower Jun 3, 2026
8d57d57
Merge branch 'release/v17' into UIK-5017/ellipsis-cleanup
Valeria-Zimnitskaya Jun 3, 2026
9eead6a
[chore] update snapshots
Valeria-Zimnitskaya Jun 3, 2026
ec5da79
[chore] update snapshots
Valeria-Zimnitskaya Jun 3, 2026
f251728
[chore] update snapshots
Valeria-Zimnitskaya Jun 3, 2026
fc6e561
[chore] update test
Valeria-Zimnitskaya Jun 3, 2026
0da8eaa
[chore] update snapshots
Valeria-Zimnitskaya Jun 3, 2026
39c16b1
[chore] update snapshots
Valeria-Zimnitskaya Jun 3, 2026
6f16a4b
[chore] update snapshots
Valeria-Zimnitskaya Jun 3, 2026
46cc456
[chore] update test
Valeria-Zimnitskaya Jun 3, 2026
9b02bde
[link] added spin as available addon for calculating link text width
ilyabrower Jun 3, 2026
cc1172e
[chore] Merge branch 'UIK-5017/ellipsis-cleanup' of github.com:semrus…
ilyabrower Jun 3, 2026
94b442c
[base-trigger] update link trigger test
Valeria-Zimnitskaya Jun 3, 2026
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
3,486 changes: 1,873 additions & 1,613 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions semcore/base-trigger/__tests__/link-trigger.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,40 @@ test.describe(` ${TAG.VISUAL}`, () => {
});
});

// Section 2.5: LinkTrigger inside Select — ellipsis with addons
// Verifies truncation still works after removing manual calc() width logic in getTextProps.
test.describe('Link Trigger inside Select - ellipsis with addons', () => {
const selectSizes = [300, 600] as const;
const selectAddonCombos = [
{ showAddonLeft: true, showAddonRight: false, desc: 'left only' },
{ showAddonLeft: false, showAddonRight: true, desc: 'right only' },
{ showAddonLeft: false, showAddonRight: false, loading: true, desc: 'loading' },
];

selectSizes.forEach((size) => {
selectAddonCombos.forEach(({ desc, loading = false, ...addons }) => {
test(`Verify LinkTrigger inside Select truncates with ${desc}, size=${size}`, {
tag: [TAG.PRIORITY_HIGH, '@link-trigger', '@select', '@ellipsis'],
}, async ({ page }) => {
await loadPage(
page,
'stories/components/base-trigger/tests/examples/link-trigger/with-select.tsx',
'en',
{
size,
loading,
...addons,
ellipsis: { ellipsis: true },
w: size < 600 ? 150 : 300,
},
);
await page.waitForTimeout(150);
await expect(page).toHaveScreenshot();
});
});
});
});

// Section 3: No-ellipsis-hint tests — verify hint does NOT appear when text is not truncated
test.describe('Link Trigger without ellipsis', () => {
const noHintVariants = [
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 1 addition & 4 deletions semcore/base-trigger/src/LinkTrigger.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@ class RootLinkTrigger extends Component {
static displayName = 'LinkTrigger';

getTextProps(props) {
const { placeholder, empty, Children, size } = this.asProps;
const { placeholder, empty } = this.asProps;
const content = empty ? placeholder : props.children;
const addons = findAllComponents(Children, [LinkTrigger.Addon.displayName]);
const addonWidth = size >= 600 ? 28 : 20;

return {
'use:children': content,
empty,
'w': `calc(100% - ${addonWidth * (addons.length + 1)}px)`,
};
}

Expand Down
3 changes: 3 additions & 0 deletions semcore/base-trigger/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,8 @@ declare const FilterTrigger: Intergalactic.Component<'div', FilterTriggerProps>
ClearButton: typeof BaseTrigger;
};

/**
* @deprecated. Use one this: ButtonTrigger, FilterTrigger, LinkTrigger.
*/
export default BaseTrigger;
export { ButtonTrigger, LinkTrigger, FilterTrigger };
2 changes: 1 addition & 1 deletion semcore/date-picker/__tests__/date-picker.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ test.describe(`${TAG.VISUAL}`, () => {
'@date-picker'],
}, async ({ page }) => {
await loadPage(page, 'stories/components/date-picker/tests/examples/day-trigger.tsx', 'pt', {
size: 'm', state: 'normal', disabled: false, neighborLocation: 'right',
size: 'm', state: 'normal', disabled: false, neighborLocation: 'right', locale: 'pt',
});

const inputs = page.locator('input[data-ui-name="DatePicker.Trigger"]');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ test.describe(`${TAG.VISUAL}`, () => {
'@base-components'],
}, async ({ page }) => {
await loadPage(page, 'stories/components/date-picker/tests/examples/day-range-trigger.tsx', 'pt', {
size: 'm', state: 'normal', disabled: false, neighborLocation: 'right',
size: 'm', state: 'normal', disabled: false, neighborLocation: 'right', locale: 'pt',
});

const inputs = page.locator('input[data-ui-name="DateRangePicker.Trigger"]');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ test.describe(`${TAG.VISUAL} `, () => {
closable: false,
showClose: true,
showBack: true,
backText: 'Go Back',
backText: 'Go to Tool',
titleText: '',
descriptionText: '',
showDescriptionTooltip: false,
Expand Down Expand Up @@ -238,14 +238,29 @@ test.describe(`${TAG.VISUAL} `, () => {
closable: false,
showClose: false,
showBack: true,
backText: 'Go Back',
backText: 'Go to Tool',
titleText: 'Modal with no close option',
descriptionText: 'Only Escape key can close this modal',
showDescriptionTooltip: false,
hasBody: true,
hasFooter: true,
testName: 'not-closable-no-close-button',
},
// Long back text + small wMax — verifies ellipsis truncation on Back button
{
closable: false,
showClose: true,
showBack: true,
backText: 'This is a very long Back navigation label that must be truncated',
backWMax: 80,
titleText: 'Modal Title',
descriptionText: 'Description text',
showDescriptionTooltip: false,
hasBody: true,
hasFooter: true,
testName: 'back-long-text-small-wmax-ellipsis',
skipSnapshot: true,
},
];

headerVariations.forEach((config) => {
Expand All @@ -271,6 +286,21 @@ test.describe(`${TAG.VISUAL} `, () => {
const backButton = locators.button(page, config.backText);
await expect(backButton).toBeVisible();
});

if ((config as { backWMax?: number }).backWMax !== undefined) {
await test.step('Verify Back text is truncated when wMax is constrained', async () => {
const back = page.locator('[data-ui-name="FullscreenModal.Back"]');
const backBox = await back.boundingBox();
expect(backBox!.width).toBeLessThanOrEqual(
(config as { backWMax: number }).backWMax + 1,
);
const textNode = back.locator('[data-ui-name="ButtonLink.Text"]');
const isTruncated = await textNode.evaluate(
(el) => el.scrollWidth > el.clientWidth,
);
expect(isTruncated).toBe(true);
});
}
}

if (config.titleText) {
Expand Down Expand Up @@ -323,13 +353,15 @@ test.describe(`${TAG.VISUAL} `, () => {
expect(headerStyles.alignItems).toBe('flex-start');
});

await test.step('Take visual snapshot', async () => {
if (config.showClose || config.closable) {
const closeButton = locators.button(page, 'Close');
await closeButton.hover();
}
await expect(page).toHaveScreenshot();
});
if (!(config as { skipSnapshot?: boolean }).skipSnapshot) {
await test.step('Take visual snapshot', async () => {
if (config.showClose || config.closable) {
const closeButton = locators.button(page, 'Close');
await closeButton.hover();
}
await expect(page).toHaveScreenshot();
});
}
});
});
});
Expand Down Expand Up @@ -371,6 +403,7 @@ test.describe(`${TAG.FUNCTIONAL} `, () => {

await page.keyboard.press('Tab');
await expect(locators.button(page, 'Go to Tool Name')).toBeFocused();

await page.keyboard.press('Enter');

await locators.button(page, 'Close').waitFor({ state: 'hidden' });
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions semcore/fullscreen-modal/src/FullscreenModal.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Flex, Box } from '@semcore/base-components';
import Button from '@semcore/button';
import Button, { ButtonLink } from '@semcore/button';
import { createComponent, Component, sstyled, Root } from '@semcore/core';
import i18nEnhance from '@semcore/core/lib/utils/enhances/i18nEnhance';
import fire from '@semcore/core/lib/utils/fire';
Expand Down Expand Up @@ -147,15 +147,13 @@ function Description(props) {

function Back(props) {
const SBack = Root;
const SBackText = Text;
const { Children, styles } = props;

return sstyled(styles)(
<SBack render={Box} tag='button' tabIndex={0}>
<ArrowLeft />
<SBackText>
<SBack render={ButtonLink} color='text-hint' size={200} addonLeft={ArrowLeft}>
<ButtonLink.Text ellipsis>
<Children />
</SBackText>
</ButtonLink.Text>
</SBack>,
);
}
Expand Down
22 changes: 0 additions & 22 deletions semcore/fullscreen-modal/src/style/fullscreen-modal.shadow.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,7 @@ SBack {
z-index: 1;
top: 8px;
left: 32px;
display: flex;
align-items: center;
margin-bottom: var(--intergalactic-spacing-3x, 12px);
color: var(--intergalactic-icon-primary-neutral, oklch(0.092 0.024 152.2 / 0.526));
font-size: var(--intergalactic-fs-100, 12px);
line-height: var(--intergalactic-lh-100, 133%);
background: none;
padding: 0;
border: none;
outline: none;

&:hover {
color: var(--intergalactic-icon-primary-neutral-hover-active, oklch(0.088 0.026 147.7 / 0.583));
}
}

SBackText {
margin-left: var(--intergalactic-spacing-1x, 4px);
font-size: var(--intergalactic-fs-200, 14px);
line-height: var(--intergalactic-lh-200, 142%);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

STitle,
Expand Down
7 changes: 3 additions & 4 deletions semcore/link/src/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { BoxProps } from '@semcore/base-components';
import { Box, Hint } from '@semcore/base-components';
import type { Intergalactic, IRootComponentProps } from '@semcore/core';
import { createComponent, Component, Root, sstyled, CORE_INSTANCE } from '@semcore/core';
import type { IRootComponentProps } from '@semcore/core';
import { createComponent, Component, Root, sstyled, CORE_INSTANCE, INHERITED_NAME } from '@semcore/core';
import addonTextChildren from '@semcore/core/lib/utils/addonTextChildren';
import resolveColorEnhance from '@semcore/core/lib/utils/enhances/resolveColorEnhance';
import { findAllComponents } from '@semcore/core/lib/utils/findComponent';
Expand Down Expand Up @@ -56,7 +55,7 @@ class RootLink extends Component<LinkProps, typeof RootLink.enhance, never, {},
const addonWidth = size === undefined || size < 600 ? 20 : 28;

let addonsCount = addons.reduce((acc, addon) => {
if (addon.props.tag?.__IS_ICON || addon.props.children?.type?.__IS_ICON) {
if (addon.props.tag?.__IS_ICON || addon.props.children?.type?.__IS_ICON || addon.props.children?.type?.[INHERITED_NAME].includes('Spin')) {
acc++;
}
return acc;
Expand Down
7 changes: 6 additions & 1 deletion semcore/pagination/__tests__/pagination.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,12 @@ test.describe(`${TAG.VISUAL}`, () => {
test(`Verify pagination number formatting with locale=${item.locale}, totalPages=${item.totalPages}, currentPage=${item.currentPage}, size=${item.size}`, {
tag: [TAG.PRIORITY_HIGH, '@pagination'],
}, async ({ page }) => {
await loadPage(page, 'stories/components/pagination/tests/examples/pagination-props.tsx', item.locale, { totalPages: item.totalPages, currentPage: item.currentPage, size: item.size });
await loadPage(page, 'stories/components/pagination/tests/examples/pagination-props.tsx', item.locale, {
totalPages: item.totalPages,
currentPage: item.currentPage,
size: item.size,
locale: item.locale,
});

await expect(page).toHaveScreenshot();
});
Expand Down
32 changes: 32 additions & 0 deletions semcore/side-panel/__tests__/side-panel.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,38 @@ test.describe(`${TAG.VISUAL} `, () => {
await page.locator('[data-ui-name="Hint"]').nth(1).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});

test('Verify SidePanel.Back with long text truncates via ellipsis', {
tag: [TAG.PRIORITY_HIGH, '@side-panel', '@ellipsis', '@button'],
}, async ({ page }) => {
await loadPage(
page,
'stories/components/side-panel/tests/examples/side-panel-additional-states.tsx',
'en',
{
backText: 'This is a very long Back navigation label that must be truncated',
backWMax: 120,
withFooter: true,
},
);

await page.keyboard.press('Tab');
await page.keyboard.press('Enter');
await locators.back(page).waitFor({ state: 'visible' });

await test.step('Back container width is constrained by wMax', async () => {
const backBox = await locators.back(page).boundingBox();
expect(backBox!.width).toBeLessThanOrEqual(121);
});

await test.step('Back inner text node is actually truncated', async () => {
const textNode = locators.back(page).locator('[data-ui-name="ButtonLink.Text"]');
const isTruncated = await textNode.evaluate(
(el) => el.scrollWidth > el.clientWidth,
);
expect(isTruncated).toBe(true);
});
});
});

/* =====================================================
Expand Down
6 changes: 2 additions & 4 deletions semcore/side-panel/src/SidePanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,13 @@ function Title(props) {

function Back(props) {
const SBack = Root;
const SBackText = ButtonLink.Text;
const { Children, styles } = props;

return sstyled(styles)(
<SBack render={ButtonLink} color='text-hint' size={100} addonLeft={ArrowLeft}>
{/* <ButtonLink.Addon><ArrowLeft /></ButtonLink.Addon> */}
<SBackText>
<ButtonLink.Text ellipsis>
<Children />
</SBackText>
</ButtonLink.Text>
</SBack>,
);
}
Expand Down
6 changes: 0 additions & 6 deletions semcore/side-panel/src/style/side-panel.shadow.css
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@ SClose {

SBack {
max-width: 100%;

SBackText {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

SHeader {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const Demo = (props: BaseTriggerEllipsisProps) => {
<DropdownMenu>
<DropdownMenu.Trigger tag={[BaseTrigger, 'h1']}>
<BaseTrigger.Text w={150} tag='h2' size={400}>
No ellipsis Few Tags Tags Tags
ellipsis with few few Few Tags
</BaseTrigger.Text>
</DropdownMenu.Trigger>
<br />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type HeaderConfig = {
showClose?: boolean;
showBack?: boolean;
backText?: string;
backWMax?: string;
titleText?: string;
titleWidth?: number;
descriptionText?: string;
Expand All @@ -35,7 +36,7 @@ const Demo = (props: HeaderConfig) => {
{props.showClose && <FullscreenModal.Close />}

{props.showBack && (
<FullscreenModal.Back>
<FullscreenModal.Back wMax={props.backWMax}>
{props.backText}
</FullscreenModal.Back>
)}
Expand Down Expand Up @@ -101,7 +102,6 @@ export const defaultProps: HeaderConfig = {
showBack: false,
backText: 'Go to Tool Name',
titleText: 'Modal Window Title',
titleWidth: undefined,
descriptionText: 'Additional information about this modal',
showDescriptionTooltip: false,
hasBody: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const ConfigurableHeader: StoryObj = {
showClose: { control: 'boolean' },
showBack: { control: 'boolean' },
backText: { control: 'text' },
backWMax: { control: 'text' },
titleText: { control: 'text' },
titleWidth: { control: 'number' },
descriptionText: { control: 'text' },
Expand Down
Loading
Loading