@guardian/stand 0.0.10 → 0.0.12

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 (46) hide show
  1. package/README.md +14 -21
  2. package/dist/components/button/Button.cjs +8 -2
  3. package/dist/components/button/Button.js +6 -4
  4. package/dist/components/button/styles.cjs +12 -4
  5. package/dist/components/button/styles.js +11 -1
  6. package/dist/components/byline/Byline.cjs +4 -18
  7. package/dist/components/byline/Preview.cjs +1 -8
  8. package/dist/components/byline/plugins.cjs +3 -13
  9. package/dist/components/icon/Icon.cjs +1 -4
  10. package/dist/components/icon/Icon.js +1 -4
  11. package/dist/components/icon-button/IconButton.cjs +45 -0
  12. package/dist/components/icon-button/IconButton.js +26 -0
  13. package/dist/components/icon-button/styles.cjs +9 -0
  14. package/dist/components/icon-button/styles.js +6 -0
  15. package/dist/components/icon-link-button/IconLinkButton.cjs +42 -0
  16. package/dist/components/icon-link-button/IconLinkButton.js +23 -0
  17. package/dist/components/icon-link-button/styles.cjs +9 -0
  18. package/dist/components/icon-link-button/styles.js +6 -0
  19. package/dist/components/link-button/LinkButton.cjs +8 -2
  20. package/dist/components/link-button/LinkButton.js +7 -5
  21. package/dist/components/user-menu/UserMenu.cjs +1 -8
  22. package/dist/fonts/OpenSans.css +64 -68
  23. package/dist/icon-button.cjs +7 -0
  24. package/dist/icon-button.js +1 -0
  25. package/dist/icon-link-button.cjs +7 -0
  26. package/dist/icon-link-button.js +1 -0
  27. package/dist/styleD/build/css/component/button.css +79 -16
  28. package/dist/styleD/build/css/semantic/typography.css +5 -10
  29. package/dist/styleD/build/typescript/component/button.cjs +208 -16
  30. package/dist/styleD/build/typescript/component/button.js +208 -16
  31. package/dist/types/components/button/Button.d.ts +1 -1
  32. package/dist/types/components/button/styles.d.ts +1 -1
  33. package/dist/types/components/button/types.d.ts +5 -0
  34. package/dist/types/components/icon-button/IconButton.d.ts +2 -0
  35. package/dist/types/components/icon-button/styles.d.ts +522 -0
  36. package/dist/types/components/icon-button/types.d.ts +26 -0
  37. package/dist/types/components/icon-link-button/IconLinkButton.d.ts +2 -0
  38. package/dist/types/components/icon-link-button/styles.d.ts +522 -0
  39. package/dist/types/components/icon-link-button/types.d.ts +26 -0
  40. package/dist/types/components/link-button/LinkButton.d.ts +1 -1
  41. package/dist/types/components/link-button/styles.d.ts +193 -1
  42. package/dist/types/components/link-button/types.d.ts +5 -0
  43. package/dist/types/icon-button.d.ts +20 -0
  44. package/dist/types/icon-link-button.d.ts +20 -0
  45. package/dist/types/styleD/build/typescript/component/button.d.ts +192 -0
  46. package/package.json +19 -3
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  _Find what you need on the (news)stand!_
4
4
 
5
- Stand is component library for Guardian editorial tools. It is co-located within flexible-content as Composer is expected to be the main consumer of the UI components within Stand. But any editorial tool should be able to make use of the components as an npm package - `@guardian/stand` - and developers should feel comfortable contributing.
5
+ Stand is component library and design system for internal Guardian tools. Any tool should be able to make use of the components as an npm package - `@guardian/stand` - and developers should feel comfortable contributing.
6
6
 
7
7
  ## Installation
8
8
 
@@ -74,7 +74,7 @@ The Open Sans variable font can also be loaded via Google Fonts, but we recommen
74
74
  3. Click "Change styles" dropdown
75
75
  4. Use "Full axis" for all options (Italic, Weight, Width)
