@patternfly/design-tokens 1.14.3 → 1.14.4
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/build/css/tokens-charts-dark.scss +1 -1
- package/build/css/tokens-charts.scss +1 -1
- package/build/css/tokens-dark.scss +1 -1
- package/build/css/tokens-default.scss +1 -1
- package/build/css/tokens-highcontrast-dark.scss +1 -1
- package/build/css/tokens-highcontrast.scss +1 -1
- package/build/css/tokens-palette.scss +1 -1
- package/package.json +8 -8
- package/patternfly-docs/content/tokensTable.js +201 -154
- package/patternfly-docs/content/tokensToolbar.js +56 -46
- package/plugins/export-patternfly-tokens/README.md +7 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/design-tokens",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.4",
|
|
4
4
|
"description": "Define the design tokens for patternfly design system and component library",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@patternfly/react-core": "6.
|
|
34
|
+
"@patternfly/react-core": "^6.1",
|
|
35
35
|
"commander": "^12.0.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"react": "^
|
|
38
|
+
"react": "^17 || ^18",
|
|
39
39
|
"react-dom": "^18.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@figma/plugin-typings": "^1.95.0",
|
|
43
|
-
"@patternfly/documentation-framework": "^6.
|
|
44
|
-
"@patternfly/patternfly": "6.
|
|
45
|
-
"@patternfly/patternfly-a11y": "^
|
|
46
|
-
"@patternfly/react-code-editor": "6.
|
|
47
|
-
"@patternfly/react-table": "6.
|
|
43
|
+
"@patternfly/documentation-framework": "^6.1",
|
|
44
|
+
"@patternfly/patternfly": "^6.1",
|
|
45
|
+
"@patternfly/patternfly-a11y": "^5.1",
|
|
46
|
+
"@patternfly/react-code-editor": "^6.1",
|
|
47
|
+
"@patternfly/react-table": "^6.1",
|
|
48
48
|
"css-loader": "^7.1.2",
|
|
49
49
|
"html-inline-script-webpack-plugin": "^3.2.1",
|
|
50
50
|
"html-webpack-plugin": "^5.6.0",
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
EmptyState,
|
|
5
|
+
EmptyStateBody,
|
|
6
|
+
EmptyStateFooter,
|
|
7
|
+
EmptyStateActions,
|
|
8
|
+
Flex,
|
|
9
|
+
FlexItem,
|
|
10
|
+
Grid,
|
|
11
|
+
GridItem,
|
|
12
|
+
Title,
|
|
13
|
+
capitalize
|
|
14
|
+
} from '@patternfly/react-core';
|
|
3
15
|
import {
|
|
4
16
|
Table,
|
|
5
17
|
Thead,
|
|
@@ -13,11 +25,14 @@ import {
|
|
|
13
25
|
} from '@patternfly/react-table';
|
|
14
26
|
import { TokensToolbar } from './tokensToolbar';
|
|
15
27
|
import './tokensTable.css';
|
|
28
|
+
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
import global_spacer_md from '@patternfly/react-tokens/dist/esm/global_spacer_md';
|
|
30
|
+
import c_expandable_section_m_display_lg_PaddingInlineStart from '@patternfly/react-tokens/dist/esm/c_expandable_section_m_display_lg_PaddingInlineStart';
|
|
19
31
|
import LevelUpAltIcon from '@patternfly/react-icons/dist/esm/icons/level-up-alt-icon';
|
|
20
32
|
|
|
33
|
+
{
|
|
34
|
+
/* Helper functions */
|
|
35
|
+
}
|
|
21
36
|
// Used to combine data grouped by theme under each token name
|
|
22
37
|
const deepMerge = (target, source) => {
|
|
23
38
|
for (const key in source) {
|
|
@@ -28,16 +43,31 @@ const deepMerge = (target, source) => {
|
|
|
28
43
|
return Object.assign(target || {}, source);
|
|
29
44
|
};
|
|
30
45
|
|
|
46
|
+
const getTokensFromJson = (tokenJson) => {
|
|
47
|
+
// parse tokens from json, convert from modules, merge into single allTokens obj
|
|
48
|
+
const themesArr = Object.keys(tokenJson);
|
|
49
|
+
const themesObj = themesArr.reduce((acc, cur) => {
|
|
50
|
+
acc[cur] = JSON.parse(JSON.stringify(tokenJson[cur]));
|
|
51
|
+
return acc;
|
|
52
|
+
}, {});
|
|
53
|
+
return deepMerge(...Object.values(themesObj));
|
|
54
|
+
};
|
|
55
|
+
|
|
31
56
|
const getTokenChain = (themeTokenData) => {
|
|
32
57
|
let tokenChain = [];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
tokenChain
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
tokenChain
|
|
40
|
-
|
|
58
|
+
// Palette & some color tokens don't have references but we still want to still show their values
|
|
59
|
+
if (!themeTokenData?.references?.[0]) {
|
|
60
|
+
tokenChain.push(themeTokenData.value);
|
|
61
|
+
} else {
|
|
62
|
+
let referenceToken = themeTokenData?.references?.[0];
|
|
63
|
+
while (referenceToken && referenceToken !== undefined) {
|
|
64
|
+
tokenChain = [...tokenChain, referenceToken.name];
|
|
65
|
+
if (referenceToken?.references?.[0]) {
|
|
66
|
+
referenceToken = referenceToken?.references?.[0];
|
|
67
|
+
} else {
|
|
68
|
+
tokenChain.push(referenceToken.value);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
41
71
|
}
|
|
42
72
|
}
|
|
43
73
|
return tokenChain;
|
|
@@ -52,11 +82,13 @@ const showTokenChain = (themeTokenData, hasReferences) => {
|
|
|
52
82
|
<div
|
|
53
83
|
key={`${index}`}
|
|
54
84
|
style={{
|
|
55
|
-
padding: `4px 0 4px calc(${
|
|
85
|
+
padding: `4px 0 4px calc(${c_expandable_section_m_display_lg_PaddingInlineStart.value} * ${index})`
|
|
56
86
|
}}
|
|
57
87
|
>
|
|
58
88
|
<LevelUpAltIcon style={{ transform: 'rotate(90deg)' }} />
|
|
59
|
-
<span style={{ paddingInlineStart:
|
|
89
|
+
<span style={{ paddingInlineStart: c_expandable_section_m_display_lg_PaddingInlineStart.value }}>
|
|
90
|
+
{nextValue}
|
|
91
|
+
</span>
|
|
60
92
|
</div>
|
|
61
93
|
))}
|
|
62
94
|
</div>
|
|
@@ -80,26 +112,127 @@ const isSearchMatch = (searchValue, tokenName, tokenData) => {
|
|
|
80
112
|
);
|
|
81
113
|
};
|
|
82
114
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
acc[cur] = JSON.parse(JSON.stringify(tokenJson[cur]));
|
|
88
|
-
return acc;
|
|
89
|
-
}, {});
|
|
90
|
-
const allTokens = deepMerge(...Object.values(themesObj));
|
|
91
|
-
// remove default property which is duplicate of other fields
|
|
92
|
-
delete allTokens.default;
|
|
115
|
+
const getFilteredTokens = (tokensArr, searchVal) =>
|
|
116
|
+
tokensArr.filter(([tokenName, tokenData]) => isSearchMatch(searchVal, tokenName, tokenData));
|
|
117
|
+
|
|
118
|
+
const getIsColor = (value) => /^(#|rgb)/.test(value);
|
|
93
119
|
|
|
120
|
+
const getCategoryTokensArr = (selectedCategory, categoryTokens) => {
|
|
121
|
+
// Create array of all tokens/nested tokens in selectedCategory
|
|
122
|
+
let categoryTokensArr = [];
|
|
123
|
+
if (!['base', 'semantic'].includes(selectedCategory)) {
|
|
124
|
+
categoryTokensArr = Object.entries(categoryTokens);
|
|
125
|
+
} else if (['base', 'semantic'].includes(selectedCategory)) {
|
|
126
|
+
// base/semantic combine nested subcategory tokens into flattened arr
|
|
127
|
+
for (var subCategory in categoryTokens) {
|
|
128
|
+
categoryTokensArr.push(...Object.entries(categoryTokens[subCategory]));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return categoryTokensArr;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
{
|
|
135
|
+
/* Components */
|
|
136
|
+
}
|
|
137
|
+
const TokenChain = ({ tokenThemesArr }) => (
|
|
138
|
+
<Tr isExpanded>
|
|
139
|
+
<Td />
|
|
140
|
+
<Td colSpan={3}>
|
|
141
|
+
<ExpandableRowContent>
|
|
142
|
+
<Grid hasGutter>
|
|
143
|
+
{tokenThemesArr.map(([themeName, themeToken]) => (
|
|
144
|
+
<React.Fragment key={themeName}>
|
|
145
|
+
<GridItem span={2}>{capitalize(themeName)}:</GridItem>
|
|
146
|
+
<GridItem span={10}>{showTokenChain(themeToken)}</GridItem>
|
|
147
|
+
</React.Fragment>
|
|
148
|
+
))}
|
|
149
|
+
</Grid>
|
|
150
|
+
</ExpandableRowContent>
|
|
151
|
+
</Td>
|
|
152
|
+
</Tr>
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const TokenValue = ({ themeName, themeToken, tokenName }) => {
|
|
156
|
+
const isColor = getIsColor(themeToken.value);
|
|
157
|
+
return (
|
|
158
|
+
<Flex
|
|
159
|
+
justifyContent={{ default: 'justify-content-space-between' }}
|
|
160
|
+
flexWrap={{ default: 'nowrap' }}
|
|
161
|
+
key={`${themeName}-${tokenName}`}
|
|
162
|
+
>
|
|
163
|
+
<FlexItem>{capitalize(themeName)}:</FlexItem>
|
|
164
|
+
{isColor ? (
|
|
165
|
+
<FlexItem key={`${themeName}_${tokenName}_swatch`} className="pf-v6-l-flex pf-m-column pf-m-align-self-center">
|
|
166
|
+
<span className="ws-token-swatch" style={{ backgroundColor: themeToken.value }} />
|
|
167
|
+
</FlexItem>
|
|
168
|
+
) : (
|
|
169
|
+
<div className="pf-v6-l-flex pf-m-column pf-m-align-self-center">{themeToken.value}</div>
|
|
170
|
+
)}
|
|
171
|
+
</Flex>
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const TokensTableBody = ({ token, expandedTokens, setExpanded, isSemanticLayer, rowIndex }) => {
|
|
176
|
+
const [tokenName, tokenData] = token;
|
|
177
|
+
const tokenThemesArr = Object.entries(tokenData);
|
|
178
|
+
const isExpandable = tokenThemesArr.some(
|
|
179
|
+
([_themeName, themeToken]) => themeToken.hasOwnProperty('references') || getIsColor(themeToken.value)
|
|
180
|
+
);
|
|
181
|
+
const isTokenExpanded = expandedTokens.includes(tokenName);
|
|
182
|
+
const tokenDescription = tokenThemesArr[0][1].description;
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<Tbody isExpanded={isTokenExpanded}>
|
|
186
|
+
<Tr>
|
|
187
|
+
{/* Expandable row icon */}
|
|
188
|
+
<Td
|
|
189
|
+
expand={
|
|
190
|
+
isExpandable && {
|
|
191
|
+
rowIndex,
|
|
192
|
+
isExpanded: isTokenExpanded,
|
|
193
|
+
onToggle: () => setExpanded(tokenName, !isTokenExpanded),
|
|
194
|
+
expandId: `${tokenName}-expandable-toggle`
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/>
|
|
198
|
+
<Td>
|
|
199
|
+
<code>{tokenName}</code>
|
|
200
|
+
</Td>
|
|
201
|
+
{/* Token values for each theme */}
|
|
202
|
+
<Td>
|
|
203
|
+
{tokenThemesArr.map(([themeName, themeToken]) => (
|
|
204
|
+
<TokenValue themeName={themeName} themeToken={themeToken} tokenName={tokenName} key={themeName} />
|
|
205
|
+
))}
|
|
206
|
+
</Td>
|
|
207
|
+
|
|
208
|
+
{/* Description - only for semantic tokens */}
|
|
209
|
+
{isSemanticLayer && <Td>{tokenDescription}</Td>}
|
|
210
|
+
</Tr>
|
|
211
|
+
|
|
212
|
+
{/* Expandable token chain */}
|
|
213
|
+
{isTokenExpanded && <TokenChain tokenThemesArr={tokenThemesArr} />}
|
|
214
|
+
</Tbody>
|
|
215
|
+
);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
export const TokensTable = ({ tokenJson }) => {
|
|
94
219
|
// state variables
|
|
95
220
|
const [searchValue, setSearchValue] = React.useState('');
|
|
96
221
|
const [expandedTokens, setExpandedTokens] = React.useState([]);
|
|
97
|
-
const [
|
|
222
|
+
const [selectedCategory, setSelectedCategory] = React.useState('semantic');
|
|
223
|
+
|
|
224
|
+
const allTokens = getTokensFromJson(tokenJson);
|
|
225
|
+
const isSemanticLayer = selectedCategory === 'semantic';
|
|
226
|
+
const categoryTokens = allTokens[selectedCategory];
|
|
227
|
+
// get tokens for selected category
|
|
228
|
+
const categoryTokensArr = getCategoryTokensArr(selectedCategory, categoryTokens);
|
|
229
|
+
// filter selected category tokens based on search term
|
|
230
|
+
const searchResults = getFilteredTokens(categoryTokensArr, searchValue);
|
|
231
|
+
// remove extra 'default' category
|
|
232
|
+
delete allTokens.default;
|
|
233
|
+
const allCategoriesArr = Object.keys(allTokens);
|
|
98
234
|
|
|
99
235
|
// helper funcs
|
|
100
|
-
const isTokenExpanded = (tokenName) => expandedTokens.includes(tokenName);
|
|
101
|
-
const isSelectedCategory = (categoryName) =>
|
|
102
|
-
selectedCategories.length === 0 || selectedCategories.includes(categoryName);
|
|
103
236
|
const setExpanded = (tokenName, isExpanding = true) =>
|
|
104
237
|
setExpandedTokens((prevExpanded) => {
|
|
105
238
|
const otherExpandedTokens = prevExpanded.filter((n) => n !== tokenName);
|
|
@@ -111,136 +244,50 @@ export const TokensTable = ({ tokenJson, formatThemeText = capitalize }) => {
|
|
|
111
244
|
<TokensToolbar
|
|
112
245
|
searchValue={searchValue}
|
|
113
246
|
setSearchValue={setSearchValue}
|
|
114
|
-
|
|
115
|
-
|
|
247
|
+
selectedCategory={selectedCategory}
|
|
248
|
+
setSelectedCategory={setSelectedCategory}
|
|
249
|
+
resultsCount={searchResults.length.toString()}
|
|
250
|
+
categories={allCategoriesArr}
|
|
116
251
|
/>
|
|
117
252
|
<OuterScrollContainer className="tokens-table-outer-wrapper">
|
|
118
253
|
<InnerScrollContainer>
|
|
119
|
-
{
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
{/* Loop through row for each token in current layer */}
|
|
157
|
-
{filteredTokens.map(([tokenName, tokenData], rowIndex) => {
|
|
158
|
-
const tokenThemesArr = Object.entries(tokenData);
|
|
159
|
-
const hasReferences = tokenThemesArr.some(([_themeName, themeToken]) =>
|
|
160
|
-
themeToken.hasOwnProperty('references')
|
|
161
|
-
);
|
|
162
|
-
const isColorToken = tokenThemesArr[0][1].type === 'color';
|
|
163
|
-
const tokenDescription = tokenThemesArr[0][1].description;
|
|
164
|
-
|
|
165
|
-
return (
|
|
166
|
-
<Tbody key={`row-${tokenName}`} isExpanded={isTokenExpanded(tokenName)}>
|
|
167
|
-
<Tr>
|
|
168
|
-
{/* Expandable row icon */}
|
|
169
|
-
<Td
|
|
170
|
-
expand={
|
|
171
|
-
hasReferences || isColorToken
|
|
172
|
-
? {
|
|
173
|
-
rowIndex,
|
|
174
|
-
isExpanded: isTokenExpanded(tokenName),
|
|
175
|
-
onToggle: () => setExpanded(tokenName, !isTokenExpanded(tokenName)),
|
|
176
|
-
expandId: `${tokenName}-expandable-toggle`
|
|
177
|
-
}
|
|
178
|
-
: undefined
|
|
179
|
-
}
|
|
180
|
-
/>
|
|
181
|
-
<Td>
|
|
182
|
-
<code>{tokenName}</code>
|
|
183
|
-
</Td>
|
|
184
|
-
{/* Token values for each theme */}
|
|
185
|
-
<Td>
|
|
186
|
-
{tokenThemesArr.map(([themeName, themeToken]) => {
|
|
187
|
-
const isColor = /^(#|rgb)/.test(themeToken.value);
|
|
188
|
-
return (
|
|
189
|
-
<Flex
|
|
190
|
-
justifyContent={{ default: 'justify-content-space-between' }}
|
|
191
|
-
flexWrap={{ default: 'nowrap' }}
|
|
192
|
-
key={`${themeName}-${tokenName}`}
|
|
193
|
-
>
|
|
194
|
-
<FlexItem>{formatThemeText(themeName)}:</FlexItem>
|
|
195
|
-
{isColor ? (
|
|
196
|
-
<FlexItem
|
|
197
|
-
key={`${themeName}_${tokenName}_swatch`}
|
|
198
|
-
className="pf-v6-l-flex pf-m-column pf-m-align-self-center"
|
|
199
|
-
>
|
|
200
|
-
<span
|
|
201
|
-
className="ws-token-swatch"
|
|
202
|
-
style={{ backgroundColor: themeToken.value }}
|
|
203
|
-
/>
|
|
204
|
-
</FlexItem>
|
|
205
|
-
) : (
|
|
206
|
-
<div className="pf-v6-l-flex pf-m-column pf-m-align-self-center">
|
|
207
|
-
{themeToken.value}
|
|
208
|
-
</div>
|
|
209
|
-
)}
|
|
210
|
-
</Flex>
|
|
211
|
-
);
|
|
212
|
-
})}
|
|
213
|
-
</Td>
|
|
214
|
-
{/* Description - only for semantic tokens */}
|
|
215
|
-
{isSemanticLayer && <Td>{tokenDescription}</Td>}
|
|
216
|
-
</Tr>
|
|
217
|
-
|
|
218
|
-
{/* Expandable token chain */}
|
|
219
|
-
{(hasReferences || isColorToken) && isTokenExpanded(tokenName) && (
|
|
220
|
-
<Tr isExpanded>
|
|
221
|
-
<Td />
|
|
222
|
-
<Td colSpan={3}>
|
|
223
|
-
<ExpandableRowContent>
|
|
224
|
-
<Grid hasGutter>
|
|
225
|
-
{tokenThemesArr.map(([themeName, themeToken]) => (
|
|
226
|
-
<>
|
|
227
|
-
<GridItem span={2}>{formatThemeText(themeName)}:</GridItem>
|
|
228
|
-
<GridItem span={10}>{showTokenChain(themeToken, hasReferences)}</GridItem>
|
|
229
|
-
</>
|
|
230
|
-
))}
|
|
231
|
-
</Grid>
|
|
232
|
-
</ExpandableRowContent>
|
|
233
|
-
</Td>
|
|
234
|
-
</Tr>
|
|
235
|
-
)}
|
|
236
|
-
</Tbody>
|
|
237
|
-
);
|
|
238
|
-
})}
|
|
239
|
-
</Table>
|
|
240
|
-
</>
|
|
241
|
-
);
|
|
242
|
-
})
|
|
243
|
-
}
|
|
254
|
+
<Title headingLevel="h2">{capitalize(selectedCategory)} tokens</Title>
|
|
255
|
+
{searchResults.length > 0 ? (
|
|
256
|
+
<Table variant="compact" style={{ marginBlockEnd: `var(--pf-t--global--spacer--xl)` }}>
|
|
257
|
+
<Thead>
|
|
258
|
+
<Tr>
|
|
259
|
+
{/* Only semantic tokens have description, adjust columns accordingly */}
|
|
260
|
+
<Th width={5} screenReaderText="Row expansion"></Th>
|
|
261
|
+
<Th width={isSemanticLayer ? 60 : 80}>Name</Th>
|
|
262
|
+
<Th width={isSemanticLayer ? 10 : 15}>Value</Th>
|
|
263
|
+
{isSemanticLayer && <Th width={25}>Description</Th>}
|
|
264
|
+
</Tr>
|
|
265
|
+
</Thead>
|
|
266
|
+
|
|
267
|
+
{/* Loop through row for each token in current layer */}
|
|
268
|
+
{searchResults.map((token, rowIndex) => (
|
|
269
|
+
<TokensTableBody
|
|
270
|
+
key={rowIndex}
|
|
271
|
+
token={token}
|
|
272
|
+
expandedTokens={expandedTokens}
|
|
273
|
+
setExpanded={setExpanded}
|
|
274
|
+
isSemanticLayer={isSemanticLayer}
|
|
275
|
+
rowIndex={rowIndex}
|
|
276
|
+
/>
|
|
277
|
+
))}
|
|
278
|
+
</Table>
|
|
279
|
+
) : (
|
|
280
|
+
<EmptyState titleText="No results found" headingLevel="h4" icon={SearchIcon}>
|
|
281
|
+
<EmptyStateBody>No results match the filter criteria. Clear all filters and try again.</EmptyStateBody>
|
|
282
|
+
<EmptyStateFooter>
|
|
283
|
+
<EmptyStateActions>
|
|
284
|
+
<Button onClick={() => setSearchValue('')} variant="link">
|
|
285
|
+
Clear search
|
|
286
|
+
</Button>
|
|
287
|
+
</EmptyStateActions>
|
|
288
|
+
</EmptyStateFooter>
|
|
289
|
+
</EmptyState>
|
|
290
|
+
)}
|
|
244
291
|
</InnerScrollContainer>
|
|
245
292
|
</OuterScrollContainer>
|
|
246
293
|
</React.Fragment>
|
|
@@ -7,15 +7,61 @@ import {
|
|
|
7
7
|
SelectOption,
|
|
8
8
|
Toolbar,
|
|
9
9
|
ToolbarItem,
|
|
10
|
-
ToolbarContent
|
|
10
|
+
ToolbarContent,
|
|
11
|
+
capitalize
|
|
11
12
|
} from '@patternfly/react-core';
|
|
12
13
|
import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
const TokensToolbarSelect = ({ selectedCategory, setSelectedCategory, categories }) => {
|
|
15
16
|
const [isSelectOpen, setIsSelectOpen] = React.useState(false);
|
|
17
|
+
const handleSelect = (_e, category) => {
|
|
18
|
+
if (!(selectedCategory === category)) {
|
|
19
|
+
setSelectedCategory(category);
|
|
20
|
+
}
|
|
21
|
+
setIsSelectOpen(!isSelectOpen);
|
|
22
|
+
};
|
|
16
23
|
|
|
24
|
+
const SelectToggle = (toggleRef) => (
|
|
25
|
+
<MenuToggle
|
|
26
|
+
icon={<FilterIcon />}
|
|
27
|
+
ref={toggleRef}
|
|
28
|
+
onClick={() => setIsSelectOpen(!isSelectOpen)}
|
|
29
|
+
isExpanded={isSelectOpen}
|
|
30
|
+
>
|
|
31
|
+
{capitalize(selectedCategory)} tokens
|
|
32
|
+
</MenuToggle>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Select
|
|
37
|
+
aria-label="Select Input"
|
|
38
|
+
role="menu"
|
|
39
|
+
toggle={SelectToggle}
|
|
40
|
+
isOpen={isSelectOpen}
|
|
41
|
+
onOpenChange={(isOpen) => setIsSelectOpen(isOpen)}
|
|
42
|
+
onSelect={handleSelect}
|
|
43
|
+
>
|
|
44
|
+
<SelectList>
|
|
45
|
+
{categories.map((category, idx) => (
|
|
46
|
+
<SelectOption key={idx} value={category} isSelected={selectedCategory === category}>
|
|
47
|
+
{capitalize(category)} tokens
|
|
48
|
+
</SelectOption>
|
|
49
|
+
))}
|
|
50
|
+
</SelectList>
|
|
51
|
+
</Select>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const TokensToolbar = ({
|
|
56
|
+
selectedCategory,
|
|
57
|
+
setSelectedCategory,
|
|
58
|
+
searchValue,
|
|
59
|
+
setSearchValue,
|
|
60
|
+
resultsCount,
|
|
61
|
+
categories
|
|
62
|
+
}) => {
|
|
17
63
|
return (
|
|
18
|
-
<Toolbar
|
|
64
|
+
<Toolbar>
|
|
19
65
|
<ToolbarContent>
|
|
20
66
|
<ToolbarItem variant="search-filter">
|
|
21
67
|
<SearchInput
|
|
@@ -24,52 +70,16 @@ export const TokensToolbar = ({ selectedCategories, setSelectedCategories, searc
|
|
|
24
70
|
value={searchValue}
|
|
25
71
|
onChange={(_event, value) => setSearchValue(value)}
|
|
26
72
|
onClear={() => setSearchValue('')}
|
|
73
|
+
resultsCount={resultsCount}
|
|
27
74
|
/>
|
|
28
75
|
</ToolbarItem>
|
|
76
|
+
|
|
29
77
|
<ToolbarItem>
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<MenuToggle
|
|
36
|
-
icon={<FilterIcon />}
|
|
37
|
-
ref={toggleRef}
|
|
38
|
-
onClick={() => setIsSelectOpen(!isSelectOpen)}
|
|
39
|
-
isExpanded={isSelectOpen}
|
|
40
|
-
>
|
|
41
|
-
Category
|
|
42
|
-
</MenuToggle>
|
|
43
|
-
)}
|
|
44
|
-
isOpen={isSelectOpen}
|
|
45
|
-
onOpenChange={(isOpen) => setIsSelectOpen(isOpen)}
|
|
46
|
-
onSelect={(_e, category) => {
|
|
47
|
-
if (selectedCategories.includes(category)) {
|
|
48
|
-
setSelectedCategories(selectedCategories.filter((cat) => cat !== category));
|
|
49
|
-
} else {
|
|
50
|
-
setSelectedCategories([...selectedCategories, category]);
|
|
51
|
-
}
|
|
52
|
-
setIsSelectOpen(!isSelectOpen);
|
|
53
|
-
}}
|
|
54
|
-
>
|
|
55
|
-
<SelectList>
|
|
56
|
-
<SelectOption hasCheckbox key={0} value="colors" isSelected={selectedCategories.includes('colors')}>
|
|
57
|
-
Colors
|
|
58
|
-
</SelectOption>
|
|
59
|
-
<SelectOption hasCheckbox key={1} value="dimension" isSelected={selectedCategories.includes('dimension')}>
|
|
60
|
-
Dimension
|
|
61
|
-
</SelectOption>
|
|
62
|
-
<SelectOption hasCheckbox key={2} value="motion" isSelected={selectedCategories.includes('motion')}>
|
|
63
|
-
Motion
|
|
64
|
-
</SelectOption>
|
|
65
|
-
<SelectOption hasCheckbox key={3} value="palette" isSelected={selectedCategories.includes('palette')}>
|
|
66
|
-
Palette
|
|
67
|
-
</SelectOption>
|
|
68
|
-
<SelectOption hasCheckbox key={4} value="chart" isSelected={selectedCategories.includes('chart')}>
|
|
69
|
-
Chart
|
|
70
|
-
</SelectOption>
|
|
71
|
-
</SelectList>
|
|
72
|
-
</Select>
|
|
78
|
+
<TokensToolbarSelect
|
|
79
|
+
selectedCategory={selectedCategory}
|
|
80
|
+
setSelectedCategory={setSelectedCategory}
|
|
81
|
+
categories={categories}
|
|
82
|
+
/>
|
|
73
83
|
</ToolbarItem>
|
|
74
84
|
</ToolbarContent>
|
|
75
85
|
</Toolbar>
|
|
@@ -15,10 +15,12 @@ The Export Patternfly Tokens plugin should now be available to use as a developm
|
|
|
15
15
|
Once the plugin has been added to Figma via the manifest file:
|
|
16
16
|
1. Make sure you are **not** in Figma's developer mode.
|
|
17
17
|
1. In Figma, select **Plugins** > **Development** > **Export Patternfly Tokens** > **Export Tokens**.
|
|
18
|
-
1. Click **Export Tokens**. The text area will display a concatenated list of all tokens exported from the Figma library. Links to each exported JSON file are displayed at the bottom of the dialog.
|
|
19
|
-
1. Click
|
|
20
|
-
1. Copy the local JSON files to your cloned design-tokens repo:
|
|
21
|
-
1.
|
|
22
|
-
1.
|
|
18
|
+
1. Click **Export Tokens**. The text area will display a concatenated list of all tokens exported from the Figma library. Links to each exported JSON file are displayed at the bottom of the dialog. There is a "Download all files" link (named `tokens.zip`) at the top of the dialog that contains all of the exported files.
|
|
19
|
+
1. Click on the `tokens.zip` file to download all of the files, unless you only want to update a specific type of token. In that case, you can click any of the JSON file links to save them locally (do not rename the JSON files!). Note: it's much easier to download all of the files at once via the `tokens.zip` file. There is no harm in downloading all of the files at once, unless there is a specific reason you want to exclude any of them.
|
|
20
|
+
1. Copy the local JSON files you downloaded to your cloned design-tokens repo:
|
|
21
|
+
1. If you downloaded `tokens.zip` in the previous step, unzip the file and simply copy the "tokens" directory it creates to **\packages\module** and override the existing "tokens" directory.
|
|
22
|
+
1. If you downloaded individual files:
|
|
23
|
+
1. Copy files that do not end in **.dark.json** to **\packages\module\tokens\default**.
|
|
24
|
+
1. Copy files ending in **.dark.json** and **palette.color.json** to **\packages\module\tokens\dark**.
|
|
23
25
|
|
|
24
26
|
Note that **palette.color.json** is saved to both the **default** and **dark** directories.
|