Skip to content

Commit b495279

Browse files
wobsorianobrkalowalexcarpenterpanteliselefLekoArts
authored
chore(clerk-js): Add API Keys component descriptors (#6095)
Co-authored-by: Bryce Kalow <[email protected]> Co-authored-by: Alex Carpenter <[email protected]> Co-authored-by: panteliselef <[email protected]> Co-authored-by: Lennart <[email protected]>
1 parent 125255b commit b495279

File tree

10 files changed

+107
-15
lines changed

10 files changed

+107
-15
lines changed

.changeset/chilly-pears-film.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@clerk/clerk-js": patch
3+
"@clerk/types": patch
4+
---
5+
6+
Add element descriptors to `<APIKeys />` component

packages/clerk-js/bundlewatch.config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{ "path": "./dist/clerk.browser.js", "maxSize": "70.16KB" },
55
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "113KB" },
66
{ "path": "./dist/clerk.headless*.js", "maxSize": "53.06KB" },
7-
{ "path": "./dist/ui-common*.js", "maxSize": "108.4KB" },
7+
{ "path": "./dist/ui-common*.js", "maxSize": "108.54KB" },
88
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
99
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
1010
{ "path": "./dist/createorganization*.js", "maxSize": "5KB" },

packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@ import { lazy, useState } from 'react';
55
import useSWRMutation from 'swr/mutation';
66