76
76
  5. Copy the relevant `<link>` tag or `@import` code snippet into your project
77
- - You don't need to include the CSS class, as the design system will handle applying the correct font-family via CSS variables or JS/TS tokens.
77
+ - You don't need to include the CSS class, as the design system will handle applying the correct font-family via CSS variables or JS/TS tokens.
78
78
 
79
79
  #### Guardian Fonts
80
80
 
@@ -149,15 +149,12 @@ import '@guardian/stand/semantic/colors.css'; // CSS usage
149
149
 
150
150
  const stringStyle = css`
151
151
  color: ${semanticColors.text.default}; /* JS/TS usage */
152
- background-color: var(
153
- --semantic-colors-bg-default-on-light
154
- ); /* CSS usage */
152
+ background-color: var(--semantic-colors-bg-default-on-light); /* CSS usage */
155
153
  `;
156
154
 
157
155
  const objectStyle = {
158
156
  color: semanticColors.text.default /* JS/TS usage */,
159
- backgroundColor:
160
- 'var(--semantic-colors-bg-default-on-light)' /* CSS usage */,
157
+ backgroundColor: 'var(--semantic-colors-bg-default-on-light)' /* CSS usage */,
161
158
  };
162
159
  ```
163
160
 
@@ -908,9 +905,7 @@ or for scenarios where you have to use relative paths/node_modules directly:
908
905
  /* example setup of button/link button style using md size and neutral secondary variant */
909
906
  .stand-button-neutral-secondary {
910
907
  color: var(--component-button-neutral-secondary-shared-color);
911
- background: var(
912
- --component-button-neutral-secondary-shared-background-color
913
- );
908
+ background: var(--component-button-neutral-secondary-shared-background-color);
914
909
  height: var(--component-button-neutral-secondary-md-height);
915
910
  padding: var(--component-button-neutral-secondary-md-padding-top)
916
911
  var(--component-button-neutral-secondary-md-padding-right)
@@ -923,9 +918,7 @@ or for scenarios where you have to use relative paths/node_modules directly:
923
918
  font-variation-settings: 'wdth'
924
919
  var(--component-button-neutral-secondary-md-typography-font-width);
925
920
  border: var(--component-button-neutral-secondary-shared-border);
926
- border-radius: var(
927
- --component-button-neutral-secondary-shared-border-radius
928
- );
921
+ border-radius: var(--component-button-neutral-secondary-shared-border-radius);
929
922
  }
930
923
  .stand-button-neutral-secondary:hover {
931
924
  background: var(
@@ -1768,9 +1761,9 @@ See the [Contributing to Stand](./CONTRIBUTING.md) documentation for guidelines
1768
1761
  - Run `pnpm test:react-matrix` to run matrix tests (see Compatibility section below)
1769
1762
  - Run `pnpm tsc` to run check TypeScript types
1770
1763
  - Run `pnpm lint` to run the linter
1771
- - Run `pnpm lint:fix` to fix any auto-fixable issues
1764
+ - Run `pnpm lint:fix` to fix any auto-fixable issues
1772
1765
  - Run `pnpm format:check` to check code formatting
1773
- - Run `pnpm format:fix` to fix code formatting issues
1766
+ - Run `pnpm format:fix` to fix code formatting issues
1774
1767
 
1775
1768
  ### Style Dictionary
1776
1769
 
@@ -1807,13 +1800,13 @@ Matrix generation in CI uses the same JSON file in the workflow: `../.github/wor
1807
1800
 
1808
1801
  1. Edit `./scripts/deps-matrix-versions.json` with new versions
1809
1802
  2. Run the matrix test locally:
1810
- ```bash
1811
- ./scripts/test-deps-matrix.sh
1812
- ```
1803
+ ```bash
1804
+ ./scripts/test-deps-matrix.sh
1805
+ ```
1813
1806
  3. (Optional) Narrow the matrix with overrides:
