@guardian/stand 0.0.4 → 0.0.6
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.
- package/README.md +394 -7
- package/dist/{byline → components/byline}/Byline.cjs +5 -5
- package/dist/{byline → components/byline}/Byline.js +5 -5
- package/dist/components/byline/styles.cjs +266 -0
- package/dist/components/byline/styles.js +256 -0
- package/dist/components/tag-picker/TagAutocomplete.cjs +107 -0
- package/dist/components/tag-picker/TagAutocomplete.js +26 -0
- package/dist/components/tag-picker/TagTable.cjs +203 -0
- package/dist/components/tag-picker/TagTable.js +91 -0
- package/dist/components/tag-picker/styles.cjs +198 -0
- package/dist/components/tag-picker/styles.js +185 -0
- package/dist/components/util.cjs +19 -0
- package/dist/components/util.js +17 -0
- package/dist/index.cjs +15 -1
- package/dist/index.js +8 -1
- package/dist/styleD/build/css/css/base/colors.css +122 -0
- package/dist/styleD/build/css/css/base/typography.css +43 -0
- package/dist/styleD/build/css/css/component/byline.css +36 -0
- package/dist/styleD/build/css/css/component/tagAutocomplete.css +23 -0
- package/dist/styleD/build/css/css/component/tagTable.css +39 -0
- package/dist/styleD/build/css/css/semantic/colors.css +27 -0
- package/dist/styleD/build/css/css/semantic/typography.css +138 -0
- package/dist/styleD/build/typescript/base/colors.cjs +144 -0
- package/dist/styleD/build/typescript/base/colors.js +142 -0
- package/dist/styleD/build/typescript/base/typography.cjs +65 -0
- package/dist/styleD/build/typescript/base/typography.js +63 -0
- package/dist/styleD/build/typescript/component/byline.cjs +42 -0
- package/dist/styleD/build/typescript/component/byline.js +40 -0
- package/dist/styleD/build/typescript/component/tagAutocomplete.cjs +29 -0
- package/dist/styleD/build/typescript/component/tagAutocomplete.js +27 -0
- package/dist/styleD/build/typescript/component/tagTable.cjs +53 -0
- package/dist/styleD/build/typescript/component/tagTable.js +51 -0
- package/dist/styleD/build/typescript/semantic/colors.cjs +37 -0
- package/dist/styleD/build/typescript/semantic/colors.js +35 -0
- package/dist/styleD/build/typescript/semantic/typography.cjs +462 -0
- package/dist/styleD/build/typescript/semantic/typography.js +460 -0
- package/dist/styleD/utils/semantic/typography.cjs +17 -0
- package/dist/styleD/utils/semantic/typography.js +15 -0
- package/dist/types/components/byline/Byline.d.ts +83 -0
- package/dist/types/components/byline/styles.d.ts +13 -0
- package/dist/types/components/byline/theme.d.ts +3 -0
- package/dist/types/components/tag-picker/TagAutocomplete.d.ts +117 -0
- package/dist/types/components/tag-picker/TagTable.d.ts +126 -0
- package/dist/types/components/tag-picker/example-tags.d.ts +2 -0
- package/dist/types/components/tag-picker/styles.d.ts +16 -0
- package/dist/types/components/tag-picker/types.d.ts +65 -0
- package/dist/types/{byline → components}/util.d.ts +1 -0
- package/dist/types/index.d.ts +26 -2
- package/dist/types/styleD/build/typescript/base/colors.d.ts +144 -0
- package/dist/types/styleD/build/typescript/base/typography.d.ts +65 -0
- package/dist/types/styleD/build/typescript/component/byline.d.ts +42 -0
- package/dist/types/styleD/build/typescript/component/tagAutocomplete.d.ts +29 -0
- package/dist/types/styleD/build/typescript/component/tagTable.d.ts +53 -0
- package/dist/types/styleD/build/typescript/semantic/colors.d.ts +37 -0
- package/dist/types/styleD/build/typescript/semantic/typography.d.ts +462 -0
- package/dist/types/styleD/stories/base/Typography.d.ts +1 -0
- package/dist/types/styleD/stories/base/storybookColorPalette.d.ts +19 -0
- package/dist/types/styleD/stories/semantic/TypographyPresets.d.ts +1 -0
- package/dist/types/styleD/utils/semantic/typography.d.ts +15 -0
- package/dist/types/styleD/utils/semantic/typography.test.d.ts +1 -0
- package/package.json +67 -22
- package/dist/byline/styles.cjs +0 -244
- package/dist/byline/styles.js +0 -234
- package/dist/types/byline/Byline.d.ts +0 -17
- package/dist/types/byline/styles.d.ts +0 -11
- package/dist/types/byline/theme.d.ts +0 -44
- /package/dist/{byline → components/byline}/Preview.cjs +0 -0
- /package/dist/{byline → components/byline}/Preview.js +0 -0
- /package/dist/{byline → components/byline}/lib.cjs +0 -0
- /package/dist/{byline → components/byline}/lib.js +0 -0
- /package/dist/{byline → components/byline}/placeholder.cjs +0 -0
- /package/dist/{byline → components/byline}/placeholder.js +0 -0
- /package/dist/{byline → components/byline}/plugins.cjs +0 -0
- /package/dist/{byline → components/byline}/plugins.js +0 -0
- /package/dist/{byline → components/byline}/schema.cjs +0 -0
- /package/dist/{byline → components/byline}/schema.js +0 -0
- /package/dist/types/{byline → components/byline}/Preview.d.ts +0 -0
- /package/dist/types/{byline → components/byline}/contributors-fixture.d.ts +0 -0
- /package/dist/types/{byline → components/byline}/lib.d.ts +0 -0
- /package/dist/types/{byline → components/byline}/lib.test.d.ts +0 -0
- /package/dist/types/{byline → components/byline}/placeholder.d.ts +0 -0
- /package/dist/types/{byline → components/byline}/plugins.d.ts +0 -0
- /package/dist/types/{byline → components/byline}/schema.d.ts +0 -0
package/README.md
CHANGED
|
@@ -4,21 +4,408 @@ _Find what you need on the (news)stand!_
|
|
|
4
4
|
|
|
5
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.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
$ pnpm add @guardian/stand # or yarn or npm
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
You'll also need to have TypeScript, React, and Emotion installed in your project.
|
|
14
|
+
|
|
15
|
+
The compatible versions are listed in the `peerDependencies` section of `package.json`.
|
|
16
|
+
|
|
17
|
+
Some components have additional dependencies that you will need to install too. See the [Components](#components) section for more details for which components have which peer dependencies.
|
|
18
|
+
|
|
19
|
+
## Foundations
|
|
20
|
+
|
|
21
|
+
The Editorial Design System foundations are available via Stand. These are split into two categories: Semantic and Base / Primitives.
|
|
22
|
+
|
|
23
|
+
In most cases consumers should use the Semantic tokens, which are more meaningful abstractions of the Base / Primitives tokens, i.e applied to specific use cases.
|
|
24
|
+
|
|
25
|
+
The base / primitives tokens are available for low-level use cases, or very specific cases, but these should be avoided where possible in favour of the semantic tokens.
|
|
26
|
+
|
|
27
|
+
Stand provides the foundations via CSS variables, as well as JS/TS exports for use in code, which could also be used in CSS-in-JS solutions.
|
|
28
|
+
|
|
29
|
+
Base / Primitive tokens should not be overridden if they are used directly, as this could have unintended consequences. Instead override the Semantic tokens which are designed to be overridden.
|
|
30
|
+
|
|
31
|
+
### Fonts
|
|
32
|
+
|
|
33
|
+
Most applications should only need to load the `Open Sans` and `Guardian Headline` fonts, as these are the primary fonts used across the Guardian's Editorial Tool design system.
|
|
34
|
+
|
|
35
|
+
You only need to load Guardian Text Egyptian if you're planning to use it in your project, in most cases you only need this when working on Guardian editorial content on an editorial tool, i.e. when using `article-body-*` semantic tokens.
|
|
36
|
+
|
|
37
|
+
#### Open Sans
|
|
38
|
+
|
|
39
|
+
We're currently looking at how to best self host this font under a Guardian specific domain, before we release `@guardian/stand` design system for wider usage.
|
|
40
|
+
|
|
41
|
+
For now, the Open Sans variable font can be loaded via Google Fonts:
|
|
42
|
+
|
|
43
|
+
1. Visit [Google Fonts - Open Sans](https://fonts.google.com/specimen/Open+Sans)
|
|
44
|
+
2. Click "Get Font" -> "Get embed code"
|
|
45
|
+
3. Click "Change styles" dropdown
|
|
46
|
+
4. Use "Full axis" for all options (Italic, Weight, Width)
|
|
47
|
+
5. Copy the relevant `<link>` tag or `@import` code snippet into your project
|
|
48
|
+
- 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.
|
|
49
|
+
|
|
50
|
+
### Guardian Fonts
|
|
51
|
+
|
|
52
|
+
Make sure to visit [guardian/fonts](https://github.com/guardian/fonts) repo for the latest information on how to self-host these fonts.
|
|
53
|
+
|
|
54
|
+
In general, we always want to use the `full-not-hinted` versions of the fonts where possible.
|
|
55
|
+
|
|
56
|
+
#### Guardian Headline
|
|
57
|
+
|
|
58
|
+
We only use the bold weight (700) of Guardian Headline in the design system.
|
|
59
|
+
|
|
60
|
+
```css
|
|
61
|
+
@font-face {
|
|
62
|
+
font-family: 'GH Guardian Headline';
|
|
63
|
+
src: url('https://assets.guim.co.uk/static/frontend/fonts/guardian-headline/full-not-hinted/GHGuardianHeadline-Bold.woff2')
|
|
64
|
+
format('woff2');
|
|
65
|
+
font-weight: 700;
|
|
66
|
+
font-style: normal;
|
|
67
|
+
font-display: swap;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Guardian Text Egyptian
|
|
72
|
+
|
|
73
|
+
We want the regular/normal weight (400), the bold weight (700), and the italic version of each weight for Guardian Text Egyptian in the design system.
|
|
74
|
+
|
|
75
|
+
```css
|
|
76
|
+
@font-face {
|
|
77
|
+
font-family: 'GuardianTextEgyptian';
|
|
78
|
+
src: url('https://assets.guim.co.uk/static/frontend/fonts/guardian-textegyptian/full-not-hinted/GuardianTextEgyptian-Regular.woff2')
|
|
79
|
+
format('woff2');
|
|
80
|
+
font-weight: 400;
|
|
81
|
+
font-style: normal;
|
|
82
|
+
font-display: swap;
|
|
83
|
+
}
|
|
84
|
+
@font-face {
|
|
85
|
+
font-family: 'GuardianTextEgyptian';
|
|
86
|
+
src: url('https://assets.guim.co.uk/static/frontend/fonts/guardian-textegyptian/full-not-hinted/GuardianTextEgyptian-RegularItalic.woff2')
|
|
87
|
+
format('woff2');
|
|
88
|
+
font-weight: 400;
|
|
89
|
+
font-style: italic;
|
|
90
|
+
font-display: swap;
|
|
91
|
+
}
|
|
92
|
+
@font-face {
|
|
93
|
+
font-family: 'GuardianTextEgyptian';
|
|
94
|
+
src: url('https://assets.guim.co.uk/static/frontend/fonts/guardian-textegyptian/full-not-hinted/GuardianTextEgyptian-Bold.woff2')
|
|
95
|
+
format('woff2');
|
|
96
|
+
font-weight: 700;
|
|
97
|
+
font-style: normal;
|
|
98
|
+
font-display: swap;
|
|
99
|
+
}
|
|
100
|
+
@font-face {
|
|
101
|
+
font-family: 'GuardianTextEgyptian';
|
|
102
|
+
src: url('https://assets.guim.co.uk/static/frontend/fonts/guardian-textegyptian/full-not-hinted/GuardianTextEgyptian-BoldItalic.woff2')
|
|
103
|
+
format('woff2');
|
|
104
|
+
font-weight: 700;
|
|
105
|
+
font-style: italic;
|
|
106
|
+
font-display: swap;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Semantic
|
|
111
|
+
|
|
112
|
+
#### Colors
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { css } from '@emotion/react';
|
|
116
|
+
import { semanticColors } from '@guardian/stand'; // JS/TS usage
|
|
117
|
+
import '@guardian/stand/semantic/colors.css'; // CSS usage
|
|
118
|
+
|
|
119
|
+
const style = css`
|
|
120
|
+
color: ${semanticColors.text.primary}; /* JS/TS usage */
|
|
121
|
+
background-color: var(
|
|
122
|
+
--semantic-colors-bg-default-on-light
|
|
123
|
+
); /* CSS usage */
|
|
124
|
+
`;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
For a list of available semantic color styles see the [Storybook Semantic Colors](https://68c12e3ed577cb56abfd31bf-ktzjjbdtby.chromatic.com/?path=/docs/stand-editorial-design-system-semantic-color-palette--docs) section.
|
|
128
|
+
|
|
129
|
+
For a full list of CSS Semantic Color tokens see [`semantic/colors.css`](./src/styleD/build/css/semantic/colors.css).
|
|
130
|
+
|
|
131
|
+
#### Typography
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import { css } from '@emotion/react';
|
|
135
|
+
import {
|
|
136
|
+
semanticTypography,
|
|
137
|
+
convertTypographyToEmotion, // helper function to convert from typography token object to emotion CSS
|
|
138
|
+
} from '@guardian/stand'; // JS/TS usage
|
|
139
|
+
import '@guardian/stand/semantic/typography.css'; // CSS usage
|
|
140
|
+
|
|
141
|
+
const styleJS = css`
|
|
142
|
+
/* JS/TS usage */
|
|
143
|
+
${convertTypographyToEmotion(semanticTypography['body-compact-md'])}
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
const styleCSS = css`
|
|
147
|
+
/* CSS usage */
|
|
148
|
+
font: var(--semantic-typography-body-compact-sm-font);
|
|
149
|
+
letter-spacing: var(--semantic-typography-body-compact-sm-letter-spacing);
|
|
150
|
+
font-variation-settings: 'wdth'
|
|
151
|
+
var(--semantic-typography-body-compact-sm-font-width);
|
|
152
|
+
`;
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
For a list of available typography styles see the [Storybook Semantic Typography](https://68c12e3ed577cb56abfd31bf-ktzjjbdtby.chromatic.com/?path=/docs/stand-editorial-design-system-semantic-typography--docs) section.
|
|
156
|
+
|
|
157
|
+
For a full list of CSS Semantic Typography tokens see [`semantic/typography.css`](./src/styleD/build/css/semantic/typography.css).
|
|
158
|
+
|
|
159
|
+
### Base / Primitives
|
|
160
|
+
|
|
161
|
+
#### Colors
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { css } from '@emotion/react';
|
|
165
|
+
import { baseColors } from '@guardian/stand'; // JS/TS usage
|
|
166
|
+
import '@guardian/stand/base/colors.css'; // CSS usage
|
|
167
|
+
|
|
168
|
+
const style = css`
|
|
169
|
+
color: ${baseColors.neutral['900']}; /* JS/TS usage */
|
|
170
|
+
background-color: var(--base-colors-blue-500); /* CSS usage */
|
|
171
|
+
`;
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
For a list of the available base/primitives color styles see the [Storybook Base Colors](https://68c12e3ed577cb56abfd31bf-ktzjjbdtby.chromatic.com/?path=/docs/stand-editorial-design-system-base-color-palette--docs) section.
|
|
175
|
+
|
|
176
|
+
For a full list of CSS Base/Primitives Color tokens see [`base/colors.css`](./src/styleD/build/css/base/colors.css).
|
|
177
|
+
|
|
178
|
+
#### Typography
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { css } from '@emotion/react';
|
|
182
|
+
import { baseTypography } from '@guardian/stand'; // JS/TS usage
|
|
183
|
+
import '@guardian/stand/base/typography.css'; // CSS usage
|
|
184
|
+
|
|
185
|
+
const styleJs = css`
|
|
186
|
+
/* JS/TS usage */
|
|
187
|
+
font-family: ${baseTypography.family['Open Sans']};
|
|
188
|
+
font-size: ${baseTypography.size['14-px']};
|
|
189
|
+
font-weight: ${baseTypography.weight['Open Sans'].normal};
|
|
190
|
+
font-variation-settings: 'wdth' ${baseTypography.width['Open Sans']};
|
|
191
|
+
font-style: ${baseTypography.style.normal};
|
|
192
|
+
line-height: ${baseTypography.lineHeight.normal};
|
|
193
|
+
letter-spacing: ${baseTypography.letterSpacing['default-px']};
|
|
194
|
+
`;
|
|
195
|
+
|
|
196
|
+
const styleCss = css`
|
|
197
|
+
/* CSS usage */
|
|
198
|
+
font-family: var(--base-typography-family-open-sans);
|
|
199
|
+
font-size: var(--base-typography-size-14-px);
|
|
200
|
+
font-weight: var(--base-typography-weight-open-sans-normal);
|
|
201
|
+
font-variation-settings: 'wdth' var(--base-typography-width-open-sans);
|
|
202
|
+
font-style: var(--base-typography-style-normal);
|
|
203
|
+
line-height: var(--base-typography-line-height-normal);
|
|
204
|
+
letter-spacing: var(--base-typography-letter-spacing-default-px);
|
|
205
|
+
`;
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For a list of the available base/primitives typography tokens see the [Storybook Base Typography](https://68c12e3ed577cb56abfd31bf-ktzjjbdtby.chromatic.com/?path=/docs/stand-editorial-design-system-base-typography--docs) section.
|
|
209
|
+
|
|
210
|
+
For a full list of CSS Base/Primitives Typography tokens see [`base/typography.css`](./src/styleD/build/css/base/typography.css).
|
|
211
|
+
|
|
212
|
+
## Components
|
|
213
|
+
|
|
214
|
+
### `Byline`
|
|
215
|
+
|
|
216
|
+
A flexible byline editor component built in ProseMirror and React with usability and accessibility in mind.
|
|
217
|
+
|
|
218
|
+
**Peer dependencies:**
|
|
219
|
+
|
|
220
|
+
You'll need to install the following peer dependencies in your project to use the `Byline` component:
|
|
221
|
+
|
|
222
|
+
- `@guardian/prosemirror-invisibles`
|
|
223
|
+
- `prosemirror-dropcursor`
|
|
224
|
+
- `prosemirror-history`
|
|
225
|
+
- `prosemirror-keymap`
|
|
226
|
+
- `prosemirror-model`
|
|
227
|
+
- `prosemirror-state`
|
|
228
|
+
- `prosemirror-view`
|
|
229
|
+
|
|
230
|
+
See the `peerDependencies` section of `package.json` for compatible versions to install.
|
|
231
|
+
|
|
232
|
+
#### Usage
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
import type { BylineModel } from '@guardian/stand';
|
|
236
|
+
import { Byline } from '@guardian/stand';
|
|
237
|
+
|
|
238
|
+
const Component = () => {
|
|
239
|
+
const bylineModel: BylineModel = {
|
|
240
|
+
// ...set up your byline model here
|
|
241
|
+
};
|
|
242
|
+
...
|
|
243
|
+
return (
|
|
244
|
+
<>
|
|
245
|
+
...
|
|
246
|
+
<Byline initialValue={bylineModel} />
|
|
247
|
+
...
|
|
248
|
+
</>
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
By itself the `Byline` component is just the editor UI. You will need to set up the ProseMirror editor state, schema, and plugins to get a fully functioning byline editor. See the props and example below for a more complete implementation.
|
|
254
|
+
|
|
255
|
+
The `BylineModel` type defines the structure of the byline data which is agnostic from any other data structure. You must convert to/from this model when integrating with your application's data structures.
|
|
256
|
+
|
|
257
|
+
#### Props
|
|
258
|
+
|
|
259
|
+
See [`BylineProps`](src/byline/Byline.tsx#L41) for the full list of props, usage example can be seen in Storybook.
|
|
260
|
+
|
|
261
|
+
#### Example
|
|
262
|
+
|
|
263
|
+
The `ContentByline` component in `flexible-frontend` has a detailed example of how to use the `Byline` component from Stand. See [ContentByline.tsx](https://github.com/guardian/flexible-content/blob/1d537615a18ae24a4a5410a3f945b2b9db1dbb47/flexible-frontend/src/app/components/furniture/content-byline/ContentByline.tsx#L72-L205).
|
|
264
|
+
|
|
265
|
+
### TagPicker
|
|
266
|
+
|
|
267
|
+
#### TagAutocomplete
|
|
268
|
+
|
|
269
|
+
_Status: Testing_
|
|
270
|
+
|
|
271
|
+
Part of the overall TagPicker component, the TagAutocomplete provides an accessible
|
|
272
|
+
autocomplete input for selecting tags from a list of options, based on the [React Aria ComboBox](https://react-spectrum.adobe.com/react-aria/ComboBox) component.
|
|
273
|
+
|
|
274
|
+
**Peer dependencies:**
|
|
275
|
+
|
|
276
|
+
- `react-aria-components`
|
|
277
|
+
|
|
278
|
+
See the `peerDependencies` section of the `package.json` for compatible versions to install.
|
|
279
|
+
|
|
280
|
+
##### Props
|
|
281
|
+
|
|
282
|
+
See [`TagAutocompleteProps`](src/components/tag-picker/TagAutocomplete.tsx#L23) for the full list of props, usage example can be seen in Storybook.
|
|
283
|
+
|
|
284
|
+
#### TagTable
|
|
285
|
+
|
|
286
|
+
_Status: Testing_
|
|
287
|
+
|
|
288
|
+
Part of the overall TagPicker component, the TagTable provides an accessible
|
|
289
|
+
table for displaying tags, with options to add, remove, and reorder tags via drag and drop,
|
|
290
|
+
based on the [React Aria Table](https://react-spectrum.adobe.com/react-aria/Table) component.
|
|
291
|
+
|
|
292
|
+
**Peer dependencies:**
|
|
293
|
+
|
|
294
|
+
- `react-aria-components`
|
|
295
|
+
|
|
296
|
+
See the `peerDependencies` section of the `package.json` for compatible versions to install.
|
|
297
|
+
|
|
298
|
+
##### Props
|
|
299
|
+
|
|
300
|
+
See [`TagTableProps`](src/components/tag-picker/TagTable.tsx#L31) for the full list of props, usage example can be seen in Storybook.
|
|
301
|
+
|
|
302
|
+
#### Usage
|
|
303
|
+
|
|
304
|
+
_Example with TagAutocomplete and TagTable combined:_
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
import { TagAutocomplete, TagTable } from '@guardian/stand';
|
|
308
|
+
|
|
309
|
+
const Component = () => {
|
|
310
|
+
const [selectedTags, setSelectedTags] = useState<
|
|
311
|
+
TagManagerObjectData[] // TagManagerObjectData is an internal type representing a Tag
|
|
312
|
+
>([]);
|
|
313
|
+
const [options, setOptions] = useState<TagManagerObjectData[]>([]);
|
|
314
|
+
const [value, setValue] = useState('');
|
|
315
|
+
const onChange = (inputText: string) => {
|
|
316
|
+
setValue(inputText);
|
|
317
|
+
if (inputText === '') {
|
|
318
|
+
setOptions([]);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (inputText === '*') {
|
|
323
|
+
setOptions(exampleTags); // exampleTags is an array of Tags
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Simple filtering against exampleTags
|
|
328
|
+
const filteredItems = exampleTags.filter((t) =>
|
|
329
|
+
t.internalName.toLowerCase().includes(inputText.toLowerCase()),
|
|
330
|
+
);
|
|
331
|
+
return setOptions(filteredItems);
|
|
332
|
+
};
|
|
333
|
+
return (
|
|
334
|
+
<>
|
|
335
|
+
<div
|
|
336
|
+
css={css`
|
|
337
|
+
display: flex;
|
|
338
|
+
`}
|
|
339
|
+
>
|
|
340
|
+
<TagAutocomplete
|
|
341
|
+
onChange={onChange}
|
|
342
|
+
options={options}
|
|
343
|
+
label="Tags"
|
|
344
|
+
addTag={(tag) =>
|
|
345
|
+
setSelectedTags((tags) => {
|
|
346
|
+
return [...tags, tag];
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
loading={false}
|
|
350
|
+
placeholder={''}
|
|
351
|
+
disabled={false}
|
|
352
|
+
value={value}
|
|
353
|
+
/>
|
|
354
|
+
<select>
|
|
355
|
+
option>All tags</option>
|
|
356
|
+
</select>
|
|
357
|
+
</div>
|
|
358
|
+
<TagTable rows={selectedTags} filterRows={() => true} />
|
|
359
|
+
</>
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### Example
|
|
365
|
+
|
|
366
|
+
This is currently still in testing phase, so a production implementation is not yet available.
|
|
367
|
+
|
|
368
|
+
### Contributing
|
|
369
|
+
|
|
370
|
+
See the [Contributing to Stand](./CONTRIBUTING.md) documentation for guidelines on contributing to this project. Project setup and common tasks are listed below.
|
|
371
|
+
|
|
372
|
+
### Setup
|
|
8
373
|
|
|
9
374
|
- Run `./setup.sh` in the project root (flexible-content) directory to set up pnpm, install dependencies, and build the project.
|
|
10
375
|
|
|
11
|
-
|
|
376
|
+
### Tasks
|
|
12
377
|
|
|
13
378
|
- Run `pnpm install` to install dependencies.
|
|
14
379
|
- Run `pnpm build` to build, this makes any changes available to flexible-frontend
|
|
15
380
|
- Run `pnpm storybook` to run Storybook
|
|
381
|
+
- Run `pnpm build:storybook` to build the Storybook static site
|
|
382
|
+
- Run `pnpm build-styled` to build the Style Dictionary styles
|
|
383
|
+
- Run `pnpm test` to run tests
|
|
384
|
+
- Run `pnpm test:e2e` to run end-to-end tests using Playwright
|
|
385
|
+
- Run `pnpm test:react-matrix` to run matrix tests (see Compatibility section below)
|
|
386
|
+
- Run `pnpm tsc` to run check TypeScript types
|
|
387
|
+
- Run `pnpm lint` to run the linter
|
|
388
|
+
- Run `pnpm lint:fix` to fix any auto-fixable issues
|
|
389
|
+
- Run `pnpm format:check` to check code formatting
|
|
390
|
+
- Run `pnpm format:fix` to fix code formatting issues
|
|
391
|
+
|
|
392
|
+
### Style Dictionary
|
|
393
|
+
|
|
394
|
+
The project uses [Style Dictionary](https://styledictionary.com/) to manage design tokens.
|
|
395
|
+
|
|
396
|
+
Tokens are defined in the `src/styleD/tokens` folder.
|
|
397
|
+
|
|
398
|
+
The output styles are generated into the `src/styleD/build` folder.
|
|
399
|
+
|
|
400
|
+
We use rollup to copy the built styles into the `dist/styleD/build` folder during the build process, and these are published with the package.
|
|
401
|
+
|
|
402
|
+
Most tokens are generated from Figma variables using a script to make these available in the `src/styleD/tokens` folder. See the [Generate Design Tokens from Figma Variables](./scripts/figma/README.md) documentation for more details.
|
|
16
403
|
|
|
17
|
-
|
|
404
|
+
Use `pnpm build-styled` to generate the styles after making changes to the tokens and make sure to test and commit the changes to the built styles.
|
|
18
405
|
|
|
19
|
-
See the [
|
|
406
|
+
See the [Style Dictionary documentation](./docs/style-dictionary.md) for more details on how we structure and generate the styles.
|
|
20
407
|
|
|
21
|
-
|
|
408
|
+
### Compatibility
|
|
22
409
|
|
|
23
410
|
See the package.json `peerDependencies` section for compatible versions of React and other dependencies that Stand works with.
|
|
24
411
|
|
|
@@ -33,7 +420,7 @@ All three variables (`REACT_VERSIONS`, `EMOTION_VERSIONS`, `TS_VERSIONS`) must b
|
|
|
33
420
|
|
|
34
421
|
Matrix generation in CI uses the same JSON file in the workflow: `../.github/workflows/stand-component-library-deps-matrix.yml` to ensure consistency.
|
|
35
422
|
|
|
36
|
-
|
|
423
|
+
#### Updating Supported Versions
|
|
37
424
|
|
|
38
425
|
1. Edit `./scripts/deps-matrix-versions.json` with new versions
|
|
39
426
|
2. Run the matrix test locally:
|
|
@@ -48,7 +435,7 @@ Matrix generation in CI uses the same JSON file in the workflow: `../.github/wor
|
|
|
48
435
|
5. Update `peerDependencies` in `package.json` to reflect the new minimum / tested range
|
|
49
436
|
6. Open a PR, the CI pipeline will comment with the compatibility matrix
|
|
50
437
|
|
|
51
|
-
|
|
438
|
+
#### Tips
|
|
52
439
|
|
|
53
440
|
- Keep versions in ascending order for readability
|
|
54
441
|
- Remove deprecated versions only after confirming no downstream tool depends on them
|
|
@@ -294,7 +294,7 @@ const Byline = ({
|
|
|
294
294
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
295
295
|
"div",
|
|
296
296
|
{
|
|
297
|
-
css: styles.bylineEditorStyles(theme
|
|
297
|
+
css: styles.bylineEditorStyles(theme),
|
|
298
298
|
ref: editorRef,
|
|
299
299
|
onBlur
|
|
300
300
|
}
|
|
@@ -317,8 +317,8 @@ const Byline = ({
|
|
|
317
317
|
role: "option",
|
|
318
318
|
"aria-selected": i === currentOptionIndex,
|
|
319
319
|
css: [
|
|
320
|
-
styles.dropdownLiStyles(theme),
|
|
321
|
-
i === currentOptionIndex && styles.selectedDropdownLiStyles(theme)
|
|
320
|
+
styles.dropdownLiStyles(theme?.dropdown),
|
|
321
|
+
i === currentOptionIndex && styles.selectedDropdownLiStyles(theme?.dropdown)
|
|
322
322
|
],
|
|
323
323
|
onMouseMove: () => {
|
|
324
324
|
if (currentOptionIndex !== i) {
|
|
@@ -346,8 +346,8 @@ const Byline = ({
|
|
|
346
346
|
id: `contributor-option-${taggedContributors.length}`,
|
|
347
347
|
"aria-selected": currentOptionIndex === taggedContributors.length,
|
|
348
348
|
css: [
|
|
349
|
-
styles.dropdownLiStyles(theme),
|
|
350
|
-
currentOptionIndex === taggedContributors.length && styles.selectedDropdownLiStyles(theme)
|
|
349
|
+
styles.dropdownLiStyles(theme?.dropdown),
|
|
350
|
+
currentOptionIndex === taggedContributors.length && styles.selectedDropdownLiStyles(theme?.dropdown)
|
|
351
351
|
],
|
|
352
352
|
onMouseMove: () => {
|
|
353
353
|
if (currentOptionIndex !== taggedContributors.length) {
|
|
@@ -246,10 +246,10 @@ const Byline = ({ theme, allowUntaggedContributors, contributorLimit, enablePrev
|
|
|
246
246
|
contributorLimit,
|
|
247
247
|
allowUntaggedContributors
|
|
248
248
|
]);
|
|
249
|
-
return jsxs("div", { css: bylineContainerStyles, children: [jsx("div", { css: bylineEditorStyles(theme
|
|
249
|
+
return jsxs("div", { css: bylineContainerStyles, children: [jsx("div", { css: bylineEditorStyles(theme), ref: editorRef, onBlur }), jsx("div", { ref: dropdownRef, tabIndex: 0, css: dropdownContainerStyles(showDropdown && // show the dropdown if there are tagged contributors to select or untagged contributors are allowed
|
|
250
250
|
(taggedContributors.length > 0 || !!allowUntaggedContributors), theme?.dropdown), children: jsxs("ul", { id: "byline-dropdown", role: "listbox", css: dropdownUlStyles, children: [taggedContributors.map((contributor, i) => jsx("li", { id: `contributor-option-${i}`, role: "option", "aria-selected": i === currentOptionIndex, css: [
|
|
251
|
-
dropdownLiStyles(theme),
|
|
252
|
-
i === currentOptionIndex && selectedDropdownLiStyles(theme)
|
|
251
|
+
dropdownLiStyles(theme?.dropdown),
|
|
252
|
+
i === currentOptionIndex && selectedDropdownLiStyles(theme?.dropdown)
|
|
253
253
|
], onMouseMove: () => {
|
|
254
254
|
if (currentOptionIndex !== i) {
|
|
255
255
|
setCurrentOptionIndex(i);
|
|
@@ -258,8 +258,8 @@ const Byline = ({ theme, allowUntaggedContributors, contributorLimit, enablePrev
|
|
|
258
258
|
e.preventDefault();
|
|
259
259
|
addTaggedContributor(contributor, viewRef, setShowDropdown, contributorLimit, isTypingFromStartRange.current);
|
|
260
260
|
}, children: contributor.internalLabel ?? contributor.label }, contributor.tagId)), allowUntaggedContributors && jsxs("li", { role: "option", id: `contributor-option-${taggedContributors.length}`, "aria-selected": currentOptionIndex === taggedContributors.length, css: [
|
|
261
|
-
dropdownLiStyles(theme),
|
|
262
|
-
currentOptionIndex === taggedContributors.length && selectedDropdownLiStyles(theme)
|
|
261
|
+
dropdownLiStyles(theme?.dropdown),
|
|
262
|
+
currentOptionIndex === taggedContributors.length && selectedDropdownLiStyles(theme?.dropdown)
|
|
263
263
|
], onMouseMove: () => {
|
|
264
264
|
if (currentOptionIndex !== taggedContributors.length) {
|
|
265
265
|
setCurrentOptionIndex(taggedContributors.length);
|