From 8bda80fd4b1e469d9b218068e1d1c278178e1a6a Mon Sep 17 00:00:00 2001 From: "ilia.brauer" Date: Thu, 23 Jul 2026 11:36:39 +0200 Subject: [PATCH 1/5] [link, button, base-trigger] changed link styles --- .../src/component/ButtonLink/ButtonLink.tsx | 10 +- .../ButtonLink/buttonLink.shadow.css | 16 ++- semcore/link/src/Link.tsx | 41 +++++-- semcore/link/src/Link.types.ts | 103 ++++++++++++------ semcore/link/src/style/link.shadow.css | 65 ++++++++--- .../link/docs/examples/all_states.tsx | 24 ++++ stories/components/link/docs/link.stories.tsx | 5 + .../style/design-tokens/design-tokens.json | 18 ++- 8 files changed, 211 insertions(+), 71 deletions(-) create mode 100644 stories/components/link/docs/examples/all_states.tsx diff --git a/semcore/button/src/component/ButtonLink/ButtonLink.tsx b/semcore/button/src/component/ButtonLink/ButtonLink.tsx index 0723521fe4..ac3bef4613 100644 --- a/semcore/button/src/component/ButtonLink/ButtonLink.tsx +++ b/semcore/button/src/component/ButtonLink/ButtonLink.tsx @@ -1,4 +1,4 @@ -import { createComponent, sstyled, Root, Component } from '@semcore/core'; +import { createComponent, sstyled, Root, Component, type IRootComponentProps } from '@semcore/core'; import Link from '@semcore/link'; import React from 'react'; @@ -36,6 +36,12 @@ class RootButtonLink extends Component< } } +function Text(props: IRootComponentProps) { + const SText = Root; + const { styles } = props; + return sstyled(styles)(); +} + /** * ButtonLink * @@ -44,7 +50,7 @@ class RootButtonLink extends Component< export const ButtonLink = createComponent( RootButtonLink, { - Text: Link.Text, + Text, Addon: Link.Addon, }, { diff --git a/semcore/button/src/component/ButtonLink/buttonLink.shadow.css b/semcore/button/src/component/ButtonLink/buttonLink.shadow.css index 82e845746c..0410db9f40 100644 --- a/semcore/button/src/component/ButtonLink/buttonLink.shadow.css +++ b/semcore/button/src/component/ButtonLink/buttonLink.shadow.css @@ -4,12 +4,20 @@ SButtonLink { } SButtonLink[use='primary']:not([color]) { - color: var(--intergalactic-text-link, oklch(0.1 0.03 137 / 0.899)); /* TODO: --intergalactic-text-link-primary */ + color: var(--intergalactic-text-link-primary, oklch(0.1 0.03 137 / 0.899)); + + SText { + text-decoration-color: transparent; + } &[active], &:active, &:hover { - color: var(--intergalactic-text-link-hover-active, oklch(0.1 0.03 137 / 0.899)); /* TODO: --intergalactic-text-link-primary-hover-active */ + color: var(--intergalactic-text-link-primary-hover-active, oklch(0.1 0.03 137 / 0.899)); + + SText { + text-decoration-color: currentColor; + } } } @@ -19,11 +27,11 @@ SButtonLink[use='secondary']:not([color]) { &[active], &:active, &:hover { - color: var(--intergalactic-text-hint-hover-active, oklch(0.086 0.026 145.8 / 0.605)); + color: var(--intergalactic-text-link-primary, oklch(0.1 0.03 137 / 0.899)); } } SButtonLink[use='secondary'] SText { - text-decoration-style: dashed; + text-decoration-style: dotted; text-decoration-color: currentColor; } diff --git a/semcore/link/src/Link.tsx b/semcore/link/src/Link.tsx index 5086cc3a42..2a5a3a4654 100644 --- a/semcore/link/src/Link.tsx +++ b/semcore/link/src/Link.tsx @@ -2,29 +2,32 @@ import { Box, Hint } from '@semcore/base-components'; 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 canUseDOM from '@semcore/core/lib/utils/canUseDOM'; import resolveColorEnhance from '@semcore/core/lib/utils/enhances/resolveColorEnhance'; import { findAllComponents } from '@semcore/core/lib/utils/findComponent'; import hasLabels from '@semcore/core/lib/utils/hasLabels'; import logger from '@semcore/core/lib/utils/logger'; +import LinkExternalAltM from '@semcore/icon/LinkExternalAlt/m'; import type { NSText } from '@semcore/typography'; import { Text } from '@semcore/typography'; import React from 'react'; -import type { LinkComponent, LinkProps } from './Link.types'; +import type { NSLink } from './Link.types'; import style from './style/link.shadow.css'; -type State = { - ariaLabelledByContent: string; -}; - -class RootLink extends Component { +class RootLink extends Component { static displayName = 'Link'; static style = style; static enhance = [resolveColorEnhance()] as const; + + static defaultProps = { + use: 'primary', + } as const; + containerRef = React.createRef(); - state: State = { + state: NSLink.State = { ariaLabelledByContent: '', }; @@ -74,6 +77,23 @@ class RootLink extends Component ) : null} - {addonTextChildren(Children, Link.Text, Link.Addon)} + {this.isExternalLink() ? ({Children.origin}) : addonTextChildren(Children, Link.Text, Link.Addon)} {AddonRight ? ( @@ -166,7 +187,7 @@ function Addon(props: IRootComponentProps) { * * {@link https://developer.semrush.com/intergalactic/components/link/link-api/|API} | {@link https://developer.semrush.com/intergalactic/components/link/link-code/|Examples} */ -const Link = createComponent(RootLink, { +const Link = createComponent(RootLink, { Text: LinkText, Addon, }); diff --git a/semcore/link/src/Link.types.ts b/semcore/link/src/Link.types.ts index baa4b0b14a..964e95f630 100644 --- a/semcore/link/src/Link.types.ts +++ b/semcore/link/src/Link.types.ts @@ -4,40 +4,73 @@ import type Icon from '@semcore/icon'; import type { NSText } from '@semcore/typography'; import type React from 'react'; -export type LinkProps = BoxProps & NSText.BaseProps & { - /** - * CSS property of the display link (inline|inline-block) - * @default false - * @deprecated. You should use default inline-flex for all cases. - */ - inline?: boolean; - /** - * Sets the link to the disabled state - */ - disabled?: boolean; - /** - * Sets the link to the active state - */ - active?: boolean; - /** This flag enables highlighting of the visited link - */ - enableVisited?: boolean; - /** The text will not be moved to a new line - * @default false - */ - noWrap?: boolean; - /** Left addon tag */ - addonLeft?: typeof Icon | React.ElementType; - /** Right addon tag */ - addonRight?: typeof Icon | React.ElementType; - /** - * The position of the popper relative to the trigger that called it. - * @default top - */ - hintPlacement?: SimpleHintPopperProps['placement']; -}; +type NoHttp = T extends `http${string}` ? never : T; + +declare namespace NSLink { + type Use = 'primary' | 'secondary' | 'accent'; + type CommonProps = BoxProps & Intergalactic.InternalTypings.EfficientOmit & { + /** + * Type of Link. + * Primary - Black. The vast majority of links. Tables with URLs and keywords, metrics in the summary. + * Secondary - Gray. Links such as 'Learn more', 'Show more', secondary information, opening hints. + * Accent - Blue. Use ONLY for action links within the texts. Limits, prompts indicating what to do, and options in the controls. + * + * @default 'primary'. + */ + use?: Use; + /** + * Sets the link to the disabled state + */ + disabled?: boolean; + /** + * Sets the link to the active state + */ + active?: boolean; + /** This flag enables highlighting of the visited link + */ + enableVisited?: boolean; + /** The text will not be moved to a new line + * @default false + */ + noWrap?: boolean; + /** + * The position of the popper relative to the trigger that called it. + * @default top + */ + hintPlacement?: SimpleHintPopperProps['placement']; + }; + + type InternalProps = CommonProps & { + /** Left addon tag */ + addonLeft?: typeof Icon | React.ElementType; + /** Right addon tag */ + addonRight?: typeof Icon | React.ElementType; + }; + + type ExternalProps = CommonProps; + + type Props = InternalProps | ExternalProps; + + type State = { + ariaLabelledByContent: string; + }; + + type DefaultProps = { + use: 'primary'; + }; + + type Component = Intergalactic.Component<'a', Props> & { + Text: Intergalactic.Component<'span', NSText.Props>; + Addon: Intergalactic.Component<'span', BoxProps>; + }; +} + +/** @deprecated It will be removed in v18. */ +export type LinkProps = NSLink.InternalProps; + +/** @deprecated It will be removed in v18. */ +export type LinkComponent = NSLink.Component; -export type LinkComponent = Intergalactic.Component<'a', LinkProps> & { - Text: Intergalactic.Component<'span', NSText.Props>; - Addon: Intergalactic.Component<'span', BoxProps>; +export { + NSLink, }; diff --git a/semcore/link/src/style/link.shadow.css b/semcore/link/src/style/link.shadow.css index 23dd087a92..53eaf1fab8 100644 --- a/semcore/link/src/style/link.shadow.css +++ b/semcore/link/src/style/link.shadow.css @@ -1,7 +1,6 @@ SLink { display: inline; align-items: center; - color: var(--intergalactic-text-link-primary, oklch(0.1 0.03 137 / 0.899)); position: relative; cursor: pointer; text-decoration: none; @@ -14,26 +13,67 @@ SLink { padding: 0; } - &[active], - &:hover, - &:active { - color: var(--intergalactic-text-link-primary-hover-active, oklch(0.1 0.03 137 / 0.899)); + &[enableVisited]:visited, + &[enableVisited]:visited:hover { + color: var(--intergalactic-text-link-visited, oklch(0.23 0.113 296)); + } + + &[use='primary'] { + color: var(--intergalactic-text-link-primary, oklch(0.1 0.03 137 / 0.899)); & SText { - text-decoration-color: currentColor; + text-decoration-color: var(--intergalactic-text-link-primary-underline, oklch(0.86 0.002 174.1)); + } + + &[active], + &:hover, + &:active { + color: var(--intergalactic-text-link-primary-hover-active, oklch(0.1 0.03 137 / 0.899)); + + & SText { + text-decoration-color: currentColor; + } } } + &[use='secondary'] { + color: var(--intergalactic-text-link-secondary, oklch(0.088 0.026 147.7 / 0.583)); - &[enableVisited]:visited, - &[enableVisited]:visited:hover { - color: var(--intergalactic-text-link-visited, oklch(0.23 0.113 296)); + & SText { + text-decoration-color: transparent; + } + + &[active], + &:hover, + &:active { + color: var(--intergalactic-text-link-secondary-hover-active, oklch(0.088 0.026 147.7 / 0.583)); + + & SText { + text-decoration-color: currentColor; + } + } + } + &[use='accent'] { + color: var(--intergalactic-text-link-accent, oklch(0.6 0.166 277.7)); + + & SText { + text-decoration-color: transparent; + } + + &[active], + &:hover, + &:active { + color: var(--intergalactic-text-link-accent-hover-active, oklch(0.6 0.166 277.7)); + + & SText { + text-decoration-color: currentColor; + } + } } } SLink[visually-disabled] { opacity: var(--intergalactic-disabled-opacity, 0.4); cursor: default; - /* Disable link interactions */ pointer-events: none; } @@ -41,10 +81,6 @@ SLink[noWrap] { white-space: nowrap; } -SLink[inline] { - display: inline; -} - SInner { align-items: baseline; height: 100%; @@ -72,7 +108,6 @@ SText { text-decoration: underline; text-decoration-style: solid; text-decoration-thickness: 1px; - text-decoration-color: var(--intergalactic-text-link-primary-underline, oklch(0.86 0.002 174.1)); text-underline-offset: 17%; transition: text-decoration-color 0.15s ease-in-out; diff --git a/stories/components/link/docs/examples/all_states.tsx b/stories/components/link/docs/examples/all_states.tsx new file mode 100644 index 0000000000..7ac2935b7e --- /dev/null +++ b/stories/components/link/docs/examples/all_states.tsx @@ -0,0 +1,24 @@ +import { Box } from '@semcore/ui/base-components'; +import Link from '@semcore/ui/link'; +import React from 'react'; + +const Demo = () => { + return ( + + Primary link +
+ Secondary link +
+ Accent link +
+
+ Primary external link +
+ Secondary external link +
+ Accent external link +
+ ); +}; + +export default Demo; diff --git a/stories/components/link/docs/link.stories.tsx b/stories/components/link/docs/link.stories.tsx index 879b3abc90..eca6e2f99a 100644 --- a/stories/components/link/docs/link.stories.tsx +++ b/stories/components/link/docs/link.stories.tsx @@ -1,6 +1,7 @@ import Link from '@semcore/ui/link'; import type { Meta, StoryObj } from '@storybook/react-vite'; +import AllStatesExample from './examples/all_states'; import ColorLinksExample from './examples/color_links'; import LinkAddonExample from './examples/link_addon'; import LinkAsButtonExample from './examples/link_as_button'; @@ -17,6 +18,10 @@ const meta: Meta = { export default meta; type Story = StoryObj; +export const AllStates: Story = { + render: AllStatesExample, +}; + export const ColorLinks: Story = { render: ColorLinksExample, }; diff --git a/website/docs/style/design-tokens/design-tokens.json b/website/docs/style/design-tokens/design-tokens.json index 2f33224f83..5d3ceb301c 100644 --- a/website/docs/style/design-tokens/design-tokens.json +++ b/website/docs/style/design-tokens/design-tokens.json @@ -2593,7 +2593,6 @@ "value": "oklch(0.086 0.026 145.8 / 0.605)", "description": "Hover and active states of the hint link text.", "components": [ - "button", "typography" ] }, @@ -2660,6 +2659,7 @@ "value": "oklch(0.1 0.03 137 / 0.899)", "description": "Default primary link color.", "components": [ + "button", "link" ] }, @@ -2668,6 +2668,7 @@ "value": "oklch(0.1 0.03 137 / 0.899)", "description": "Hover and active states for the primary link.", "components": [ + "button", "link" ] }, @@ -2695,27 +2696,34 @@ "name": "--intergalactic-text-link-secondary", "value": "oklch(0.088 0.026 147.7 / 0.583)", "description": "Default secondary link color.", - "components": [] + "components": [ + "link" + ] }, { "name": "--intergalactic-text-link-secondary-hover-active", "value": "oklch(0.088 0.026 147.7 / 0.583)", "description": "Hover and active states for the secondary link.", - "components": [] + "components": [ + "link" + ] }, { "name": "--intergalactic-text-link-accent", "value": "oklch(0.6 0.166 277.7)", "description": "Default accent link color.", "components": [ - "button" + "button", + "link" ] }, { "name": "--intergalactic-text-link-accent-hover-active", "value": "oklch(0.6 0.166 277.7)", "description": "Hover and active states for the accent link.", - "components": [] + "components": [ + "link" + ] }, { "name": "--intergalactic-text-link-visited", From f0e9d6264a700c07e822e478d7b441b086f7fbac Mon Sep 17 00:00:00 2001 From: "ilia.brauer" Date: Fri, 24 Jul 2026 12:37:40 +0200 Subject: [PATCH 2/5] [link] added isExternal property --- semcore/link/src/Link.tsx | 12 +++++++++--- semcore/link/src/Link.types.ts | 20 ++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/semcore/link/src/Link.tsx b/semcore/link/src/Link.tsx index 2a5a3a4654..1c01215b38 100644 --- a/semcore/link/src/Link.tsx +++ b/semcore/link/src/Link.tsx @@ -78,7 +78,10 @@ class RootLink extends Component = T extends `http${string}` ? never : T; - declare namespace NSLink { type Use = 'primary' | 'secondary' | 'accent'; - type CommonProps = BoxProps & Intergalactic.InternalTypings.EfficientOmit & { + type Props = BoxProps & Intergalactic.InternalTypings.EfficientOmit & { /** * Type of Link. + * * Primary - Black. The vast majority of links. Tables with URLs and keywords, metrics in the summary. + * * Secondary - Gray. Links such as 'Learn more', 'Show more', secondary information, opening hints. + * * Accent - Blue. Use ONLY for action links within the texts. Limits, prompts indicating what to do, and options in the controls. * * @default 'primary'. @@ -38,19 +39,14 @@ declare namespace NSLink { * @default top */ hintPlacement?: SimpleHintPopperProps['placement']; - }; - - type InternalProps = CommonProps & { /** Left addon tag */ addonLeft?: typeof Icon | React.ElementType; /** Right addon tag */ addonRight?: typeof Icon | React.ElementType; + /** Flag to mark a link as external. Use it in SSR. */ + isExternal?: boolean; }; - type ExternalProps = CommonProps; - - type Props = InternalProps | ExternalProps; - type State = { ariaLabelledByContent: string; }; @@ -66,7 +62,7 @@ declare namespace NSLink { } /** @deprecated It will be removed in v18. */ -export type LinkProps = NSLink.InternalProps; +export type LinkProps = NSLink.Props; /** @deprecated It will be removed in v18. */ export type LinkComponent = NSLink.Component; From fb67e5d316ed9a96db2055e2fda60001b7b17c12 Mon Sep 17 00:00:00 2001 From: "ilia.brauer" Date: Fri, 24 Jul 2026 12:58:58 +0200 Subject: [PATCH 3/5] [link] fixed test story --- stories/components/link/tests/examples/basic_usage.tsx | 4 ++++ stories/components/link/tests/link.stories.tsx | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/stories/components/link/tests/examples/basic_usage.tsx b/stories/components/link/tests/examples/basic_usage.tsx index 5b98236bff..d2490e9b5c 100644 --- a/stories/components/link/tests/examples/basic_usage.tsx +++ b/stories/components/link/tests/examples/basic_usage.tsx @@ -31,6 +31,7 @@ type BasicLinkProps = LinkProps & { const Demo = (props: BasicLinkProps) => { const { text = 'Link example', + use, showAddonLeft = false, showAddonRight = false, disabled, @@ -103,6 +104,7 @@ const Demo = (props: BasicLinkProps) => { return ( { {`${numSize} `} { export const defaultProps: BasicLinkProps = { text: 'Link example', href: '#', + use: 'primary', size: 300, showAddonLeft: false, showAddonRight: false, diff --git a/stories/components/link/tests/link.stories.tsx b/stories/components/link/tests/link.stories.tsx index d0c5bb902f..bfff84895d 100644 --- a/stories/components/link/tests/link.stories.tsx +++ b/stories/components/link/tests/link.stories.tsx @@ -19,6 +19,14 @@ export const BasicUsage: StoryObj = { text: { control: { type: 'text' }, }, + use: { + control: { type: 'select' }, + options: [ + 'primary', + 'secondary', + 'accent', + ], + }, href: { control: { type: 'text' }, }, From f26bd4943e92391852642ad406ba580508fcfac8 Mon Sep 17 00:00:00 2001 From: Julia Mnizhek Date: Fri, 24 Jul 2026 16:34:54 +0200 Subject: [PATCH 4/5] [stories] updates test stories --- semcore/link/src/Link.types.ts | 6 ++-- .../link/docs/examples/all_states.tsx | 29 +++++++++---------- .../advanced/components/Components/index.tsx | 2 ++ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/semcore/link/src/Link.types.ts b/semcore/link/src/Link.types.ts index 817576925d..879192b975 100644 --- a/semcore/link/src/Link.types.ts +++ b/semcore/link/src/Link.types.ts @@ -10,11 +10,11 @@ declare namespace NSLink { /** * Type of Link. * - * Primary - Black. The vast majority of links. Tables with URLs and keywords, metrics in the summary. + * Primary. The vast majority of links. Tables with URLs and keywords, metrics in the summary. * - * Secondary - Gray. Links such as 'Learn more', 'Show more', secondary information, opening hints. + * Secondary. Links such as 'Learn more', 'Show more', secondary information, opening hints. * - * Accent - Blue. Use ONLY for action links within the texts. Limits, prompts indicating what to do, and options in the controls. + * Accent. Use ONLY for action links within the texts. Limits, prompts indicating what to do, and options in the controls. * * @default 'primary'. */ diff --git a/stories/components/link/docs/examples/all_states.tsx b/stories/components/link/docs/examples/all_states.tsx index 7ac2935b7e..9584c897c4 100644 --- a/stories/components/link/docs/examples/all_states.tsx +++ b/stories/components/link/docs/examples/all_states.tsx @@ -1,23 +1,22 @@ -import { Box } from '@semcore/ui/base-components'; +import { Flex } from '@semcore/ui/base-components'; import Link from '@semcore/ui/link'; import React from 'react'; const Demo = () => { return ( - - Primary link -
- Secondary link -
- Accent link -
-
- Primary external link -
- Secondary external link -
- Accent external link -
+ + + Primary link + Secondary link + Accent link + + + + Primary external link + Secondary external link + Accent external link + + ); }; diff --git a/stories/patterns/core/advanced/components/Components/index.tsx b/stories/patterns/core/advanced/components/Components/index.tsx index ad2bba833e..634e1a5b1f 100644 --- a/stories/patterns/core/advanced/components/Components/index.tsx +++ b/stories/patterns/core/advanced/components/Components/index.tsx @@ -22,6 +22,7 @@ import InlineNumberInput from '../../../../../components/inline-input/docs/examp import InputClear from '../../../../../components/input/docs/examples/input_with_the_clearing_ability'; import InputNumberDemo from '../../../../../components/input-number/docs/examples/range_of_values'; import InputTags from '../../../../../components/input-tags/docs/examples/entering_and_editing_tags'; +import LinkAllStatesExample from '../../../../../components/link/docs/examples/all_states'; import LinkColorLinksExample from '../../../../../components/link/docs/examples/color_links'; import BasicNoticeExample from '../../../../../components/notice/docs/examples/basic_notice'; import PillsBasicExample, { @@ -75,6 +76,7 @@ export function Components() { + From fcd616a1b099be3701cef1d15b7549f21268c669 Mon Sep 17 00:00:00 2001 From: "ilia.brauer" Date: Tue, 28 Jul 2026 10:06:48 +0200 Subject: [PATCH 5/5] [link, data-table] added LinkAction component for render links in table --- pnpm-lock.yaml | 5 ++- semcore/data-table/package.json | 1 + .../src/components/LinkAction/LinkAction.tsx | 32 +++++++++++++++++ semcore/data-table/src/index.ts | 2 ++ semcore/link/src/Link.tsx | 6 +++- .../tests/examples/in_table_with_link.tsx | 35 +++++++------------ 6 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 semcore/data-table/src/components/LinkAction/LinkAction.tsx diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdda9ec380..8457fcdd80 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -764,6 +764,9 @@ importers: '@semcore/checkbox': specifier: ^17.2.1 version: link:../checkbox + '@semcore/link': + specifier: ^17.2.1 + version: link:../link '@semcore/spin': specifier: ^17.2.1 version: link:../spin @@ -19556,7 +19559,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@9.20.3)(jsdom@22.1.0)(lightningcss@1.31.1)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.8.3) + vitest: 3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@9.20.3)(jsdom@22.1.0)(lightningcss@1.31.1)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.48.0)(yaml@2.8.3) '@vitest/utils@3.2.4': dependencies: diff --git a/semcore/data-table/package.json b/semcore/data-table/package.json index 0e08a0d78a..a1f296c14e 100644 --- a/semcore/data-table/package.json +++ b/semcore/data-table/package.json @@ -21,6 +21,7 @@ "@semcore/checkbox": "^17.2.1", "@semcore/spin": "^17.2.1", "@semcore/tooltip": "^17.2.1", + "@semcore/link": "^17.2.1", "@semcore/widget-empty": "^17.2.1" }, "devDependencies": { diff --git a/semcore/data-table/src/components/LinkAction/LinkAction.tsx b/semcore/data-table/src/components/LinkAction/LinkAction.tsx new file mode 100644 index 0000000000..d81bcf8a61 --- /dev/null +++ b/semcore/data-table/src/components/LinkAction/LinkAction.tsx @@ -0,0 +1,32 @@ +import { ButtonLink } from '@semcore/button'; +import Divider from '@semcore/divider'; +import LinkExternalM from '@semcore/icon/LinkExternal/m'; +import Link from '@semcore/link'; +import type { NSText } from '@semcore/typography'; +import React from 'react'; + +interface IProps extends NSText.BaseProps, NSText.EllipsisProps, NSText.HintProps { + displayHref: string; + externalHref: string; + internalAction: string | (() => void); +} + +export class LinkAction extends React.PureComponent { + render(): React.ReactNode { + const { displayHref, externalHref, internalAction, ...textProps } = this.props; + return ( + <> + {typeof internalAction === 'string' + ? ({displayHref}) + : ({displayHref})} + + } + aria-label={externalHref} + /> + + ); + } +} diff --git a/semcore/data-table/src/index.ts b/semcore/data-table/src/index.ts index b12cd90ef1..05988a3fce 100644 --- a/semcore/data-table/src/index.ts +++ b/semcore/data-table/src/index.ts @@ -13,6 +13,7 @@ import type { ColumnGroupConfig, ColumnItemConfig, } from './components/DataTable/DataTable.types'; +import { LinkAction } from './components/LinkAction/LinkAction.tsx'; import { SelectableRows } from './store/SelectableRows'; const wrapDataTable = ( @@ -32,6 +33,7 @@ export { ROW_GROUP, wrapDataTable, SelectableRows, + LinkAction, }; export type { DataTableSort, diff --git a/semcore/link/src/Link.tsx b/semcore/link/src/Link.tsx index 1c01215b38..cf1dfa7e14 100644 --- a/semcore/link/src/Link.tsx +++ b/semcore/link/src/Link.tsx @@ -152,7 +152,11 @@ class RootLink extends Component ) : null} - {this.isExternalLink() ? ({Children.origin}) : addonTextChildren(Children, Link.Text, Link.Addon)} + { + (this.isExternalLink() && Children.origin) + ? ({Children.origin}) + : addonTextChildren(Children, Link.Text, Link.Addon) + } {AddonRight ? ( diff --git a/stories/components/base-components/ellipsis/tests/examples/in_table_with_link.tsx b/stories/components/base-components/ellipsis/tests/examples/in_table_with_link.tsx index 33128b57aa..90fcfc1fea 100644 --- a/stories/components/base-components/ellipsis/tests/examples/in_table_with_link.tsx +++ b/stories/components/base-components/ellipsis/tests/examples/in_table_with_link.tsx @@ -1,7 +1,5 @@ -import LinkExternalM from '@semcore/icon/LinkExternal/m'; import type { CellRenderProps } from '@semcore/ui/data-table'; -import { DataTable } from '@semcore/ui/data-table'; -import Link from '@semcore/ui/link'; +import { LinkAction, DataTable } from '@semcore/ui/data-table'; import Pagination from '@semcore/ui/pagination'; import React from 'react'; @@ -78,27 +76,18 @@ export default function Demo() { const renderCell = React.useMemo(() => (props: CellRenderProps) => { if (props.columnName === 'url' && Boolean(columnElement)) { - const pageUrl = props.value?.toString?.() ?? ''; + const url = props.value.toString(); + return ( - - - {removeProtocol(pageUrl)} - - - - - + console.log('here we are')} + + ellipsis:cropPosition='middle' + ellipsis:containerElement={columnElement} + ellipsis:recalculateContainerWidth={recalculateContainerWidth} + /> ); } return props.defaultRender();