1814
- ```bash
1815
- REACT_VERSIONS="18.0.0" EMOTION_VERSIONS="11.14.0" TS_VERSIONS="5.1" ./scripts/test-deps-matrix.sh
1816
- ```
1807
+ ```bash
1808
+ REACT_VERSIONS="18.0.0" EMOTION_VERSIONS="11.14.0" TS_VERSIONS="5.1" ./scripts/test-deps-matrix.sh
1809
+ ```
1817
1810
  4. Review results (table output and any failures). Fix issues or adjust code
1818
1811
  5. Update `peerDependencies` in `package.json` to reflect the new minimum / tested range
1819
1812
  6. Open a PR, the CI pipeline will comment with the compatibility matrix
@@ -3,6 +3,7 @@
3
3
  var jsxRuntime = require('@emotion/react/jsx-runtime');
4
4
  var reactAriaComponents = require('react-aria-components');
5
5
  var mergeDeep = require('../../util/mergeDeep.cjs');
6
+ var Icon = require('../icon/Icon.cjs');
6
7
  var styles = require('./styles.cjs');
7
8
 
8
9
  function Button({
@@ -10,17 +11,22 @@ function Button({
10
11
  size = "md",
11
12
  theme = {},
12
13
  cssOverrides,
14
+ icon,
13
15
  ...props
14
16
  }) {
15
17
  const mergedTheme = mergeDeep.mergeDeep(styles.defaultButtonTheme, theme);
18
+ const iconSize = size === "xs" ? "sm" : size;
16
19
  return /* @__PURE__ */ jsxRuntime.jsx(
17
20
  reactAriaComponents.Button,
18
21
  {
19
22
  ...props,
20
- css: [styles.buttonStyles(mergedTheme, { variant, size }), cssOverrides],
23
+ css: [styles.buttonStyles(mergedTheme, { variant, size }, !!icon), cssOverrides],
21
24
  children: reactAriaComponents.composeRenderProps(props.children, (children) => (
22
25
  // TODO: isPending (loading) state - see https://react-aria.adobe.com/Button
23
- /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children })
26
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
27
+ icon && /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { size: iconSize, children: icon }),
28
+ children
29
+ ] })
24
30
  ))
25
31
  }
26
32
  );
@@ -1,13 +1,15 @@
1
- import { jsx, Fragment } from '@emotion/react/jsx-runtime';
1
+ import { jsx, jsxs, Fragment } from '@emotion/react/jsx-runtime';
2
2
  import { Button as Button$1, composeRenderProps } from 'react-aria-components';
3
3
  import { mergeDeep } from '../../util/mergeDeep.js';
4
+ import { Icon } from '../icon/Icon.js';
4
5
  import { buttonStyles, defaultButtonTheme } from './styles.js';
5
6
 