77
import { useApiKeysContext, withCoreUserGuard } from '@/ui/contexts';
8-
import { Box, Button, Col, Flex, Flow, Icon, localizationKeys, useLocalizations } from '@/ui/customizables';
8+
import {
9+
Box,
10+
Button,
11+
Col,
12+
descriptors,
13+
Flex,
14+
Flow,
15+
Icon,
16+
localizationKeys,
17+
useLocalizations,
18+
} from '@/ui/customizables';
919
import { Action } from '@/ui/elements/Action';
1020
import { useCardState, withCardStateProvider } from '@/ui/elements/contexts';
1121
import { InputWithIcon } from '@/ui/elements/InputWithIcon';
@@ -81,6 +91,7 @@ export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPagePr
8191
<Col
8292
gap={4}
8393
sx={{ width: '100%' }}
94+
elementDescriptor={descriptors.apiKeys}
8495
>
8596
<Action.Root>
8697
<Flex
@@ -93,8 +104,9 @@ export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPagePr
93104
alignItems: 'stretch',
94105
},
95106
}}
107+
elementDescriptor={descriptors.apiKeysHeader}
96108
>
97-
<Box>
109+
<Box elementDescriptor={descriptors.apiKeysSearchBox}>
98110
<InputWithIcon
99111
placeholder={t(localizationKeys('apiKeys.action__search'))}
100112
leftIcon={<Icon icon={MagnifyingGlass} />}
@@ -103,6 +115,7 @@ export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPagePr
103115
setSearch(e.target.value);
104116
setPage(1);
105117
}}
118+
elementDescriptor={descriptors.apiKeysSearchInput}
106119
/>
107120
</Box>
108121
<Action.Trigger
@@ -112,6 +125,7 @@ export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPagePr
112125
<Button
113126
variant='solid'
114127
localizationKey={localizationKeys('apiKeys.action__add')}
128+
elementDescriptor={descriptors.apiKeysAddButton}
115129
/>
116130
</Action.Trigger>
117131
</Flex>
@@ -130,6 +144,7 @@ export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPagePr
130144
rows={apiKeys}
131145
isLoading={isLoading}
132146
onRevoke={handleRevoke}
147+
elementDescriptor={descriptors.apiKeysTable}
133148
/>
134149
{itemCount > (perPage ?? 5) && (
135150
<Pagination

packages/clerk-js/src/ui/components/ApiKeys/ApiKeysTable.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
Thead,
2121
Tr,
2222
} from '@/ui/customizables';
23+
import type { ElementDescriptor } from '@/ui/customizables/elementDescriptors';
2324
import { ThreeDotsMenu } from '@/ui/elements/ThreeDotsMenu';
2425
import { useClipboard } from '@/ui/hooks';
2526
import { Check, ClipboardOutline, Eye, EyeSlash } from '@/ui/icons';
@@ -50,6 +51,7 @@ const CopySecretButton = ({ apiKeyID }: { apiKeyID: string }) => {
5051
aria-label={hasCopied ? 'Copied API key to clipboard' : 'Copy API key'}
5152
onClick={() => setEnabled(true)}
5253
focusRing={false}
54+
elementDescriptor={descriptors.apiKeysCopyButton}
5355
>
5456
<Icon
5557
size='sm'
@@ -92,6 +94,7 @@ const SecretInputWithToggle = ({ apiKeyID }: { apiKeyID: string }) => {
9294
})}
9395
focusRing={false}
9496
aria-label={'Show key'}
97+
elementDescriptor={descriptors.apiKeysRevealButton}
9598
onClick={() => setRevealed(!revealed)}
9699
>
97100
<Icon
@@ -107,14 +110,19 @@ export const ApiKeysTable = ({
107110
rows,
108111
isLoading,
109112
onRevoke,
113+
elementDescriptor,
110114
}: {
111115
rows: APIKeyResource[];
112116
isLoading: boolean;
113117
onRevoke: (id: string, name: string) => void;
118+
elementDescriptor?: ElementDescriptor;
114119
}) => {
115120
return (
116121
<Flex sx={t => ({ width: '100%', [mqu.sm]: { overflowX: 'auto', padding: t.space.$0x25 } })}>
117-
<Table sx={t => ({ background: t.colors.$colorBackground })}>
122+
<Table
123+
sx={t => ({ background: t.colors.$colorBackground })}
124+
elementDescriptor={elementDescriptor}
125+
>
118126
<Thead>
119127
<Tr>
120128
<Th>Name</Th>

packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState } from 'react';
22

3-
import { Box, Button, Col, Flex, FormLabel, localizationKeys, Text } from '@/ui/customizables';
3+
import { Box, Button, Col, descriptors, Flex, FormLabel, localizationKeys, Text } from '@/ui/customizables';
44
import { useActionContext } from '@/ui/elements/Action/ActionRoot';
55
import { Form } from '@/ui/elements/Form';
66
import { FormButtons } from '@/ui/elements/FormButtons';
@@ -97,14 +97,21 @@ export const CreateApiKeyForm = ({ onCreate, isSubmitting }: CreateApiKeyFormPro
9797
<FormContainer
9898
headerTitle={localizationKeys('apiKeys.formTitle')}
9999
headerSubtitle={localizationKeys('apiKeys.formHint')}
100+
elementDescriptor={descriptors.apiKeysCreateForm}
100101
>
101102
<Form.Root onSubmit={handleSubmit}>
102-
<Form.ControlRow elementId={nameField.id}>
103+
<Form.ControlRow
104+
elementId={nameField.id}
105+
elementDescriptor={descriptors.apiKeysCreateFormNameInput}
106+
>
103107
<Form.PlainInput {...nameField.props} />
104108
</Form.ControlRow>
105109
{showAdvanced && (
106110
<>
107-
<Form.ControlRow elementId={descriptionField.id}>
111+
<Form.ControlRow
112+
elementId={descriptionField.id}
113+
elementDescriptor={descriptors.apiKeysCreateFormDescriptionInput}
114+
>
108115
<Form.PlainInput {...descriptionField.props} />
109116
</Form.ControlRow>
110117
<Flex
@@ -155,6 +162,7 @@ export const CreateApiKeyForm = ({ onCreate, isSubmitting }: CreateApiKeyFormPro
155162
<Form.ControlRow
156163
elementId={expirationDateField.id}
157164
sx={{ flex: 3 }}
165+
elementDescriptor={descriptors.apiKeysCreateFormExpirationInput}
158166
>
159167
<Form.PlainInput
160168
type='date'
@@ -190,6 +198,7 @@ export const CreateApiKeyForm = ({ onCreate, isSubmitting }: CreateApiKeyFormPro
190198
isDisabled={!canSubmit}
191199
onReset={closeCardFn}
192200
isLoading={isSubmitting}
201+
elementDescriptor={descriptors.apiKeysCreateFormSubmitButton}
193202
/>
194203
</Flex>
195204
</Form.Root>

packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useClerk } from '@clerk/shared/react';
22
import { useSWRConfig } from 'swr';
33

4+
import { descriptors } from '@/ui/customizables';
45
import { Card } from '@/ui/elements/Card';
56
import { Form } from '@/ui/elements/Form';
67
import { FormButtons } from '@/ui/elements/FormButtons';
@@ -37,6 +38,7 @@ export const RevokeAPIKeyConfirmationModal = ({
3738

3839
await clerk.apiKeys.revoke({ apiKeyID: apiKeyId });
3940
const cacheKey = { key: 'api-keys', subject };
41+
4042
void mutate(cacheKey);
4143
onClose();
4244
};
@@ -79,7 +81,10 @@ export const RevokeAPIKeyConfirmationModal = ({
7981
: {},
8082
]}
8183
>
82-
<Card.Root role='alertdialog'>
84+
<Card.Root
85+
role='alertdialog'
86+
elementDescriptor={descriptors.apiKeysRevokeModal}
87+
>
8388
<Card.Content
8489
sx={t => ({
8590
textAlign: 'left',
@@ -91,14 +96,18 @@ export const RevokeAPIKeyConfirmationModal = ({
9196
headerSubtitle={localizationKeys('apiKeys.revokeConfirmation.formHint')}
9297
>
9398
<Form.Root onSubmit={handleSubmit}>
94-
<Form.ControlRow elementId={revokeField.id}>
99+
<Form.ControlRow
100+
elementId={revokeField.id}
101+
elementDescriptor={descriptors.apiKeysRevokeModalInput}
102+
>
95103
<Form.PlainInput {...revokeField.props} />
96104
</Form.ControlRow>
97105
<FormButtons
98106
submitLabel={localizationKeys('apiKeys.revokeConfirmation.formButtonPrimary__revoke')}
99107
colorScheme='danger'
100108
isDisabled={!canSubmit}
101109
onReset={onClose}
110+
elementDescriptor={descriptors.apiKeysRevokeModalSubmitButton}
102111
/>
103112
</Form.Root>
104113
</FormContainer>

packages/clerk-js/src/ui/components/ApiKeys/useApiKeys.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export const useApiKeys = ({ subject, perPage = 5 }: { subject: string; perPage?
88
key: 'api-keys',
99
subject,
1010
};
11-
1211
const { data: apiKeys, isLoading, mutate } = useSWR(cacheKey, () => clerk.apiKeys.getAll({ subject }));
1312
const [search, setSearch] = useState('');
1413
const filteredApiKeys = (apiKeys ?? []).filter(key => key.name.toLowerCase().includes(search.toLowerCase()));

packages/clerk-js/src/ui/customizables/elementDescriptors.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([
333333
'tabListContainer',
334334

335335
'tableHead',
336+
'tableBody',
337+
'tableRow',
338+
'tableHeaderCell',
339+
'tableBodyCell',
336340

337341
'paginationButton',
338342
'paginationButtonIcon',
@@ -458,6 +462,23 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([
458462
'notificationBadge',
459463
'buttonArrowIcon',
460464
'spinner',
465+
466+
'apiKeys',
467+
'apiKeysHeader',
468+
'apiKeysSearchBox',
469+
'apiKeysSearchInput',
470+
'apiKeysAddButton',
471+
'apiKeysTable',
472+
'apiKeysCopyButton',
473+
'apiKeysRevealButton',
474+
'apiKeysCreateForm',
475+
'apiKeysCreateFormNameInput',
476+
'apiKeysCreateFormDescriptionInput',
477+
'apiKeysCreateFormExpirationInput',
478+
'apiKeysCreateFormSubmitButton',
479+
'apiKeysRevokeModal',
480+
'apiKeysRevokeModalInput',
481+
'apiKeysRevokeModalSubmitButton',
461482
] as const).map(camelize) as (keyof ElementsConfig)[];
462483

463484
type TargettableClassname<K extends keyof ElementsConfig> = `${typeof CLASS_PREFIX}${K}`;

packages/clerk-js/src/ui/customizables/index.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,15 @@ export const NotificationBadge = makeCustomizable(makeLocalizable(sanitizeDomPro
5555
});
5656

5757
export const Table = makeCustomizable(sanitizeDomProps(Primitives.Table), { defaultDescriptor: descriptors.table });
58-
export const Thead = makeCustomizable(sanitizeDomProps(Primitives.Thead));
59-
export const Tbody = makeCustomizable(sanitizeDomProps(Primitives.Tbody));
60-
export const Tr = makeCustomizable(sanitizeDomProps(Primitives.Tr));
61-
export const Th = makeCustomizable(makeLocalizable(sanitizeDomProps(Primitives.Th)));
62-
export const Td = makeCustomizable(makeLocalizable(sanitizeDomProps(Primitives.Td)));
58+
export const Thead = makeCustomizable(sanitizeDomProps(Primitives.Thead), { defaultDescriptor: descriptors.tableHead });
59+
export const Tbody = makeCustomizable(sanitizeDomProps(Primitives.Tbody), { defaultDescriptor: descriptors.tableBody });
60+
export const Tr = makeCustomizable(sanitizeDomProps(Primitives.Tr), { defaultDescriptor: descriptors.tableRow });
61+
export const Th = makeCustomizable(makeLocalizable(sanitizeDomProps(Primitives.Th)), {
62+
defaultDescriptor: descriptors.tableHeaderCell,
63+
});
64+
export const Td = makeCustomizable(makeLocalizable(sanitizeDomProps(Primitives.Td)), {
65+
defaultDescriptor: descriptors.tableBodyCell,
66+
});
6367

6468
export const Dl = makeCustomizable(makeLocalizable(sanitizeDomProps(Primitives.Dl)));
6569
export const Dd = makeCustomizable(makeLocalizable(sanitizeDomProps(Primitives.Dd)));

packages/types/src/appearance.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,10 @@ export type ElementsConfig = {
459459
tabListContainer: WithOptions;
460460

461461
tableHead: WithOptions;
462+
tableBody: WithOptions;
463+
tableRow: WithOptions;
464+
tableHeaderCell: WithOptions;
465+
tableBodyCell: WithOptions;
462466

463467
paginationButton: WithOptions;
464468
paginationButtonIcon: WithOptions;
@@ -586,6 +590,23 @@ export type ElementsConfig = {
586590
notificationBadge: WithOptions;
587591
buttonArrowIcon: WithOptions;
588592
spinner: WithOptions;
593+
594+
apiKeys: WithOptions;
595+
apiKeysHeader: WithOptions;
596+
apiKeysSearchBox: WithOptions;
597+
apiKeysSearchInput: WithOptions;
598+
apiKeysAddButton: WithOptions;
599+
apiKeysTable: WithOptions;
600+
apiKeysCopyButton: WithOptions<string>;
601+
apiKeysRevealButton: WithOptions<string>;
602+
apiKeysCreateForm: WithOptions;
603+
apiKeysCreateFormNameInput: WithOptions;
604+
apiKeysCreateFormDescriptionInput: WithOptions;
605+
apiKeysCreateFormExpirationInput: WithOptions;
606+
apiKeysCreateFormSubmitButton: WithOptions;
607+
apiKeysRevokeModal: WithOptions;
608+
apiKeysRevokeModalInput: WithOptions;
609+
apiKeysRevokeModalSubmitButton: WithOptions;
589610
};
590611

591612
export type Elements = {

0 commit comments

Comments
 (0)