@nixxie-cms/auth 2.0.0 → 2.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"InitPage.d.ts","sourceRoot":"../../../../src/pages","sources":["InitPage.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAgB;yBAE5B,OAAO,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AAArD,wBAAuF;AAEvF,iBAAS,QAAQ,CAAC,EAChB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,YAAY,EAAE,YAAY,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,2CA4QA"}
1
+ {"version":3,"file":"InitPage.d.ts","sourceRoot":"../../../../src/pages","sources":["InitPage.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAgB;yBAE5B,OAAO,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AAArD,wBAAuF;AAEvF,iBAAS,QAAQ,CAAC,EAChB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,YAAY,EAAE,YAAY,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,2CAyRA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SigninPage.d.ts","sourceRoot":"../../../../src/pages","sources":["SigninPage.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAgB;yBAE5B,OAAO,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;AAAvD,wBAA2F;AAE3F,iBAAS,UAAU,CAAC,EAClB,aAAa,EACb,WAAW,EACX,YAAY,GACb,EAAE;IACD,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,YAAY,CAAA;CAC3B,2CA4SA"}
1
+ {"version":3,"file":"SigninPage.d.ts","sourceRoot":"../../../../src/pages","sources":["SigninPage.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAgB;yBAE5B,OAAO,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;AAAvD,wBAA2F;AAE3F,iBAAS,UAAU,CAAC,EAClB,aAAa,EACb,WAAW,EACX,YAAY,GACb,EAAE;IACD,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,YAAY,CAAA;CAC3B,2CA+TA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nixxie-cms/auth",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/nixxie-cms-auth.cjs.js",
6
6
  "module": "dist/nixxie-cms-auth.esm.js",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "react": "^19.2.4",
39
- "@nixxie-cms/core": "^2.0.0"
39
+ "@nixxie-cms/core": "^2.2.0"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@nixxie-cms/core": "^2.0.0",
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var NextHead = require('next/head');
6
+ var react = require('react');
6
7
  var style = require('@keystar/ui/style');
7
8
  var apollo = require('@nixxie-cms/core/admin-ui/apollo');
8
9
  var components = require('@nixxie-cms/core/admin-ui/components');
@@ -11,7 +12,6 @@ var router = require('@nixxie-cms/core/admin-ui/router');
11
12
  var utils = require('@nixxie-cms/core/admin-ui/utils');
12
13
  var useFromRedirect = require('../../../dist/useFromRedirect-80f27dbb.cjs.js');
13
14
  var jsxRuntime = require('react/jsx-runtime');
14
- require('react');
15
15
 
16
16
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
17
17
 
@@ -61,12 +61,24 @@ function InitPage$1({
61
61
  }
62
62
  });
63
63
  } catch (e) {
64
- console.error(e);
64
+ if (process.env.NODE_ENV !== 'production') console.error(e);
65
65
  return;
66
66
  }
67
67
  router$1.push(redirect);
68
68
  };
69
69
  const pending = loading || (data === null || data === void 0 || (_data$authenticate = data.authenticate) === null || _data$authenticate === void 0 ? void 0 : _data$authenticate.__typename) === successTypename;
70
+
71
+ // Announce and focus the error region when item creation fails.
72
+ const errorRef = react.useRef(null);
73
+ react.useEffect(() => {
74
+ if (!error) return;
75
+ try {
76
+ var _errorRef$current;
77
+ (_errorRef$current = errorRef.current) === null || _errorRef$current === void 0 || _errorRef$current.focus();
78
+ } catch {
79
+ // focus is best-effort; ignore environments where it isn't available
80
+ }
81
+ }, [error]);
70
82
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
71
83
  children: [/*#__PURE__*/jsxRuntime.jsx(NextHead__default["default"], {
72
84
  children: /*#__PURE__*/jsxRuntime.jsx("title", {
@@ -81,7 +93,7 @@ function InitPage$1({
81
93
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
82
94
  className: style.css({
83
95
  width: 420,
84
- backgroundColor: '#000000',
96
+ backgroundColor: style.tokenSchema.color.scale.black,
85
97
  display: 'flex',
86
98
  flexDirection: 'column',
87
99
  justifyContent: 'space-between',
@@ -125,7 +137,7 @@ function InitPage$1({
125
137
  className: style.css({
126
138
  fontSize: 15,
127
139
  fontWeight: 600,
128
- color: '#ffffff',
140
+ color: style.tokenSchema.color.foreground.onEmphasis,
129
141
  letterSpacing: '-0.03em',
130
142
  lineHeight: 1
131
143
  }),
@@ -137,7 +149,7 @@ function InitPage$1({
137
149
  margin: '0 0 16px',
138
150
  fontSize: 34,
139
151
  fontWeight: 700,
140
- color: '#ffffff',
152
+ color: style.tokenSchema.color.foreground.onEmphasis,
141
153
  letterSpacing: '-0.04em',
142
154
  lineHeight: 1.15
143
155
  }),
@@ -146,7 +158,7 @@ function InitPage$1({
146
158
  className: style.css({
147
159
  margin: 0,
148
160
  fontSize: 13.5,
149
- color: 'rgba(255,255,255,0.38)',
161
+ color: style.tokenSchema.color.foreground.inverseSecondary,
150
162
  lineHeight: 1.65
151
163
  }),
152
164
  children: ["Create your first admin account to", /*#__PURE__*/jsxRuntime.jsx("br", {}), "get started with Nixxie CMS."]
@@ -155,7 +167,7 @@ function InitPage$1({
155
167
  className: style.css({
156
168
  margin: 0,
157
169
  fontSize: 10.5,
158
- color: 'rgba(255,255,255,0.18)',
170
+ color: style.tokenSchema.color.foreground.inverseSecondary,
159
171
  letterSpacing: '0.06em',
160
172
  textTransform: 'uppercase'
161
173
  }),
@@ -164,7 +176,7 @@ function InitPage$1({
164
176
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
165
177
  className: style.css({
166
178
  flex: 1,
167
- backgroundColor: '#ffffff',
179
+ backgroundColor: style.tokenSchema.color.background.canvas,
168
180
  display: 'flex',
169
181
  alignItems: 'center',
170
182
  justifyContent: 'center',
@@ -186,7 +198,7 @@ function InitPage$1({
186
198
  width: 36,
187
199
  height: 36,
188
200
  borderRadius: 8,
189
- backgroundColor: '#000000',
201
+ backgroundColor: style.tokenSchema.color.scale.black,
190
202
  marginBottom: 32
191
203
  }),
192
204
  children: /*#__PURE__*/jsxRuntime.jsx("svg", {
@@ -207,7 +219,7 @@ function InitPage$1({
207
219
  margin: '0 0 6px',
208
220
  fontSize: 23,
209
221
  fontWeight: 700,
210
- color: '#0a0a0a',
222
+ color: style.tokenSchema.color.foreground.neutralEmphasis,
211
223
  letterSpacing: '-0.03em',
212
224
  lineHeight: 1.2
213
225
  }),
@@ -216,12 +228,18 @@ function InitPage$1({
216
228
  className: style.css({
217
229
  margin: '0 0 28px',
218
230
  fontSize: 13.5,
219
- color: '#8a8a8a',
231
+ color: style.tokenSchema.color.foreground.neutralSecondary,
220
232
  lineHeight: 1.5
221
233
  }),
222
234
  children: "Set up your admin account to start using Nixxie CMS."
223
- }), /*#__PURE__*/jsxRuntime.jsx(components.GraphQLErrorNotice, {
224
- errors: [error]
235
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
236
+ ref: errorRef,
237
+ tabIndex: -1,
238
+ role: "alert",
239
+ "aria-live": "assertive",
240
+ children: /*#__PURE__*/jsxRuntime.jsx(components.GraphQLErrorNotice, {
241
+ errors: [error]
242
+ })
225
243
  }), /*#__PURE__*/jsxRuntime.jsxs("form", {
226
244
  onSubmit: onSubmit,
227
245
  className: style.css({
@@ -241,8 +259,8 @@ function InitPage$1({
241
259
  justifyContent: 'center',
242
260
  paddingInline: 20,
243
261
  paddingBlock: 11,
244
- backgroundColor: '#000000',
245
- color: '#ffffff',
262
+ backgroundColor: style.tokenSchema.color.scale.black,
263
+ color: style.tokenSchema.color.foreground.onEmphasis,
246
264
  borderRadius: 7,
247
265
  fontSize: 14,
248
266
  fontWeight: 600,
@@ -257,7 +275,7 @@ function InitPage$1({
257
275
  backgroundColor: '#1a1a1a'
258
276
  },
259
277
  '&:focus-visible': {
260
- outline: '2px solid #000',
278
+ outline: `2px solid ${style.tokenSchema.color.scale.black}`,
261
279
  outlineOffset: 3,
262
280
  borderRadius: 7
263
281
  }
@@ -1,5 +1,6 @@
1
1
  import NextHead from 'next/head';
2
- import { css } from '@keystar/ui/style';
2
+ import { useRef, useEffect } from 'react';
3
+ import { css, tokenSchema } from '@keystar/ui/style';
3
4
  import { useMutation, gql } from '@nixxie-cms/core/admin-ui/apollo';
4
5
  import { GraphQLErrorNotice } from '@nixxie-cms/core/admin-ui/components';
5
6
  import { useList } from '@nixxie-cms/core/admin-ui/context';
@@ -7,7 +8,6 @@ import { useRouter } from '@nixxie-cms/core/admin-ui/router';
7
8
  import { useBuildItem, Fields } from '@nixxie-cms/core/admin-ui/utils';
8
9
  import { u as useRedirect } from '../../../dist/useFromRedirect-e80750d8.esm.js';
9
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
- import 'react';
11
11
 
12
12
  var InitPage = props => () => /*#__PURE__*/jsx(InitPage$1, {
13
13
  ...props
@@ -53,12 +53,24 @@ function InitPage$1({
53
53
  }
54
54
  });
55
55
  } catch (e) {
56
- console.error(e);
56
+ if (process.env.NODE_ENV !== 'production') console.error(e);
57
57
  return;
58
58
  }
59
59
  router.push(redirect);
60
60
  };
61
61
  const pending = loading || (data === null || data === void 0 || (_data$authenticate = data.authenticate) === null || _data$authenticate === void 0 ? void 0 : _data$authenticate.__typename) === successTypename;
62
+
63
+ // Announce and focus the error region when item creation fails.
64
+ const errorRef = useRef(null);
65
+ useEffect(() => {
66
+ if (!error) return;
67
+ try {
68
+ var _errorRef$current;
69
+ (_errorRef$current = errorRef.current) === null || _errorRef$current === void 0 || _errorRef$current.focus();
70
+ } catch {
71
+ // focus is best-effort; ignore environments where it isn't available
72
+ }
73
+ }, [error]);
62
74
  return /*#__PURE__*/jsxs(Fragment, {
63
75
  children: [/*#__PURE__*/jsx(NextHead, {
64
76
  children: /*#__PURE__*/jsx("title", {
@@ -73,7 +85,7 @@ function InitPage$1({
73
85
  children: [/*#__PURE__*/jsxs("div", {
74
86
  className: css({
75
87
  width: 420,
76
- backgroundColor: '#000000',
88
+ backgroundColor: tokenSchema.color.scale.black,
77
89
  display: 'flex',
78
90
  flexDirection: 'column',
79
91
  justifyContent: 'space-between',
@@ -117,7 +129,7 @@ function InitPage$1({
117
129
  className: css({
118
130
  fontSize: 15,
119
131
  fontWeight: 600,
120
- color: '#ffffff',
132
+ color: tokenSchema.color.foreground.onEmphasis,
121
133
  letterSpacing: '-0.03em',
122
134
  lineHeight: 1
123
135
  }),
@@ -129,7 +141,7 @@ function InitPage$1({
129
141
  margin: '0 0 16px',
130
142
  fontSize: 34,
131
143
  fontWeight: 700,
132
- color: '#ffffff',
144
+ color: tokenSchema.color.foreground.onEmphasis,
133
145
  letterSpacing: '-0.04em',
134
146
  lineHeight: 1.15
135
147
  }),
@@ -138,7 +150,7 @@ function InitPage$1({
138
150
  className: css({
139
151
  margin: 0,
140
152
  fontSize: 13.5,
141
- color: 'rgba(255,255,255,0.38)',
153
+ color: tokenSchema.color.foreground.inverseSecondary,
142
154
  lineHeight: 1.65
143
155
  }),
144
156
  children: ["Create your first admin account to", /*#__PURE__*/jsx("br", {}), "get started with Nixxie CMS."]
@@ -147,7 +159,7 @@ function InitPage$1({
147
159
  className: css({
148
160
  margin: 0,
149
161
  fontSize: 10.5,
150
- color: 'rgba(255,255,255,0.18)',
162
+ color: tokenSchema.color.foreground.inverseSecondary,
151
163
  letterSpacing: '0.06em',
152
164
  textTransform: 'uppercase'
153
165
  }),
@@ -156,7 +168,7 @@ function InitPage$1({
156
168
  }), /*#__PURE__*/jsx("div", {
157
169
  className: css({
158
170
  flex: 1,
159
- backgroundColor: '#ffffff',
171
+ backgroundColor: tokenSchema.color.background.canvas,
160
172
  display: 'flex',
161
173
  alignItems: 'center',
162
174
  justifyContent: 'center',
@@ -178,7 +190,7 @@ function InitPage$1({
178
190
  width: 36,
179
191
  height: 36,
180
192
  borderRadius: 8,
181
- backgroundColor: '#000000',
193
+ backgroundColor: tokenSchema.color.scale.black,
182
194
  marginBottom: 32
183
195
  }),
184
196
  children: /*#__PURE__*/jsx("svg", {
@@ -199,7 +211,7 @@ function InitPage$1({
199
211
  margin: '0 0 6px',
200
212
  fontSize: 23,
201
213
  fontWeight: 700,
202
- color: '#0a0a0a',
214
+ color: tokenSchema.color.foreground.neutralEmphasis,
203
215
  letterSpacing: '-0.03em',
204
216
  lineHeight: 1.2
205
217
  }),
@@ -208,12 +220,18 @@ function InitPage$1({
208
220
  className: css({
209
221
  margin: '0 0 28px',
210
222
  fontSize: 13.5,
211
- color: '#8a8a8a',
223
+ color: tokenSchema.color.foreground.neutralSecondary,
212
224
  lineHeight: 1.5
213
225
  }),
214
226
  children: "Set up your admin account to start using Nixxie CMS."
215
- }), /*#__PURE__*/jsx(GraphQLErrorNotice, {
216
- errors: [error]
227
+ }), /*#__PURE__*/jsx("div", {
228
+ ref: errorRef,
229
+ tabIndex: -1,
230
+ role: "alert",
231
+ "aria-live": "assertive",
232
+ children: /*#__PURE__*/jsx(GraphQLErrorNotice, {
233
+ errors: [error]
234
+ })
217
235
  }), /*#__PURE__*/jsxs("form", {
218
236
  onSubmit: onSubmit,
219
237
  className: css({
@@ -233,8 +251,8 @@ function InitPage$1({
233
251
  justifyContent: 'center',
234
252
  paddingInline: 20,
235
253
  paddingBlock: 11,
236
- backgroundColor: '#000000',
237
- color: '#ffffff',
254
+ backgroundColor: tokenSchema.color.scale.black,
255
+ color: tokenSchema.color.foreground.onEmphasis,
238
256
  borderRadius: 7,
239
257
  fontSize: 14,
240
258
  fontWeight: 600,
@@ -249,7 +267,7 @@ function InitPage$1({
249
267
  backgroundColor: '#1a1a1a'
250
268
  },
251
269
  '&:focus-visible': {
252
- outline: '2px solid #000',
270
+ outline: `2px solid ${tokenSchema.color.scale.black}`,
253
271
  outlineOffset: 3,
254
272
  borderRadius: 7
255
273
  }
@@ -28,7 +28,7 @@ function SigninPage$1({
28
28
  secretField,
29
29
  authGqlNames
30
30
  }) {
31
- var _data$authenticate, _data$authenticate2;
31
+ var _data$authenticate, _data$authenticate2, _data$authenticate3;
32
32
  const router$1 = router.useRouter();
33
33
  const redirect = useFromRedirect.useRedirect();
34
34
  const [state, setState] = react.useState({
@@ -75,11 +75,24 @@ function SigninPage$1({
75
75
  router$1.push(redirect);
76
76
  }
77
77
  } catch (e) {
78
- console.error(e);
78
+ if (process.env.NODE_ENV !== 'production') console.error(e);
79
79
  return;
80
80
  }
81
81
  };
82
82
  const pending = loading || (data === null || data === void 0 || (_data$authenticate = data.authenticate) === null || _data$authenticate === void 0 ? void 0 : _data$authenticate.__typename) === successTypename;
83
+ const didFail = !!error || (data === null || data === void 0 || (_data$authenticate2 = data.authenticate) === null || _data$authenticate2 === void 0 ? void 0 : _data$authenticate2.__typename) === failureTypename;
84
+
85
+ // Announce and focus the error region when authentication fails.
86
+ const errorRef = react.useRef(null);
87
+ react.useEffect(() => {
88
+ if (!didFail) return;
89
+ try {
90
+ var _errorRef$current;
91
+ (_errorRef$current = errorRef.current) === null || _errorRef$current === void 0 || _errorRef$current.focus();
92
+ } catch {
93
+ // focus is best-effort; ignore environments where it isn't available
94
+ }
95
+ }, [didFail]);
83
96
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
84
97
  children: [/*#__PURE__*/jsxRuntime.jsx(NextHead__default["default"], {
85
98
  children: /*#__PURE__*/jsxRuntime.jsx("title", {
@@ -94,7 +107,7 @@ function SigninPage$1({
94
107
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
95
108
  className: style.css({
96
109
  width: 420,
97
- backgroundColor: '#000000',
110
+ backgroundColor: style.tokenSchema.color.scale.black,
98
111
  display: 'flex',
99
112
  flexDirection: 'column',
100
113
  justifyContent: 'space-between',
@@ -138,7 +151,7 @@ function SigninPage$1({
138
151
  className: style.css({
139
152
  fontSize: 15,
140
153
  fontWeight: 600,
141
- color: '#ffffff',
154
+ color: style.tokenSchema.color.foreground.onEmphasis,
142
155
  letterSpacing: '-0.03em',
143
156
  lineHeight: 1
144
157
  }),
@@ -150,7 +163,7 @@ function SigninPage$1({
150
163
  margin: '0 0 16px',
151
164
  fontSize: 34,
152
165
  fontWeight: 700,
153
- color: '#ffffff',
166
+ color: style.tokenSchema.color.foreground.onEmphasis,
154
167
  letterSpacing: '-0.04em',
155
168
  lineHeight: 1.15
156
169
  }),
@@ -159,7 +172,7 @@ function SigninPage$1({
159
172
  className: style.css({
160
173
  margin: 0,
161
174
  fontSize: 13.5,
162
- color: 'rgba(255,255,255,0.38)',
175
+ color: style.tokenSchema.color.foreground.inverseSecondary,
163
176
  lineHeight: 1.65
164
177
  }),
165
178
  children: ["A professional CMS built for modern", /*#__PURE__*/jsxRuntime.jsx("br", {}), "teams who care about craft."]
@@ -168,7 +181,7 @@ function SigninPage$1({
168
181
  className: style.css({
169
182
  margin: 0,
170
183
  fontSize: 10.5,
171
- color: 'rgba(255,255,255,0.18)',
184
+ color: style.tokenSchema.color.foreground.inverseSecondary,
172
185
  letterSpacing: '0.06em',
173
186
  textTransform: 'uppercase'
174
187
  }),
@@ -177,7 +190,7 @@ function SigninPage$1({
177
190
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
178
191
  className: style.css({
179
192
  flex: 1,
180
- backgroundColor: '#ffffff',
193
+ backgroundColor: style.tokenSchema.color.background.canvas,
181
194
  display: 'flex',
182
195
  alignItems: 'center',
183
196
  justifyContent: 'center',
@@ -199,7 +212,7 @@ function SigninPage$1({
199
212
  width: 36,
200
213
  height: 36,
201
214
  borderRadius: 8,
202
- backgroundColor: '#000000',
215
+ backgroundColor: style.tokenSchema.color.scale.black,
203
216
  marginBottom: 32
204
217
  }),
205
218
  children: /*#__PURE__*/jsxRuntime.jsx("svg", {
@@ -220,7 +233,7 @@ function SigninPage$1({
220
233
  margin: '0 0 6px',
221
234
  fontSize: 23,
222
235
  fontWeight: 700,
223
- color: '#0a0a0a',
236
+ color: style.tokenSchema.color.foreground.neutralEmphasis,
224
237
  letterSpacing: '-0.03em',
225
238
  lineHeight: 1.2
226
239
  }),
@@ -229,19 +242,25 @@ function SigninPage$1({
229
242
  className: style.css({
230
243
  margin: '0 0 28px',
231
244
  fontSize: 13.5,
232
- color: '#8a8a8a',
245
+ color: style.tokenSchema.color.foreground.neutralSecondary,
233
246
  lineHeight: 1.5
234
247
  }),
235
248
  children: "Welcome back. Enter your credentials to continue."
236
- }), /*#__PURE__*/jsxRuntime.jsx(components.GraphQLErrorNotice, {
237
- errors: [error]
238
- }), (data === null || data === void 0 || (_data$authenticate2 = data.authenticate) === null || _data$authenticate2 === void 0 ? void 0 : _data$authenticate2.__typename) === failureTypename && /*#__PURE__*/jsxRuntime.jsx(notice.Notice, {
239
- tone: "critical",
240
- children: /*#__PURE__*/jsxRuntime.jsx(slots.Content, {
241
- children: /*#__PURE__*/jsxRuntime.jsx(typography.Text, {
242
- children: data === null || data === void 0 ? void 0 : data.authenticate.message
249
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
250
+ ref: errorRef,
251
+ tabIndex: -1,
252
+ role: "alert",
253
+ "aria-live": "assertive",
254
+ children: [/*#__PURE__*/jsxRuntime.jsx(components.GraphQLErrorNotice, {
255
+ errors: [error]
256
+ }), (data === null || data === void 0 || (_data$authenticate3 = data.authenticate) === null || _data$authenticate3 === void 0 ? void 0 : _data$authenticate3.__typename) === failureTypename && /*#__PURE__*/jsxRuntime.jsx(notice.Notice, {
257
+ tone: "critical",
258
+ children: /*#__PURE__*/jsxRuntime.jsx(slots.Content, {
259
+ children: /*#__PURE__*/jsxRuntime.jsx(typography.Text, {
260
+ children: data === null || data === void 0 ? void 0 : data.authenticate.message
261
+ })
243
262
  })
244
- })
263
+ })]
245
264
  }), /*#__PURE__*/jsxRuntime.jsxs("form", {
246
265
  onSubmit: onSubmit,
247
266
  className: style.css({
@@ -250,8 +269,12 @@ function SigninPage$1({
250
269
  gap: 16
251
270
  }),
252
271
  children: [/*#__PURE__*/jsxRuntime.jsx(textField.TextField, {
272
+ autoComplete: "username",
253
273
  autoFocus: true,
254
- id: "identity",
274
+ id: "identity"
275
+ // @ts-expect-error — valid prop, types need to be fixed in "@keystar/ui"
276
+ ,
277
+ isInvalid: didFail,
255
278
  isRequired: true,
256
279
  label: capitalizeFirstLetter(identityField),
257
280
  name: "identity",
@@ -261,11 +284,13 @@ function SigninPage$1({
261
284
  }),
262
285
  value: state.identity
263
286
  }), /*#__PURE__*/jsxRuntime.jsx(passwordField.PasswordField, {
264
- id: "password",
265
- isRequired: true,
266
- label: capitalizeFirstLetter(secretField)
267
- // @ts-expect-error — valid prop, types need to be fixed in "@keystar/ui"
287
+ autoComplete: "current-password",
288
+ id: "password"
289
+ // @ts-expect-error — valid props (isInvalid, name), types need to be fixed in "@keystar/ui"
268
290
  ,
291
+ isInvalid: didFail,
292
+ isRequired: true,
293
+ label: capitalizeFirstLetter(secretField),
269
294
  name: "password",
270
295
  onChange: v => setState({
271
296
  ...state,
@@ -283,8 +308,8 @@ function SigninPage$1({
283
308
  justifyContent: 'center',
284
309
  paddingInline: 20,
285
310
  paddingBlock: 11,
286
- backgroundColor: '#000000',
287
- color: '#ffffff',
311
+ backgroundColor: style.tokenSchema.color.scale.black,
312
+ color: style.tokenSchema.color.foreground.onEmphasis,
288
313
  borderRadius: 7,
289
314
  fontSize: 14,
290
315
  fontWeight: 600,
@@ -299,7 +324,7 @@ function SigninPage$1({
299
324
  backgroundColor: '#1a1a1a'
300
325
  },
301
326
  '&:focus-visible': {
302
- outline: '2px solid #000',
327
+ outline: `2px solid ${style.tokenSchema.color.scale.black}`,
303
328
  outlineOffset: 3,
304
329
  borderRadius: 7
305
330
  }
@@ -1,9 +1,9 @@
1
1
  import NextHead from 'next/head';
2
- import { useState } from 'react';
2
+ import { useState, useRef, useEffect } from 'react';
3
3
  import { Notice } from '@keystar/ui/notice';
4
4
  import { PasswordField } from '@keystar/ui/password-field';
5
5
  import { Content } from '@keystar/ui/slots';
6
- import { css } from '@keystar/ui/style';
6
+ import { css, tokenSchema } from '@keystar/ui/style';
7
7
  import { TextField } from '@keystar/ui/text-field';
8
8
  import { Text } from '@keystar/ui/typography';
9
9
  import { useMutation, gql } from '@nixxie-cms/core/admin-ui/apollo';
@@ -20,7 +20,7 @@ function SigninPage$1({
20
20
  secretField,
21
21
  authGqlNames
22
22
  }) {
23
- var _data$authenticate, _data$authenticate2;
23
+ var _data$authenticate, _data$authenticate2, _data$authenticate3;
24
24
  const router = useRouter();
25
25
  const redirect = useRedirect();
26
26
  const [state, setState] = useState({
@@ -67,11 +67,24 @@ function SigninPage$1({
67
67
  router.push(redirect);
68
68
  }
69
69
  } catch (e) {
70
- console.error(e);
70
+ if (process.env.NODE_ENV !== 'production') console.error(e);
71
71
  return;
72
72
  }
73
73
  };
74
74
  const pending = loading || (data === null || data === void 0 || (_data$authenticate = data.authenticate) === null || _data$authenticate === void 0 ? void 0 : _data$authenticate.__typename) === successTypename;
75
+ const didFail = !!error || (data === null || data === void 0 || (_data$authenticate2 = data.authenticate) === null || _data$authenticate2 === void 0 ? void 0 : _data$authenticate2.__typename) === failureTypename;
76
+
77
+ // Announce and focus the error region when authentication fails.
78
+ const errorRef = useRef(null);
79
+ useEffect(() => {
80
+ if (!didFail) return;
81
+ try {
82
+ var _errorRef$current;
83
+ (_errorRef$current = errorRef.current) === null || _errorRef$current === void 0 || _errorRef$current.focus();
84
+ } catch {
85
+ // focus is best-effort; ignore environments where it isn't available
86
+ }
87
+ }, [didFail]);
75
88
  return /*#__PURE__*/jsxs(Fragment, {
76
89
  children: [/*#__PURE__*/jsx(NextHead, {
77
90
  children: /*#__PURE__*/jsx("title", {
@@ -86,7 +99,7 @@ function SigninPage$1({
86
99
  children: [/*#__PURE__*/jsxs("div", {
87
100
  className: css({
88
101
  width: 420,
89
- backgroundColor: '#000000',
102
+ backgroundColor: tokenSchema.color.scale.black,
90
103
  display: 'flex',
91
104
  flexDirection: 'column',
92
105
  justifyContent: 'space-between',
@@ -130,7 +143,7 @@ function SigninPage$1({
130
143
  className: css({
131
144
  fontSize: 15,
132
145
  fontWeight: 600,
133
- color: '#ffffff',
146
+ color: tokenSchema.color.foreground.onEmphasis,
134
147
  letterSpacing: '-0.03em',
135
148
  lineHeight: 1
136
149
  }),
@@ -142,7 +155,7 @@ function SigninPage$1({
142
155
  margin: '0 0 16px',
143
156
  fontSize: 34,
144
157
  fontWeight: 700,
145
- color: '#ffffff',
158
+ color: tokenSchema.color.foreground.onEmphasis,
146
159
  letterSpacing: '-0.04em',
147
160
  lineHeight: 1.15
148
161
  }),
@@ -151,7 +164,7 @@ function SigninPage$1({
151
164
  className: css({
152
165
  margin: 0,
153
166
  fontSize: 13.5,
154
- color: 'rgba(255,255,255,0.38)',
167
+ color: tokenSchema.color.foreground.inverseSecondary,
155
168
  lineHeight: 1.65
156
169
  }),
157
170
  children: ["A professional CMS built for modern", /*#__PURE__*/jsx("br", {}), "teams who care about craft."]
@@ -160,7 +173,7 @@ function SigninPage$1({
160
173
  className: css({
161
174
  margin: 0,
162
175
  fontSize: 10.5,
163
- color: 'rgba(255,255,255,0.18)',
176
+ color: tokenSchema.color.foreground.inverseSecondary,
164
177
  letterSpacing: '0.06em',
165
178
  textTransform: 'uppercase'
166
179
  }),
@@ -169,7 +182,7 @@ function SigninPage$1({
169
182
  }), /*#__PURE__*/jsx("div", {
170
183
  className: css({
171
184
  flex: 1,
172
- backgroundColor: '#ffffff',
185
+ backgroundColor: tokenSchema.color.background.canvas,
173
186
  display: 'flex',
174
187
  alignItems: 'center',
175
188
  justifyContent: 'center',
@@ -191,7 +204,7 @@ function SigninPage$1({
191
204
  width: 36,
192
205
  height: 36,
193
206
  borderRadius: 8,
194
- backgroundColor: '#000000',
207
+ backgroundColor: tokenSchema.color.scale.black,
195
208
  marginBottom: 32
196
209
  }),
197
210
  children: /*#__PURE__*/jsx("svg", {
@@ -212,7 +225,7 @@ function SigninPage$1({
212
225
  margin: '0 0 6px',
213
226
  fontSize: 23,
214
227
  fontWeight: 700,
215
- color: '#0a0a0a',
228
+ color: tokenSchema.color.foreground.neutralEmphasis,
216
229
  letterSpacing: '-0.03em',
217
230
  lineHeight: 1.2
218
231
  }),
@@ -221,19 +234,25 @@ function SigninPage$1({
221
234
  className: css({
222
235
  margin: '0 0 28px',
223
236
  fontSize: 13.5,
224
- color: '#8a8a8a',
237
+ color: tokenSchema.color.foreground.neutralSecondary,
225
238
  lineHeight: 1.5
226
239
  }),
227
240
  children: "Welcome back. Enter your credentials to continue."
228
- }), /*#__PURE__*/jsx(GraphQLErrorNotice, {
229
- errors: [error]
230
- }), (data === null || data === void 0 || (_data$authenticate2 = data.authenticate) === null || _data$authenticate2 === void 0 ? void 0 : _data$authenticate2.__typename) === failureTypename && /*#__PURE__*/jsx(Notice, {
231
- tone: "critical",
232
- children: /*#__PURE__*/jsx(Content, {
233
- children: /*#__PURE__*/jsx(Text, {
234
- children: data === null || data === void 0 ? void 0 : data.authenticate.message
241
+ }), /*#__PURE__*/jsxs("div", {
242
+ ref: errorRef,
243
+ tabIndex: -1,
244
+ role: "alert",
245
+ "aria-live": "assertive",
246
+ children: [/*#__PURE__*/jsx(GraphQLErrorNotice, {
247
+ errors: [error]
248
+ }), (data === null || data === void 0 || (_data$authenticate3 = data.authenticate) === null || _data$authenticate3 === void 0 ? void 0 : _data$authenticate3.__typename) === failureTypename && /*#__PURE__*/jsx(Notice, {
249
+ tone: "critical",
250
+ children: /*#__PURE__*/jsx(Content, {
251
+ children: /*#__PURE__*/jsx(Text, {
252
+ children: data === null || data === void 0 ? void 0 : data.authenticate.message
253
+ })
235
254
  })
236
- })
255
+ })]
237
256
  }), /*#__PURE__*/jsxs("form", {
238
257
  onSubmit: onSubmit,
239
258
  className: css({
@@ -242,8 +261,12 @@ function SigninPage$1({
242
261
  gap: 16
243
262
  }),
244
263
  children: [/*#__PURE__*/jsx(TextField, {
264
+ autoComplete: "username",
245
265
  autoFocus: true,
246
- id: "identity",
266
+ id: "identity"
267
+ // @ts-expect-error — valid prop, types need to be fixed in "@keystar/ui"
268
+ ,
269
+ isInvalid: didFail,
247
270
  isRequired: true,
248
271
  label: capitalizeFirstLetter(identityField),
249
272
  name: "identity",
@@ -253,11 +276,13 @@ function SigninPage$1({
253
276
  }),
254
277
  value: state.identity
255
278
  }), /*#__PURE__*/jsx(PasswordField, {
256
- id: "password",
257
- isRequired: true,
258
- label: capitalizeFirstLetter(secretField)
259
- // @ts-expect-error — valid prop, types need to be fixed in "@keystar/ui"
279
+ autoComplete: "current-password",
280
+ id: "password"
281
+ // @ts-expect-error — valid props (isInvalid, name), types need to be fixed in "@keystar/ui"
260
282
  ,
283
+ isInvalid: didFail,
284
+ isRequired: true,
285
+ label: capitalizeFirstLetter(secretField),
261
286
  name: "password",
262
287
  onChange: v => setState({
263
288
  ...state,
@@ -275,8 +300,8 @@ function SigninPage$1({
275
300
  justifyContent: 'center',
276
301
  paddingInline: 20,
277
302
  paddingBlock: 11,
278
- backgroundColor: '#000000',
279
- color: '#ffffff',
303
+ backgroundColor: tokenSchema.color.scale.black,
304
+ color: tokenSchema.color.foreground.onEmphasis,
280
305
  borderRadius: 7,
281
306
  fontSize: 14,
282
307
  fontWeight: 600,
@@ -291,7 +316,7 @@ function SigninPage$1({
291
316
  backgroundColor: '#1a1a1a'
292
317
  },
293
318
  '&:focus-visible': {
294
- outline: '2px solid #000',
319
+ outline: `2px solid ${tokenSchema.color.scale.black}`,
295
320
  outlineOffset: 3,
296
321
  borderRadius: 7
297
322
  }
@@ -1,6 +1,7 @@
1
1
  import NextHead from 'next/head'
2
+ import { useEffect, useRef } from 'react'
2
3
 
3
- import { css } from '@keystar/ui/style'
4
+ import { css, tokenSchema } from '@keystar/ui/style'
4
5
 
5
6
  import { gql, type TypedDocumentNode, useMutation } from '@nixxie-cms/core/admin-ui/apollo'
6
7
  import { GraphQLErrorNotice } from '@nixxie-cms/core/admin-ui/components'
@@ -61,7 +62,7 @@ function InitPage({
61
62
  },
62
63
  })
63
64
  } catch (e) {
64
- console.error(e)
65
+ if (process.env.NODE_ENV !== 'production') console.error(e)
65
66
  return
66
67
  }
67
68
 
@@ -70,6 +71,17 @@ function InitPage({
70
71
 
71
72
  const pending = loading || data?.authenticate?.__typename === successTypename
72
73
 
74
+ // Announce and focus the error region when item creation fails.
75
+ const errorRef = useRef<HTMLDivElement>(null)
76
+ useEffect(() => {
77
+ if (!error) return
78
+ try {
79
+ errorRef.current?.focus()
80
+ } catch {
81
+ // focus is best-effort; ignore environments where it isn't available
82
+ }
83
+ }, [error])
84
+
73
85
  return (
74
86
  <>
75
87
  <NextHead>
@@ -87,7 +99,7 @@ function InitPage({
87
99
  <div
88
100
  className={css({
89
101
  width: 420,
90
- backgroundColor: '#000000',
102
+ backgroundColor: tokenSchema.color.scale.black,
91
103
  display: 'flex',
92
104
  flexDirection: 'column',
93
105
  justifyContent: 'space-between',
@@ -124,7 +136,7 @@ function InitPage({
124
136
  className={css({
125
137
  fontSize: 15,
126
138
  fontWeight: 600,
127
- color: '#ffffff',
139
+ color: tokenSchema.color.foreground.onEmphasis,
128
140
  letterSpacing: '-0.03em',
129
141
  lineHeight: 1,
130
142
  })}
@@ -140,7 +152,7 @@ function InitPage({
140
152
  margin: '0 0 16px',
141
153
  fontSize: 34,
142
154
  fontWeight: 700,
143
- color: '#ffffff',
155
+ color: tokenSchema.color.foreground.onEmphasis,
144
156
  letterSpacing: '-0.04em',
145
157
  lineHeight: 1.15,
146
158
  })}
@@ -153,7 +165,7 @@ function InitPage({
153
165
  className={css({
154
166
  margin: 0,
155
167
  fontSize: 13.5,
156
- color: 'rgba(255,255,255,0.38)',
168
+ color: tokenSchema.color.foreground.inverseSecondary,
157
169
  lineHeight: 1.65,
158
170
  })}
159
171
  >
@@ -168,7 +180,7 @@ function InitPage({
168
180
  className={css({
169
181
  margin: 0,
170
182
  fontSize: 10.5,
171
- color: 'rgba(255,255,255,0.18)',
183
+ color: tokenSchema.color.foreground.inverseSecondary,
172
184
  letterSpacing: '0.06em',
173
185
  textTransform: 'uppercase',
174
186
  })}
@@ -181,7 +193,7 @@ function InitPage({
181
193
  <div
182
194
  className={css({
183
195
  flex: 1,
184
- backgroundColor: '#ffffff',
196
+ backgroundColor: tokenSchema.color.background.canvas,
185
197
  display: 'flex',
186
198
  alignItems: 'center',
187
199
  justifyContent: 'center',
@@ -199,7 +211,7 @@ function InitPage({
199
211
  width: 36,
200
212
  height: 36,
201
213
  borderRadius: 8,
202
- backgroundColor: '#000000',
214
+ backgroundColor: tokenSchema.color.scale.black,
203
215
  marginBottom: 32,
204
216
  })}
205
217
  >
@@ -219,7 +231,7 @@ function InitPage({
219
231
  margin: '0 0 6px',
220
232
  fontSize: 23,
221
233
  fontWeight: 700,
222
- color: '#0a0a0a',
234
+ color: tokenSchema.color.foreground.neutralEmphasis,
223
235
  letterSpacing: '-0.03em',
224
236
  lineHeight: 1.2,
225
237
  })}
@@ -230,7 +242,7 @@ function InitPage({
230
242
  className={css({
231
243
  margin: '0 0 28px',
232
244
  fontSize: 13.5,
233
- color: '#8a8a8a',
245
+ color: tokenSchema.color.foreground.neutralSecondary,
234
246
  lineHeight: 1.5,
235
247
  })}
236
248
  >
@@ -238,7 +250,9 @@ function InitPage({
238
250
  </p>
239
251
 
240
252
  {/* Errors */}
241
- <GraphQLErrorNotice errors={[error]} />
253
+ <div ref={errorRef} tabIndex={-1} role="alert" aria-live="assertive">
254
+ <GraphQLErrorNotice errors={[error]} />
255
+ </div>
242
256
 
243
257
  {/* Form */}
244
258
  <form
@@ -261,8 +275,8 @@ function InitPage({
261
275
  justifyContent: 'center',
262
276
  paddingInline: 20,
263
277
  paddingBlock: 11,
264
- backgroundColor: '#000000',
265
- color: '#ffffff',
278
+ backgroundColor: tokenSchema.color.scale.black,
279
+ color: tokenSchema.color.foreground.onEmphasis,
266
280
  borderRadius: 7,
267
281
  fontSize: 14,
268
282
  fontWeight: 600,
@@ -275,7 +289,7 @@ function InitPage({
275
289
  fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
276
290
  '&:hover:not(:disabled)': { backgroundColor: '#1a1a1a' },
277
291
  '&:focus-visible': {
278
- outline: '2px solid #000',
292
+ outline: `2px solid ${tokenSchema.color.scale.black}`,
279
293
  outlineOffset: 3,
280
294
  borderRadius: 7,
281
295
  },
@@ -1,10 +1,10 @@
1
1
  import NextHead from 'next/head'
2
- import { useState } from 'react'
2
+ import { useEffect, useRef, useState } from 'react'
3
3
 
4
4
  import { Notice } from '@keystar/ui/notice'
5
5
  import { PasswordField } from '@keystar/ui/password-field'
6
6
  import { Content } from '@keystar/ui/slots'
7
- import { css } from '@keystar/ui/style'
7
+ import { css, tokenSchema } from '@keystar/ui/style'
8
8
  import { TextField } from '@keystar/ui/text-field'
9
9
  import { Text } from '@keystar/ui/typography'
10
10
 
@@ -71,12 +71,24 @@ function SigninPage({
71
71
  router.push(redirect)
72
72
  }
73
73
  } catch (e) {
74
- console.error(e)
74
+ if (process.env.NODE_ENV !== 'production') console.error(e)
75
75
  return
76
76
  }
77
77
  }
78
78
 
79
79
  const pending = loading || data?.authenticate?.__typename === successTypename
80
+ const didFail = !!error || data?.authenticate?.__typename === failureTypename
81
+
82
+ // Announce and focus the error region when authentication fails.
83
+ const errorRef = useRef<HTMLDivElement>(null)
84
+ useEffect(() => {
85
+ if (!didFail) return
86
+ try {
87
+ errorRef.current?.focus()
88
+ } catch {
89
+ // focus is best-effort; ignore environments where it isn't available
90
+ }
91
+ }, [didFail])
80
92
 
81
93
  return (
82
94
  <>
@@ -95,7 +107,7 @@ function SigninPage({
95
107
  <div
96
108
  className={css({
97
109
  width: 420,
98
- backgroundColor: '#000000',
110
+ backgroundColor: tokenSchema.color.scale.black,
99
111
  display: 'flex',
100
112
  flexDirection: 'column',
101
113
  justifyContent: 'space-between',
@@ -132,7 +144,7 @@ function SigninPage({
132
144
  className={css({
133
145
  fontSize: 15,
134
146
  fontWeight: 600,
135
- color: '#ffffff',
147
+ color: tokenSchema.color.foreground.onEmphasis,
136
148
  letterSpacing: '-0.03em',
137
149
  lineHeight: 1,
138
150
  })}
@@ -148,7 +160,7 @@ function SigninPage({
148
160
  margin: '0 0 16px',
149
161
  fontSize: 34,
150
162
  fontWeight: 700,
151
- color: '#ffffff',
163
+ color: tokenSchema.color.foreground.onEmphasis,
152
164
  letterSpacing: '-0.04em',
153
165
  lineHeight: 1.15,
154
166
  })}
@@ -163,7 +175,7 @@ function SigninPage({
163
175
  className={css({
164
176
  margin: 0,
165
177
  fontSize: 13.5,
166
- color: 'rgba(255,255,255,0.38)',
178
+ color: tokenSchema.color.foreground.inverseSecondary,
167
179
  lineHeight: 1.65,
168
180
  })}
169
181
  >
@@ -178,7 +190,7 @@ function SigninPage({
178
190
  className={css({
179
191
  margin: 0,
180
192
  fontSize: 10.5,
181
- color: 'rgba(255,255,255,0.18)',
193
+ color: tokenSchema.color.foreground.inverseSecondary,
182
194
  letterSpacing: '0.06em',
183
195
  textTransform: 'uppercase',
184
196
  })}
@@ -191,7 +203,7 @@ function SigninPage({
191
203
  <div
192
204
  className={css({
193
205
  flex: 1,
194
- backgroundColor: '#ffffff',
206
+ backgroundColor: tokenSchema.color.background.canvas,
195
207
  display: 'flex',
196
208
  alignItems: 'center',
197
209
  justifyContent: 'center',
@@ -209,7 +221,7 @@ function SigninPage({
209
221
  width: 36,
210
222
  height: 36,
211
223
  borderRadius: 8,
212
- backgroundColor: '#000000',
224
+ backgroundColor: tokenSchema.color.scale.black,
213
225
  marginBottom: 32,
214
226
  })}
215
227
  >
@@ -229,7 +241,7 @@ function SigninPage({
229
241
  margin: '0 0 6px',
230
242
  fontSize: 23,
231
243
  fontWeight: 700,
232
- color: '#0a0a0a',
244
+ color: tokenSchema.color.foreground.neutralEmphasis,
233
245
  letterSpacing: '-0.03em',
234
246
  lineHeight: 1.2,
235
247
  })}
@@ -240,7 +252,7 @@ function SigninPage({
240
252
  className={css({
241
253
  margin: '0 0 28px',
242
254
  fontSize: 13.5,
243
- color: '#8a8a8a',
255
+ color: tokenSchema.color.foreground.neutralSecondary,
244
256
  lineHeight: 1.5,
245
257
  })}
246
258
  >
@@ -248,14 +260,16 @@ function SigninPage({
248
260
  </p>
249
261
 
250
262
  {/* Errors */}
251
- <GraphQLErrorNotice errors={[error]} />
252
- {data?.authenticate?.__typename === failureTypename && (
253
- <Notice tone="critical">
254
- <Content>
255
- <Text>{data?.authenticate.message}</Text>
256
- </Content>
257
- </Notice>
258
- )}
263
+ <div ref={errorRef} tabIndex={-1} role="alert" aria-live="assertive">
264
+ <GraphQLErrorNotice errors={[error]} />
265
+ {data?.authenticate?.__typename === failureTypename && (
266
+ <Notice tone="critical">
267
+ <Content>
268
+ <Text>{data?.authenticate.message}</Text>
269
+ </Content>
270
+ </Notice>
271
+ )}
272
+ </div>
259
273
 
260
274
  {/* Form */}
261
275
  <form
@@ -267,8 +281,11 @@ function SigninPage({
267
281
  })}
268
282
  >
269
283
  <TextField
284
+ autoComplete="username"
270
285
  autoFocus
271
286
  id="identity"
287
+ // @ts-expect-error — valid prop, types need to be fixed in "@keystar/ui"
288
+ isInvalid={didFail}
272
289
  isRequired
273
290
  label={capitalizeFirstLetter(identityField)}
274
291
  name="identity"
@@ -276,10 +293,12 @@ function SigninPage({
276
293
  value={state.identity}
277
294
  />
278
295
  <PasswordField
296
+ autoComplete="current-password"
279
297
  id="password"
298
+ // @ts-expect-error — valid props (isInvalid, name), types need to be fixed in "@keystar/ui"
299
+ isInvalid={didFail}
280
300
  isRequired
281
301
  label={capitalizeFirstLetter(secretField)}
282
- // @ts-expect-error — valid prop, types need to be fixed in "@keystar/ui"
283
302
  name="password"
284
303
  onChange={v => setState({ ...state, secret: v })}
285
304
  type="password"
@@ -296,8 +315,8 @@ function SigninPage({
296
315
  justifyContent: 'center',
297
316
  paddingInline: 20,
298
317
  paddingBlock: 11,
299
- backgroundColor: '#000000',
300
- color: '#ffffff',
318
+ backgroundColor: tokenSchema.color.scale.black,
319
+ color: tokenSchema.color.foreground.onEmphasis,
301
320
  borderRadius: 7,
302
321
  fontSize: 14,
303
322
  fontWeight: 600,
@@ -310,7 +329,7 @@ function SigninPage({
310
329
  fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
311
330
  '&:hover:not(:disabled)': { backgroundColor: '#1a1a1a' },
312
331
  '&:focus-visible': {
313
- outline: '2px solid #000',
332
+ outline: `2px solid ${tokenSchema.color.scale.black}`,
314
333
  outlineOffset: 3,
315
334
  borderRadius: 7,
316
335
  },