uikit-react-public 0.11.24 → 0.14.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/dist/components/Badge/Badge.d.ts +6 -0
  2. package/dist/components/Badge/Badge.stories.d.ts +15 -0
  3. package/dist/components/Badge/index.d.ts +2 -0
  4. package/dist/components/Button/Button.d.ts +2 -1
  5. package/dist/components/CookieNotice/CookieNotice.d.ts +16 -0
  6. package/dist/components/CookieNotice/index.d.ts +2 -0
  7. package/dist/components/Dialog/BaseDialog.d.ts +7 -2
  8. package/dist/components/FileInput/FileInput.d.ts +8 -0
  9. package/dist/components/FileInput/FileInput.stories.d.ts +16 -0
  10. package/dist/components/FileInput/__tests__/FileInput.test.d.ts +1 -0
  11. package/dist/components/FileInput/index.d.ts +2 -0
  12. package/dist/components/Header/Header.d.ts +4 -1
  13. package/dist/components/Heading/Heading.d.ts +1 -1
  14. package/dist/components/Link/BaseLink.d.ts +10 -0
  15. package/dist/components/Link/Link.d.ts +5 -10
  16. package/dist/components/Link/Link.stories.d.ts +1 -1
  17. package/dist/components/Link/index.d.ts +1 -1
  18. package/dist/components/Menu/MenuContent.d.ts +1 -1
  19. package/dist/components/Menu/MenuItem.d.ts +2 -0
  20. package/dist/components/Menu/MenuSection.d.ts +1 -1
  21. package/dist/components/Search/Search.d.ts +16 -0
  22. package/dist/components/Search/Search.stories.d.ts +34 -0
  23. package/dist/components/Search/__tests__/Search.test.d.ts +1 -0
  24. package/dist/components/Search/index.d.ts +2 -0
  25. package/dist/components/Select/Select.d.ts +1 -1
  26. package/dist/components/Select/Select.stories.d.ts +3 -7
  27. package/dist/components/Select/Select.types.d.ts +19 -14
  28. package/dist/components/Select/subcomponents/CustomOption.d.ts +1 -1
  29. package/dist/components/Select/subcomponents/CustomSelect.d.ts +1 -2
  30. package/dist/components/Select/subcomponents/Panel.d.ts +1 -1
  31. package/dist/components/Select/subcomponents/VisibleField.d.ts +4 -4
  32. package/dist/components/StandaloneLink/StandaloneLink.d.ts +12 -0
  33. package/dist/components/StandaloneLink/StandaloneLink.stories.d.ts +13 -0
  34. package/dist/components/StandaloneLink/__tests__/StandaloneLink.test.d.ts +1 -0
  35. package/dist/components/StandaloneLink/index.d.ts +2 -0
  36. package/dist/components/Table/Table.d.ts +10 -8
  37. package/dist/components/Table/Table.stories.d.ts +21 -0
  38. package/dist/components/Table/Table.types.d.ts +11 -0
  39. package/dist/components/Table/__tests__/Table.test.d.ts +1 -0
  40. package/dist/components/Table/index.d.ts +2 -1
  41. package/dist/components/Table/subcomponents/Body.d.ts +4 -0
  42. package/dist/components/Table/subcomponents/Cell/Cell.d.ts +12 -0
  43. package/dist/components/Table/subcomponents/Cell/Cell.stories.d.ts +313 -0
  44. package/dist/components/Table/subcomponents/Cell/CellContent.d.ts +10 -0
  45. package/dist/components/Table/subcomponents/Cell/__tests__/Cell.test.d.ts +1 -0
  46. package/dist/components/Table/subcomponents/Head.d.ts +4 -0
  47. package/dist/components/Table/subcomponents/HeadCell/HeadCell.d.ts +13 -0
  48. package/dist/components/Table/subcomponents/HeadCell/HeadCell.stories.d.ts +312 -0
  49. package/dist/components/Table/subcomponents/HeadCell/HeadCellContent.d.ts +10 -0
  50. package/dist/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.d.ts +1 -0
  51. package/dist/components/Table/subcomponents/Row.d.ts +5 -0
  52. package/dist/components/Table/subcomponents/SortIcon.d.ts +7 -0
  53. package/dist/components/Table/subcomponents/index.d.ts +10 -0
  54. package/dist/components/Tabs/Tab.d.ts +1 -1
  55. package/dist/components/Tabs/TabContext.d.ts +1 -0
  56. package/dist/components/Tabs/Tabs.d.ts +3 -1
  57. package/dist/components/Tabs/Tabs.stories.d.ts +3 -0
  58. package/dist/components/Timepicker/Timepicker.d.ts +10 -0
  59. package/dist/components/Timepicker/Timepicker.stories.d.ts +7 -0
  60. package/dist/components/Timepicker/__tests__/Timepicker.test.d.ts +1 -0
  61. package/dist/components/Timepicker/index.d.ts +2 -0
  62. package/dist/components/Timepicker/utils/convertDateToTimeString.d.ts +2 -0
  63. package/dist/components/Timepicker/utils/convertDateToTimeString.test.d.ts +1 -0
  64. package/dist/components/Timepicker/utils/index.d.ts +1 -0
  65. package/dist/components/WeekPicker/WeekPicker.d.ts +3 -0
  66. package/dist/components/WeekPicker/index.d.ts +1 -0
  67. package/dist/components/WeekPicker/subcomponents/CustomDatepicker.d.ts +17 -0
  68. package/dist/components/WeekPicker/subcomponents/DatepickerInput.d.ts +13 -0
  69. package/dist/components/WeekPicker/subcomponents/VisibleField.d.ts +15 -0
  70. package/dist/components/WeekPicker/subcomponents/index.d.ts +3 -0
  71. package/dist/components/index.d.ts +11 -0
  72. package/dist/hooks/index.d.ts +2 -0
  73. package/dist/hooks/useFocusTrap.d.ts +9 -0
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.js +5703 -4448
  76. package/dist/theme/defaultTheme.d.ts +7 -0
  77. package/dist/theme/useTheme.d.ts +14 -0
  78. package/dist/utils/__tests__/capitalise.test.d.ts +1 -0
  79. package/dist/utils/capitalise.d.ts +2 -0
  80. package/lib/components/Alert/Alert.tsx +7 -1
  81. package/lib/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap +4 -0
  82. package/lib/components/Badge/Badge.stories.tsx +19 -0
  83. package/lib/components/Badge/Badge.tsx +48 -0
  84. package/lib/components/Badge/index.ts +2 -0
  85. package/lib/components/Breadcrumbs/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +4 -4
  86. package/lib/components/Button/Button.tsx +5 -2
  87. package/lib/components/Calendar/subcomponents/Grid.tsx +0 -1
  88. package/lib/components/CookieNotice/CookieNotice.tsx +114 -0
  89. package/lib/components/CookieNotice/index.ts +2 -0
  90. package/lib/components/Dialog/BaseDialog.tsx +44 -4
  91. package/lib/components/Field/__tests__/Field.test.tsx +148 -148
  92. package/lib/components/FileInput/FileInput.stories.tsx +70 -0
  93. package/lib/components/FileInput/FileInput.tsx +68 -0
  94. package/lib/components/FileInput/__tests__/FileInput.test.tsx +99 -0
  95. package/lib/components/FileInput/__tests__/__snapshots__/FileInput.test.tsx.snap +91 -0
  96. package/lib/components/FileInput/index.ts +2 -0
  97. package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +25 -25
  98. package/lib/components/Header/Header.tsx +19 -2
  99. package/lib/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +4 -4
  100. package/lib/components/Heading/Documentation.mdx +1 -1
  101. package/lib/components/Heading/Heading.tsx +1 -1
  102. package/lib/components/Heading/__tests__/Heading.test.tsx +7 -19
  103. package/lib/components/Heading/__tests__/__snapshots__/Heading.test.tsx.snap +7 -7
  104. package/lib/components/Label/Label.tsx +0 -2
  105. package/lib/components/Label/__tests__/__snapshots__/Label.test.tsx.snap +7 -7
  106. package/lib/components/Link/BaseLink.tsx +84 -0
  107. package/lib/components/Link/Link.tsx +72 -32
  108. package/lib/components/Link/__tests__/__snapshots__/link.test.tsx.snap +3 -3
  109. package/lib/components/Link/__tests__/link.test.tsx +6 -13
  110. package/lib/components/Link/index.ts +1 -1
  111. package/lib/components/Menu/Menu.context.tsx +3 -1
  112. package/lib/components/Menu/Menu.tsx +2 -2
  113. package/lib/components/Menu/MenuContent.tsx +5 -5
  114. package/lib/components/Menu/MenuItem.tsx +20 -3
  115. package/lib/components/Menu/MenuSection.tsx +4 -3
  116. package/lib/components/Pagination/PaginationControls.tsx +1 -3
  117. package/lib/components/Search/Search.stories.tsx +41 -0
  118. package/lib/components/Search/Search.tsx +167 -0
  119. package/lib/components/Search/__tests__/Search.test.tsx +94 -0
  120. package/lib/components/Search/__tests__/__snapshots__/Search.test.tsx.snap +179 -0
  121. package/lib/components/Search/index.ts +2 -0
  122. package/lib/components/Select/Select.stories.tsx +8 -35
  123. package/lib/components/Select/Select.tsx +2 -2
  124. package/lib/components/Select/Select.types.ts +20 -15
  125. package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +3 -3
  126. package/lib/components/Select/subcomponents/CustomOption.tsx +22 -9
  127. package/lib/components/Select/subcomponents/CustomSelect.tsx +31 -20
  128. package/lib/components/Select/subcomponents/Panel.tsx +4 -5
  129. package/lib/components/Select/subcomponents/VisibleField.tsx +26 -22
  130. package/lib/components/StandaloneLink/StandaloneLink.stories.tsx +32 -0
  131. package/lib/components/StandaloneLink/StandaloneLink.tsx +183 -0
  132. package/lib/components/StandaloneLink/__tests__/StandaloneLink.test.tsx +57 -0
  133. package/lib/components/StandaloneLink/__tests__/__snapshots__/StandaloneLink.test.tsx.snap +19 -0
  134. package/lib/components/StandaloneLink/index.ts +2 -0
  135. package/lib/components/Table/Table.stories.tsx +337 -0
  136. package/lib/components/Table/Table.tsx +42 -67
  137. package/lib/components/Table/Table.types.ts +14 -0
  138. package/lib/components/Table/__tests__/Table.test.tsx +121 -0
  139. package/lib/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +210 -0
  140. package/lib/components/Table/index.ts +8 -1
  141. package/lib/components/Table/subcomponents/Body.tsx +18 -0
  142. package/lib/components/Table/subcomponents/Cell/Cell.stories.tsx +151 -0
  143. package/lib/components/Table/subcomponents/Cell/Cell.tsx +72 -0
  144. package/lib/components/Table/subcomponents/Cell/CellContent.tsx +91 -0
  145. package/lib/components/Table/subcomponents/Cell/__tests__/Cell.test.tsx +115 -0
  146. package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +107 -0
  147. package/lib/components/Table/subcomponents/Head.tsx +34 -0
  148. package/lib/components/Table/subcomponents/HeadCell/HeadCell.stories.tsx +85 -0
  149. package/lib/components/Table/subcomponents/HeadCell/HeadCell.tsx +99 -0
  150. package/lib/components/Table/subcomponents/HeadCell/HeadCellContent.tsx +61 -0
  151. package/lib/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.tsx +137 -0
  152. package/lib/components/Table/subcomponents/HeadCell/__tests__/__snapshots__/HeadCell.test.tsx.snap +110 -0
  153. package/lib/components/Table/subcomponents/Row.tsx +49 -0
  154. package/lib/components/Table/subcomponents/SortIcon.tsx +63 -0
  155. package/lib/components/Table/subcomponents/index.ts +14 -0
  156. package/lib/components/Tabs/Tab.tsx +3 -3
  157. package/lib/components/Tabs/TabContext.tsx +1 -0
  158. package/lib/components/Tabs/Tabs.stories.tsx +9 -3
  159. package/lib/components/Tabs/Tabs.tsx +10 -32
  160. package/lib/components/Tabs/__tests__/Tabs.test.tsx +10 -4
  161. package/lib/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +32 -32
  162. package/lib/components/Timepicker/Timepicker.stories.tsx +43 -0
  163. package/lib/components/Timepicker/Timepicker.tsx +96 -0
  164. package/lib/components/Timepicker/__tests__/Timepicker.test.tsx +55 -0
  165. package/lib/components/Timepicker/__tests__/__snapshots__/Timepicker.test.tsx.snap +19 -0
  166. package/lib/components/Timepicker/index.tsx +2 -0
  167. package/lib/components/Timepicker/utils/convertDateToTimeString.test.ts +54 -0
  168. package/lib/components/Timepicker/utils/convertDateToTimeString.ts +10 -0
  169. package/lib/components/Timepicker/utils/index.ts +1 -0
  170. package/lib/components/WeekPicker/WeekPicker.tsx +26 -0
  171. package/lib/components/WeekPicker/index.ts +1 -0
  172. package/lib/components/WeekPicker/subcomponents/CustomDatepicker.tsx +298 -0
  173. package/lib/components/WeekPicker/subcomponents/DatepickerInput.tsx +111 -0
  174. package/lib/components/WeekPicker/subcomponents/VisibleField.tsx +126 -0
  175. package/lib/components/WeekPicker/subcomponents/index.ts +3 -0
  176. package/lib/components/index.ts +17 -0
  177. package/lib/hooks/index.ts +2 -0
  178. package/lib/hooks/useFocusTrap.ts +123 -0
  179. package/lib/index.ts +1 -0
  180. package/lib/theme/defaultTheme.ts +7 -0
  181. package/lib/utils/__tests__/capitalise.test.ts +40 -0
  182. package/lib/utils/capitalise.ts +4 -0
  183. package/package.json +1 -1
  184. package/lib/components/Field/__tests__/__snapshots__/Field.test.tsx.snap +0 -300