6
- function Button({ variant = "emphasised-primary", size = "md", theme = {}, cssOverrides, ...props }) {
7
+ function Button({ variant = "emphasised-primary", size = "md", theme = {}, cssOverrides, icon, ...props }) {
7
8
  const mergedTheme = mergeDeep(defaultButtonTheme, theme);
8
- return jsx(Button$1, { ...props, css: [buttonStyles(mergedTheme, { variant, size }), cssOverrides], children: composeRenderProps(props.children, (children) => (
9
+ const iconSize = size === "xs" ? "sm" : size;
10
+ return jsx(Button$1, { ...props, css: [buttonStyles(mergedTheme, { variant, size }, !!icon), cssOverrides], children: composeRenderProps(props.children, (children) => (
9
11
  // TODO: isPending (loading) state - see https://react-aria.adobe.com/Button
10
- jsx(Fragment, { children })
12
+ jsxs(Fragment, { children: [icon && jsx(Icon, { size: iconSize, children: icon }), children] })
11
13
  )) });
12
14
  }
13
15
 
@@ -5,7 +5,7 @@ var button = require('../../styleD/build/typescript/component/button.cjs');
5
5
  var typography = require('../../styleD/utils/semantic/typography.cjs');
6
6
 
7
7
  const defaultButtonTheme = button.componentButton;
8
- const buttonStyles = (theme, { size, variant }) => {
8
+ const buttonStyles = (theme, { size, variant }, hasIcon = false, isIconButton = false) => {
9
9
  return react.css`
10
10
  /* button/link button reset styles */
11
11
  display: ${theme.shared["display"]};
@@ -24,12 +24,20 @@ const buttonStyles = (theme, { size, variant }) => {
24
24
  ${theme[variant][size].padding.right}
25
25
  ${theme[variant][size].padding.bottom}
26
26
  ${theme[variant][size].padding.left};
27
- ${typography.convertTypographyToEmotionStringStyle(
28
- theme[variant][size].typography
29
- )}
27
+ ${typography.convertTypographyToEmotionStringStyle(theme[variant][size].typography)}
30
28
  border: ${theme[variant].shared.border};
31
29
  border-radius: ${theme[variant].shared.borderRadius};
32
30
 
31
+ ${hasIcon && react.css`
32
+ padding-left: ${theme[variant][size].padding.withIcon.iconLeft.left};
33
+ gap: ${theme[variant][size].icon.gap};
34
+ `}
35
+
36
+ ${isIconButton && react.css`
37
+ width: ${theme[variant][size].iconButton.width};
38
+ padding: 0;
39
+ `}
40
+
33
41
  &[data-hovered] {
34
42
  background: ${theme[variant].shared[":hover"].backgroundColor};
35
43
  border: ${theme[variant].shared[":hover"].border};
@@ -3,7 +3,7 @@ import { componentButton } from '../../styleD/build/typescript/component/button.
3
3
  import { convertTypographyToEmotionStringStyle } from '../../styleD/utils/semantic/typography.js';
4
4
 
5
5
  const defaultButtonTheme = componentButton;
6
- const buttonStyles = (theme, { size, variant }) => {
6
+ const buttonStyles = (theme, { size, variant }, hasIcon = false, isIconButton = false) => {
7
7
  return css`
8
8
  /* button/link button reset styles */
9
9
  display: ${theme.shared["display"]};
@@ -26,6 +26,16 @@ const buttonStyles = (theme, { size, variant }) => {
26
26
  border: ${theme[variant].shared.border};
27
27
  border-radius: ${theme[variant].shared.borderRadius};
28
28
 
29
+ ${hasIcon && css`
30
+ padding-left: ${theme[variant][size].padding.withIcon.iconLeft.left};
31
+ gap: ${theme[variant][size].icon.gap};
32
+ `}
33
+
34
+ ${isIconButton && css`
35
+ width: ${theme[variant][size].iconButton.width};
36
+ padding: 0;
37
+ `}
38
+
29
39
  &[data-hovered] {
30
40
  background: ${theme[variant].shared[":hover"].backgroundColor};
31
41
  border: ${theme[variant].shared[":hover"].border};
@@ -165,9 +165,7 @@ const Byline = ({
165
165
  if (readOnly) {
166
166
  return false;
167
167
  }
168
- if (!dropdownRef.current?.contains(
169
- event.relatedTarget
170
- )) {
168
+ if (!dropdownRef.current?.contains(event.relatedTarget)) {
171
169
  setShowDropdown(false);
172
170
  }
173
171
  return false;
@@ -203,10 +201,7 @@ const Byline = ({
203
201
  void searchContributors(selectedText).then((contributors) => {
204
202
  setTaggedContributors(contributors);
205
203
  }).catch((error) => {
206
- console.error(
207
- "Error fetching tagged contributors:",
208
- error
209
- );
204
+ console.error("Error fetching tagged contributors:", error);
210
205
  setTaggedContributors([]);
211
206
  });
212
207
  } else {
@@ -291,14 +286,7 @@ const Byline = ({
291
286
  allowUntaggedContributors
292
287
  ]);
293
288
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { css: styles.bylineContainerStyles, children: [
294
- /* @__PURE__ */ jsxRuntime.jsx(
295
- "div",
296
- {
297
- css: styles.bylineEditorStyles(theme),
298
- ref: editorRef,
299
- onBlur
300
- }
301
- ),
289
+ /* @__PURE__ */ jsxRuntime.jsx("div", { css: styles.bylineEditorStyles(theme), ref: editorRef, onBlur }),
302
290
  /* @__PURE__ */ jsxRuntime.jsx(
303
291
  "div",
304
292
  {
@@ -351,9 +339,7 @@ const Byline = ({
351
339
  ],
352
340
  onMouseMove: () => {
353
341
  if (currentOptionIndex !== taggedContributors.length) {
354
- setCurrentOptionIndex(
355
- taggedContributors.length
356
- );
342
+ setCurrentOptionIndex(taggedContributors.length);
357
343
  }
358
344
  },
359
345
  onMouseDown: (e) => {
@@ -13,14 +13,7 @@ const Preview = ({ doc }) => {
13
13
  });
14
14
  return /* @__PURE__ */ jsxRuntime.jsx("div", { css: styles.previewStyles, "data-testid": "byline-preview", children: parts.map((node, i) => {
15
15
  if (node.isText) {
16
- return /* @__PURE__ */ jsxRuntime.jsx(
17
- "span",
18
- {
19
- css: styles.previewFreeTextStyles,
20
- children: node.text
21
- },
22
- `${node.text}${i}`
23
- );
16
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { css: styles.previewFreeTextStyles, children: node.text }, `${node.text}${i}`);
24
17
  } else if (node.type.name === "chip") {
25
18
  if (node.attrs.path) {
26
19
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -70,11 +70,7 @@ const clipboardPlugin = (allowUntaggedContributors, contributorLimit) => {
70
70
  {},
71
71
  transformedNodes
72
72
  ).content;
73
- return new prosemirrorModel.Slice(
74
- newFragment,
75
- slice.openStart,
76
- slice.openEnd
77
- );
73
+ return new prosemirrorModel.Slice(newFragment, slice.openStart, slice.openEnd);
78
74
  }
79
75
  return slice;
80
76
  }
@@ -110,10 +106,7 @@ const bylinePlugin = () => {
110
106
  dom.setAttribute("data-tag-id", node.attrs.tagId);
111
107
  dom.setAttribute("data-path", node.attrs.path);
112
108
  if (node.attrs.meta) {
113
- dom.setAttribute(
114
- "data-meta",
115
- JSON.stringify(node.attrs.meta)
116
- );
109
+ dom.setAttribute("data-meta", JSON.stringify(node.attrs.meta));
117
110
  }
118
111
  dom.textContent = node.attrs.label;
119
112
  const deleteHandle = document.createElement("span");
@@ -125,10 +118,7 @@ const bylinePlugin = () => {
125
118
  if (pos === void 0) {
126
119
  return;
127
120
  }
128
- const tr = view.state.tr.deleteRange(
129
- pos,
130
- pos + node.nodeSize
131
- );
121
+ const tr = view.state.tr.deleteRange(pos, pos + node.nodeSize);
132
122
  view.dispatch(tr);
133
123
  });
134
124
  dom.appendChild(deleteHandle);
@@ -33,10 +33,7 @@ function Icon({
33
33
  "span",
34
34
  {
35
35
  className,
36
- css: [
37
- styles.iconStyles(mergedTheme, { size, fill, mode: "svg" }),
38
- cssOverrides
39
- ],
36
+ css: [styles.iconStyles(mergedTheme, { size, fill, mode: "svg" }), cssOverrides],
40
37
  ...alt ? { role: "img", "aria-label": alt } : { "aria-hidden": true },
41
38
  children
42
39
  }
@@ -10,10 +10,7 @@ function Icon({ children, size = "md", fill, alt, symbol, theme = {}, cssOverrid
10
10
  cssOverrides
11
11
  ], ...alt ? { role: "img", "aria-label": alt } : { "aria-hidden": true }, children: symbol ?? children });
12
12
  }
13
- return jsx("span", { className, css: [
14
- iconStyles(mergedTheme, { size, fill, mode: "svg" }),
15
- cssOverrides
16
- ], ...alt ? { role: "img", "aria-label": alt } : { "aria-hidden": true }, children });
13
+ return jsx("span", { className, css: [iconStyles(mergedTheme, { size, fill, mode: "svg" }), cssOverrides], ...alt ? { role: "img", "aria-label": alt } : { "aria-hidden": true }, children });
17
14
  }
18
15
 
19
16
  export { Icon };
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('@emotion/react/jsx-runtime');
4
+ var react = require('react');
5
+ var reactAriaComponents = require('react-aria-components');
6
+ var mergeDeep = require('../../util/mergeDeep.cjs');
7
+ var Icon = require('../icon/Icon.cjs');
8
+ var styles = require('./styles.cjs');
9
+
10
+ function IconButton({
11
+ variant = "emphasised-primary",
12
+ size = "md",
13
+ symbol,
14
+ ariaLabel,
15
+ theme = {},
16
+ cssOverrides,
17
+ ...props
18
+ }) {
19
+ const mergedTheme = mergeDeep.mergeDeep(styles.defaultIconButtonTheme, theme);
20
+ const buttonRef = react.useRef(null);
21
+ react.useEffect(() => {
22
+ if (buttonRef.current) {
23
+ buttonRef.current.title = ariaLabel;
24
+ }
25
+ }, [ariaLabel]);
26
+ const iconSize = size === "xs" ? "sm" : size;
27
+ return /* @__PURE__ */ jsxRuntime.jsx(
28
+ reactAriaComponents.Button,
29
+ {
30
+ ...props,
31
+ ref: buttonRef,
32
+ "aria-label": ariaLabel,
33
+ css: [
34
+ styles.iconButtonStyles(mergedTheme, { variant, size }, false, true),
35
+ cssOverrides
36
+ ],
37
+ children: reactAriaComponents.composeRenderProps(props.children, (children) => (
38
+ // TODO: isPending (loading) state - see https://react-aria.adobe.com/Button
39
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { size: iconSize, symbol, children })
40
+ ))
41
+ }
42
+ );
43
+ }
44
+
45
+ exports.IconButton = IconButton;
@@ -0,0 +1,26 @@
1
+ import { jsx } from '@emotion/react/jsx-runtime';
2
+ import { useRef, useEffect } from 'react';
3
+ import { Button, composeRenderProps } from 'react-aria-components';
4
+ import { mergeDeep } from '../../util/mergeDeep.js';
5
+ import { Icon } from '../icon/Icon.js';
6
+ import { iconButtonStyles, defaultIconButtonTheme } from './styles.js';
7
+
8
+ function IconButton({ variant = "emphasised-primary", size = "md", symbol, ariaLabel, theme = {}, cssOverrides, ...props }) {
9
+ const mergedTheme = mergeDeep(defaultIconButtonTheme, theme);
10
+ const buttonRef = useRef(null);
11
+ useEffect(() => {
12
+ if (buttonRef.current) {
13
+ buttonRef.current.title = ariaLabel;
14
+ }
15
+ }, [ariaLabel]);
16
+ const iconSize = size === "xs" ? "sm" : size;
17
+ return jsx(Button, { ...props, ref: buttonRef, "aria-label": ariaLabel, css: [
18
+ iconButtonStyles(mergedTheme, { variant, size }, false, true),
19
+ cssOverrides
20
+ ], children: composeRenderProps(props.children, (children) => (
21
+ // TODO: isPending (loading) state - see https://react-aria.adobe.com/Button
22
+ jsx(Icon, { size: iconSize, symbol, children })
23
+ )) });
24
+ }
25
+
26
+ export { IconButton };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var styles = require('../button/styles.cjs');
4
+
5
+ const defaultIconButtonTheme = styles.defaultButtonTheme;
6
+ const iconButtonStyles = styles.buttonStyles;
7
+
8
+ exports.defaultIconButtonTheme = defaultIconButtonTheme;
9
+ exports.iconButtonStyles = iconButtonStyles;
@@ -0,0 +1,6 @@
1
+ import { buttonStyles, defaultButtonTheme } from '../button/styles.js';
2
+
3
+ const defaultIconButtonTheme = defaultButtonTheme;
4
+ const iconButtonStyles = buttonStyles;
5
+
6
+ export { defaultIconButtonTheme, iconButtonStyles };
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('@emotion/react/jsx-runtime');
4
+ var react = require('react');
5
+ var reactAriaComponents = require('react-aria-components');
6
+ var mergeDeep = require('../../util/mergeDeep.cjs');
7
+ var Icon = require('../icon/Icon.cjs');
8
+ var styles = require('./styles.cjs');
9
+
10
+ function IconLinkButton({
11
+ variant = "emphasised-primary",
12
+ size = "md",
13
+ symbol,
14
+ ariaLabel,
15
+ theme = {},
16
+ cssOverrides,
17
+ ...props
18
+ }) {
19
+ const mergedTheme = mergeDeep.mergeDeep(styles.defaultIconLinkButtonTheme, theme);
20
+ const linkRef = react.useRef(null);
21
+ react.useEffect(() => {
22
+ if (linkRef.current) {
23
+ linkRef.current.title = ariaLabel;
24
+ }
25
+ }, [ariaLabel]);
26
+ const iconSize = size === "xs" ? "sm" : size;
27
+ return /* @__PURE__ */ jsxRuntime.jsx(
28
+ reactAriaComponents.Link,
29
+ {
30
+ ...props,
31
+ ref: linkRef,
32
+ "aria-label": ariaLabel,
33
+ css: [
34
+ styles.iconLinkButtonStyles(mergedTheme, { variant, size }, false, true),
35
+ cssOverrides
36
+ ],
37
+ children: reactAriaComponents.composeRenderProps(props.children, (children) => /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { size: iconSize, symbol, children }))
38
+ }
39
+ );
40
+ }
41
+
42
+ exports.IconLinkButton = IconLinkButton;
@@ -0,0 +1,23 @@
1
+ import { jsx } from '@emotion/react/jsx-runtime';
2
+ import { useRef, useEffect } from 'react';
3
+ import { Link, composeRenderProps } from 'react-aria-components';
4
+ import { mergeDeep } from '../../util/mergeDeep.js';
5
+ import { Icon } from '../icon/Icon.js';
6
+ import { iconLinkButtonStyles, defaultIconLinkButtonTheme } from './styles.js';
7
+
8
+ function IconLinkButton({ variant = "emphasised-primary", size = "md", symbol, ariaLabel, theme = {}, cssOverrides, ...props }) {
9
+ const mergedTheme = mergeDeep(defaultIconLinkButtonTheme, theme);
10
+ const linkRef = useRef(null);
11
+ useEffect(() => {
12
+ if (linkRef.current) {
13
+ linkRef.current.title = ariaLabel;
14
+ }
15
+ }, [ariaLabel]);
16
+ const iconSize = size === "xs" ? "sm" : size;
17
+ return jsx(Link, { ...props, ref: linkRef, "aria-label": ariaLabel, css: [
18
+ iconLinkButtonStyles(mergedTheme, { variant, size }, false, true),
19
+ cssOverrides
20
+ ], children: composeRenderProps(props.children, (children) => jsx(Icon, { size: iconSize, symbol, children })) });
21
+ }
22
+
23
+ export { IconLinkButton };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var styles = require('../button/styles.cjs');
4
+
5
+ const defaultIconLinkButtonTheme = styles.defaultButtonTheme;
6
+ const iconLinkButtonStyles = styles.buttonStyles;
7
+
8
+ exports.defaultIconLinkButtonTheme = defaultIconLinkButtonTheme;
9
+ exports.iconLinkButtonStyles = iconLinkButtonStyles;
@@ -0,0 +1,6 @@
1
+ import { buttonStyles, defaultButtonTheme } from '../button/styles.js';
2
+
3
+ const defaultIconLinkButtonTheme = defaultButtonTheme;
4
+ const iconLinkButtonStyles = buttonStyles;
5
+
6
+ export { defaultIconLinkButtonTheme, iconLinkButtonStyles };
@@ -3,6 +3,7 @@
3
3
  var jsxRuntime = require('@emotion/react/jsx-runtime');
4
4
  var reactAriaComponents = require('react-aria-components');
5
5
  var mergeDeep = require('../../util/mergeDeep.cjs');
6
+ var Icon = require('../icon/Icon.cjs');
6
7
  var styles = require('./styles.cjs');
7
8
 
8
9
  function LinkButton({
@@ -10,18 +11,23 @@ function LinkButton({
10
11
  size = "md",
11
12
  theme = {},
12
13
  cssOverrides,
14
+ icon,
13
15
  ...props
14
16
  }) {
15
17
  const mergedTheme = mergeDeep.mergeDeep(styles.defaultLinkButtonTheme, theme);
18
+ const iconSize = size === "xs" ? "sm" : size;
16
19
  return /* @__PURE__ */ jsxRuntime.jsx(
17
20
  reactAriaComponents.Link,
18
21
  {
19
22
  ...props,
20
23
  css: [
21
- styles.linkButtonStyles(mergedTheme, { variant, size }),
24
+ styles.linkButtonStyles(mergedTheme, { variant, size }, !!icon),
22
25
  cssOverrides
23
26
  ],
24
- children: props.children
27
+ children: reactAriaComponents.composeRenderProps(props.children, (children) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
28
+ icon && /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { size: iconSize, children: icon }),
29
+ children
30
+ ] }))
25
31
  }
26
32
  );
27
33
  }
@@ -1,14 +1,16 @@
1
- import { jsx } from '@emotion/react/jsx-runtime';
2
- import { Link } from 'react-aria-components';
1
+ import { jsx, jsxs, Fragment } from '@emotion/react/jsx-runtime';
2
+ import { Link, composeRenderProps } from 'react-aria-components';
3
3
  import { mergeDeep } from '../../util/mergeDeep.js';
4
+ import { Icon } from '../icon/Icon.js';
4
5
  import { linkButtonStyles, defaultLinkButtonTheme } from './styles.js';
5
6
 
6
- function LinkButton({ variant = "emphasised-primary", size = "md", theme = {}, cssOverrides, ...props }) {
7
+ function LinkButton({ variant = "emphasised-primary", size = "md", theme = {}, cssOverrides, icon, ...props }) {
7
8
  const mergedTheme = mergeDeep(defaultLinkButtonTheme, theme);
9
+ const iconSize = size === "xs" ? "sm" : size;
8
10
  return jsx(Link, { ...props, css: [
9
- linkButtonStyles(mergedTheme, { variant, size }),
11
+ linkButtonStyles(mergedTheme, { variant, size }, !!icon),
10
12
  cssOverrides
11
- ], children: props.children });
13
+ ], children: composeRenderProps(props.children, (children) => jsxs(Fragment, { children: [icon && jsx(Icon, { size: iconSize, children: icon }), children] })) });
12
14
  }
13
15
 
14
16
  export { LinkButton };
@@ -17,14 +17,7 @@ function UserMenu({
17
17
  headingLevel
18
18
  }) {
19
19
  return /* @__PURE__ */ jsxRuntime.jsxs("aside", { css: styles.userMenuStyles(theme), children: [
20
- /* @__PURE__ */ jsxRuntime.jsx(
21
- TitleText.TitleText,
22
- {
23
- headingLevel,
24
- css: styles.userMenuHeadingStyles(theme),
25
- children: "Accessibility Settings"
26
- }
27
- ),
20
+ /* @__PURE__ */ jsxRuntime.jsx(TitleText.TitleText, { headingLevel, css: styles.userMenuHeadingStyles(theme), children: "Accessibility Settings" }),
28
21
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
29
22
  "Customise your reading & writing experience.",
30
23
  " ",