@@ -5,7 +5,7 @@ const NAME = 'ucl-uikit-select__panel';
5
5
 
6
6
  type PanelProps = React.ComponentPropsWithoutRef<'div'>;
7
7
 
8
- const Panel = (props: PanelProps) => {
8
+ const Panel = ({ className, ...props }: PanelProps) => {
9
9
  const [theme] = useTheme();
10
10
 
11
11
  const handleClick = (event: React.MouseEvent) => {
@@ -14,15 +14,14 @@ const Panel = (props: PanelProps) => {
14
14
  };
15
15
 
16
16
  const baseStyle = css`
17
- display: flex;
18
- flex-direction: column;
19
17
  position: absolute;
20
18
  top: 46px;
21
19
  left: -1px; // -1px to align with the border of the field
22
20
  z-index: 10; // Required: panel must be 'above' subsquent DOM elements
23
21
  min-width: 100%;
24
22
  width: fit-content;
25
- max-height: 300px;
23
+ max-width: calc(100vw - 64px);
24
+ max-height: 400px;
26
25
  overflow-y: auto;
27
26
  overflow-x: hidden;
28
27
  box-sizing: content-box;
@@ -31,7 +30,7 @@ const Panel = (props: PanelProps) => {
31
30
  background-color: ${theme.color.neutral.white};
32
31
  `;
33
32
 
34
- const style = cx(NAME, baseStyle);
33
+ const style = cx(NAME, baseStyle, className);
35
34
 
36
35
  return (
37
36
  <div
@@ -5,19 +5,19 @@ import { OptionData } from '../Select.types';
5
5
 
6
6
  const NAME = 'ucl-uikit-select__visible-field';
7
7
 
8
- interface VisibleFieldProps {
8
+ interface VisibleFieldProps<T> {
9
9
  isOpen?: boolean;
10
10
  disabled?: boolean;
11
- selectedOption: OptionData | null | undefined;
11
+ selectedOption: OptionData<T> | null | undefined;
12
12
  placeholder?: string;
13
13
  }
14
14
 
15
- const Field = ({
15
+ const VisibleField = <T extends string | number>({
16
16
  selectedOption,
17
17
  isOpen,
18
18
  placeholder,
19
19
  disabled,
20
- }: VisibleFieldProps) => {
20
+ }: VisibleFieldProps<T>) => {
21
21
  const [theme] = useTheme();
22
22
 
23
23
  const baseStyle = css`
@@ -29,22 +29,33 @@ const Field = ({
29
29
  line-height: ${theme.font.lineHeight.h150};
30
30
  `;
31
31
 
32
+ const style = cx(NAME, baseStyle);
33
+
32
34
  const innerStyle = css`
33
- display: inline-flex;
34
- gap: 8px;
35
- white-space: nowrap;
36
35
  overflow: hidden;
36
+ white-space: nowrap;
37
+ text-overflow: ellipsis;
37
38
  `;
38
39
 
39
- const iconStyle = css`
40
- min-width: 24px;
40
+ const chevronIconBaseStyle = css`
41
+ flex-shrink: 0;
41
42
  margin-left: auto;
42
43
  color: ${theme.color.interaction.blue70};
43
- ${disabled && `color: ${theme.color.neutral.grey20};`}
44
- ${isOpen && `transform: rotate(180deg);`}
45
44
  `;
46
45
 
47
- const style = cx(NAME, baseStyle);
46
+ const chevronIconOpenStyle = css`
47
+ transform: rotate(180deg);
48
+ `;
49
+
50
+ const chevronIconDisabledStyle = css`
51
+ color: ${theme.color.neutral.grey20};
52
+ `;
53
+
54
+ const chevronIconStyle = cx(
55
+ chevronIconBaseStyle,
56
+ isOpen && chevronIconOpenStyle,
57
+ disabled && chevronIconDisabledStyle
58
+ );
48
59
 
49
60
  return (
50
61
  <div
@@ -52,18 +63,11 @@ const Field = ({
52
63
  data-testid={NAME}
53
64
  >
54
65
  <span className={innerStyle}>
55
- {selectedOption ? (
56
- <>
57
- {selectedOption.icon ?? null}
58
- {selectedOption.label}
59
- </>
60
- ) : (
61
- placeholder || ''
62
- )}
66
+ {selectedOption ? selectedOption.label : placeholder || ''}
63
67
  </span>
64
- <Icon.ChevronDown className={iconStyle} />
68
+ <Icon.ChevronDown className={chevronIconStyle} />
65
69
  </div>
66
70
  );
67
71
  };
68
72
 
69
- export default Field;
73
+ export default VisibleField;
@@ -0,0 +1,32 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import Link from './StandaloneLink';
4
+
5
+ const meta = {
6
+ title: 'Components/Work in progress/StandaloneLink',
7
+ component: Link,
8
+ args: {
9
+ children: 'Default link text',
10
+ href: 'https://ucl.ac.uk',
11
+ },
12
+ } satisfies Meta<typeof Link>;
13
+
14
+ export default meta;
15
+
16
+ type Story = StoryObj<typeof meta>;
17
+
18
+ export const Default: Story = {
19
+ render: (args) => <Link {...args}>{args.children}</Link>,
20
+ };
21
+
22
+ export const NewTab: Story = {
23
+ name: 'Opens in a new tab',
24
+ render: (args) => (
25
+ <Link
26
+ {...args}
27
+ target='_blank'
28
+ >
29
+ {args.children}
30
+ </Link>
31
+ ),
32
+ };
@@ -0,0 +1,183 @@
1
+ import { cloneElement, forwardRef, ReactElement } from 'react';
2
+ import { css, cx } from '@emotion/css';
3
+ import useTheme from '../../theme/useTheme';
4
+ import { IconProps } from '../Icon';
5
+ import BaseLink, { BaseLinkProps } from '../Link/BaseLink';
6
+ import marginsStyle, { MarginProps } from '../common/marginsStyle';
7
+
8
+ export interface StandaloneLinkBaseProps extends BaseLinkProps {
9
+ variant?: 'primary' | 'secondary' | 'tertiary';
10
+ icon?: ReactElement<IconProps>;
11
+ iconPosition?: 'left' | 'right';
12
+ }
13
+
14
+ export type StandaloneLinkProps = StandaloneLinkBaseProps & MarginProps;
15
+
16
+ const NAME = 'ucl-uikit-standalone-link';
17
+
18
+ const StandaloneLink = forwardRef<HTMLAnchorElement, StandaloneLinkProps>(
19
+ (
20
+ {
21
+ variant = 'primary',
22
+ icon,
23
+ iconPosition = 'left',
24
+ noVisited = false,
25
+ disabled = false,
26
+ testId = NAME,
27
+ className,
28
+ children,
29
+ ...props
30
+ },
31
+ ref
32
+ ) => {
33
+ const iconSize: number = {
34
+ primary: 24,
35
+ secondary: 16,
36
+ tertiary: 16,
37
+ }[variant];
38
+
39
+ const [theme] = useTheme();
40
+
41
+ const baseStyle = css`
42
+ display: inline-flex;
43
+ align-items: center;
44
+ gap: 8px;
45
+ text-decoration: none;
46
+ `;
47
+
48
+ const primaryStyle = css`
49
+ color: ${theme.color.link.default};
50
+ font-weight: 700;
51
+ `;
52
+
53
+ const secondaryStyle = css`
54
+ color: ${theme.color.link.default};
55
+ `;
56
+
57
+ const tertiaryStyle = css`
58
+ color: ${theme.color.text.primary};
59
+ `;
60
+
61
+ const visitedStyle = css`
62
+ &:visited {
63
+ color: ${theme.color.link.visited};
64
+ }
65
+ `;
66
+
67
+ const primaryNoVisitedStyle = css`
68
+ &:visited {
69
+ color: ${theme.color.link.default};
70
+ }
71
+ `;
72
+
73
+ const secondaryNoVisitedStyle = css`
74
+ &:visited {
75
+ color: ${theme.color.link.default};
76
+ }
77
+ `;
78
+
79
+ const tertiaryNoVisitedStyle = css`
80
+ &:visited {
81
+ color: ${theme.color.text.primary};
82
+ }
83
+ `;
84
+
85
+ const primaryHoverAndActiveStyle = css`
86
+ &:hover {
87
+ color: ${theme.color.link.hover};
88
+ text-decoration: underline;
89
+ text-decoration-skip-ink: none;
90
+ text-decoration-thickness: 10%;
91
+ text-underline-offset: 25%;
92
+ text-underline-position: from-font;
93
+ }
94
+ &:active {
95
+ color: ${theme.color.link.hover};
96
+ }
97
+ `;
98
+
99
+ const secondaryHoverAndActiveStyle = css`
100
+ &:hover {
101
+ color: ${theme.color.link.hover};
102
+ text-decoration: underline;
103
+ text-decoration-skip-ink: none;
104
+ text-decoration-thickness: 10%;
105
+ text-underline-offset: 25%;
106
+ text-underline-position: from-font;
107
+ }
108
+ &:active {
109
+ color: ${theme.color.link.hover};
110
+ }
111
+ `;
112
+
113
+ const tertiaryHoverAndActiveStyle = css`
114
+ &:hover {
115
+ text-decoration: underline;
116
+ text-decoration-skip-ink: none;
117
+ text-decoration-thickness: 10%;
118
+ text-underline-offset: 25%;
119
+ text-underline-position: from-font;
120
+ }
121
+ &:hover {
122
+ color: ${theme.color.text.primary};
123
+ }
124
+ `;
125
+
126
+ let variantStyle = undefined;
127
+ if (variant === 'primary') {
128
+ variantStyle = cx(
129
+ primaryStyle,
130
+ noVisited && !disabled && primaryNoVisitedStyle,
131
+ !disabled && primaryHoverAndActiveStyle,
132
+ !noVisited && !disabled && visitedStyle
133
+ );
134
+ } else if (variant === 'secondary') {
135
+ variantStyle = cx(
136
+ secondaryStyle,
137
+ noVisited && !disabled && secondaryNoVisitedStyle,
138
+ !disabled && secondaryHoverAndActiveStyle,
139
+ !noVisited && !disabled && visitedStyle
140
+ );
141
+ } else if (variant === 'tertiary') {
142
+ variantStyle = cx(
143
+ tertiaryStyle,
144
+ !disabled && tertiaryNoVisitedStyle,
145
+ !disabled && tertiaryHoverAndActiveStyle
146
+ );
147
+ }
148
+
149
+ const disabledStyle = css`
150
+ cursor: not-allowed;
151
+ color: ${theme.color.link.disabled};
152
+ `;
153
+
154
+ const style = cx(
155
+ NAME,
156
+ baseStyle,
157
+ marginsStyle(props, theme),
158
+ variantStyle,
159
+ disabled && disabledStyle,
160
+ className
161
+ );
162
+
163
+ return (
164
+ <BaseLink
165
+ ref={ref}
166
+ className={style}
167
+ testId={testId}
168
+ disabled={disabled}
169
+ {...props}
170
+ >
171
+ {icon &&
172
+ iconPosition === 'left' &&
173
+ cloneElement(icon, { size: iconSize })}
174
+ {children}
175
+ {icon &&
176
+ iconPosition === 'right' &&
177
+ cloneElement(icon, { size: iconSize })}
178
+ </BaseLink>
179
+ );
180
+ }
181
+ );
182
+
183
+ export default StandaloneLink;
@@ -0,0 +1,57 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import StandaloneLink from '../StandaloneLink';
4
+ import { ThemeContextProvider } from '../../../theme/useTheme';
5
+
6
+ describe('Link', () => {
7
+ // Snapshot tests
8
+
9
+ test('snapshot: no props', () => {
10
+ const renderResult = render(
11
+ <ThemeContextProvider>
12
+ <StandaloneLink>test</StandaloneLink>
13
+ </ThemeContextProvider>
14
+ );
15
+ expect(renderResult.container.firstChild).toMatchSnapshot();
16
+ });
17
+
18
+ test('snapshot: testId prop', () => {
19
+ const renderResult = render(
20
+ <ThemeContextProvider>
21
+ <StandaloneLink testId='test123'> testidlink </StandaloneLink>
22
+ </ThemeContextProvider>
23
+ );
24
+ expect(renderResult.container.firstChild).toMatchSnapshot();
25
+ });
26
+
27
+ test('test ID: default', () => {
28
+ render(
29
+ <ThemeContextProvider>
30
+ <StandaloneLink> testidlink </StandaloneLink>
31
+ </ThemeContextProvider>
32
+ );
33
+ const link = screen.getByTestId('ucl-uikit-standalone-link');
34
+ expect(link).toBeDefined();
35
+ });
36
+
37
+ test('test ID: custom', () => {
38
+ render(
39
+ <ThemeContextProvider>
40
+ <StandaloneLink testId='custom-test-id'> testidlink </StandaloneLink>
41
+ </ThemeContextProvider>
42
+ );
43
+ const link = screen.getByTestId('custom-test-id');
44
+ expect(link).toBeDefined();
45
+ });
46
+
47
+ test('href value', async () => {
48
+ render(
49
+ <ThemeContextProvider>
50
+ <StandaloneLink href='/testlink'>linktext</StandaloneLink>
51
+ </ThemeContextProvider>
52
+ );
53
+ const link = screen.getByRole('link') as HTMLAnchorElement;
54
+ expect(link.textContent).toBe('linktext');
55
+ expect(link.href).toBe('http://localhost:3000/testlink');
56
+ });
57
+ });
@@ -0,0 +1,19 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Link > snapshot: no props 1`] = `
4
+ <a
5
+ class="ucl-uikit-base-link ucl-uikit-standalone-link css-1fdgbfz"
6
+ data-testid="ucl-uikit-standalone-link"
7
+ >
8
+ test
9
+ </a>
10
+ `;
11
+
12
+ exports[`Link > snapshot: testId prop 1`] = `
13
+ <a
14
+ class="ucl-uikit-base-link ucl-uikit-standalone-link css-1fdgbfz"
15
+ data-testid="test123"
16
+ >
17
+ testidlink
18
+ </a>
19
+ `;
@@ -0,0 +1,2 @@
1
+ export { default } from './StandaloneLink';
2
+ export type { StandaloneLinkProps } from './StandaloneLink';