Skip to content

Commit b966d37

Browse files
authored
Merge pull request #884 from jsonwebtoken/update-token-encoder-picker
Update token encoder picker
2 parents 92148a7 + 1f0c9a2 commit b966d37

File tree

11 files changed

+223
-71
lines changed

11 files changed

+223
-71
lines changed

src/features/common/components/card/card.component.tsx

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import React, { PropsWithChildren, useId } from "react";
22
import styles from "./card.module.scss";
33
import { clsx } from "clsx";
4-
import { getLocalizedSecondaryFont, MonoFont } from "@/libs/theme/fonts";
4+
import { getLocalizedSecondaryFont } from "@/libs/theme/fonts";
55
import { CardMessageComponent } from "@/features/common/components/card-message/card-message.component";
66
import { HeaderIcon } from "../icons/header/header-icon";
77
import { CheckIcon } from "../icons/check/check-icon";
8+
import { EncodingFormatToggleSwitchComponent } from "@/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch";
9+
import { useDecoderStore } from "@/features/decoder/services/decoder.store";
10+
import { isHmacAlg } from "../../services/jwt.service";
11+
import { TokenDecoderKeyFormatPickerComponent } from "@/features/decoder/components/token-decoder-key-format-picker.component";
812

913
export interface CardComponentProps extends PropsWithChildren {
1014
id: string;
@@ -150,10 +154,10 @@ export const CardComponent: React.FC<CardComponentProps> = (props) => {
150154
>
151155
{messages.success.map((line, index) => {
152156
return (
153-
<>
154-
<CheckIcon />
155-
<CardMessageComponent key={index}>{line}</CardMessageComponent>
156-
</>
157+
<div key={index} style={{ display: "flex" }}>
158+
<CheckIcon />
159+
<CardMessageComponent key={index}>{line}</CardMessageComponent>
160+
</div>
157161
);
158162
})}
159163
</div>
@@ -197,31 +201,40 @@ export const CardWithHeadlineComponent: React.FC<
197201
CardWithHeadlineComponentProps
198202
> = ({ sectionHeadline, languageCode, ...props }) => {
199203
const regionId = useId();
204+
const alg$ = useDecoderStore((state) => state.alg);
200205

201206
return (
202207
<div role="region" aria-labelledby={regionId}>
203208
{sectionHeadline && (
204-
<>
205-
<h3
206-
id={regionId}
207-
className={clsx(
208-
styles.cardHeadline__title,
209-
getLocalizedSecondaryFont(languageCode)
210-
)}
211-
>
212-
{sectionHeadline.title}
213-
{sectionHeadline.titleTag && (
214-
<span className={styles.cardHeadline__titleTag}>
215-
{sectionHeadline.titleTag}
216-
</span>
209+
<div className={styles.title__container}>
210+
<div>
211+
<h3
212+
id={regionId}
213+
className={clsx(
214+
styles.cardHeadline__title,
215+
getLocalizedSecondaryFont(languageCode)
216+
)}
217+
>
218+
{sectionHeadline.title}
219+
{sectionHeadline.titleTag && (
220+
<span className={styles.cardHeadline__titleTag}>
221+
{sectionHeadline.titleTag}
222+
</span>
223+
)}
224+
</h3>
225+
{sectionHeadline.description && (
226+
<p className={styles.cardHeadline__description}>
227+
{sectionHeadline.description}
228+
</p>
217229
)}
218-
</h3>
219-
{sectionHeadline.description && (
220-
<p className={styles.cardHeadline__description}>
221-
{sectionHeadline.description}
222-
</p>
230+
</div>
231+
232+
{isHmacAlg(alg$) ? (
233+
<EncodingFormatToggleSwitchComponent languageCode={languageCode} />
234+
) : (
235+
<TokenDecoderKeyFormatPickerComponent languageCode={languageCode} />
223236
)}
224-
</>
237+
</div>
225238
)}
226239
<CardComponent languageCode={languageCode} {...props} />
227240
</div>

src/features/common/components/card/card.module.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@
5656
}
5757
}
5858

59+
.title__container {
60+
grid-column: 1/-1;
61+
width: 100%;
62+
color: var(--color_fg_bold);
63+
font-size: 1.75rem;
64+
font-weight: 500;
65+
line-height: 1.5;
66+
margin-bottom: .5rem;
67+
display: flex;
68+
justify-content: space-between;
69+
}
70+
5971
.card {
6072
isolation: isolate;
6173
grid-column: span 6;

src/features/common/components/debugger-picker/debugger-picker.component.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ interface DebuggerPickerComponentProps {
4040
GroupBase<DebuggerPickerOptionModel>
4141
>;
4242
isGrouped?: boolean;
43-
selectedOptionCode: DebuggerPickerOptionModel | null;
43+
selectedOptionCode?: DebuggerPickerOptionModel | null;
4444
handleSelection: (
4545
selection: string,
4646
parentLabel?: LibraryFilterLabel
@@ -54,6 +54,7 @@ export const DebuggerPickerComponent: React.FC<
5454
> = ({
5555
label,
5656
options,
57+
selectedOptionCode,
5758
handleSelection,
5859
placeholder,
5960
minWidth,
@@ -93,6 +94,7 @@ export const DebuggerPickerComponent: React.FC<
9394
classNamePrefix={"react-select"}
9495
isSearchable={false}
9596
placeholder={placeholder}
97+
value={selectedOptionCode}
9698
styles={{
9799
control: (base) => ({
98100
...base,

src/features/common/components/debugger-picker/debugger-picker.module.scss

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,17 @@ $picker-list-offset-lg: calc(($picker-list-width-lg - $picker-width-lg) / 2);
3333
}
3434

3535
.picker__label {
36-
display: flex;
37-
align-items: center;
38-
justify-content: center;
39-
padding: 0;
40-
list-style-type: none;
41-
margin: 0;
42-
gap: 0.5rem;
43-
font-size: 0.8125rem;
44-
line-height: 1.3125rem;
45-
letter-spacing: -0.05px;
46-
47-
width: 100%;
48-
49-
height: 100%;
36+
display: flex;
37+
align-items: center;
38+
justify-content: flex-start;
39+
padding: 0;
40+
list-style-type: none;
41+
margin: 0;
42+
gap: .5rem;
43+
font-size: .875rem;
44+
line-height: 1.35;
45+
width: 100%;
46+
height: 100%;
5047

5148
& svg {
5249
stroke: var(--color_fg_bold);
@@ -55,4 +52,5 @@ $picker-list-offset-lg: calc(($picker-list-width-lg - $picker-width-lg) / 2);
5552

5653
.picker__fullName {
5754
display: flex;
55+
font-weight: 600;
5856
}

src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.component.tsx

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
algDictionary,
1616
jwsExampleAlgHeaderParameterValuesDictionary,
1717
} from "@/features/common/values/jws-alg-header-parameter-values.dictionary";
18-
import { useButton } from "@react-aria/button"
18+
import { useButton } from "@react-aria/button";
1919
import { DebuggerPickerOptionModel } from "@/features/common/models/debugger-picker-option.model";
2020

2121
enum PickerStates {
@@ -92,7 +92,6 @@ export const WidgetAlgPickerComponent: React.FC<
9292
setPickerState(PickerStates.IDLE);
9393
};
9494

95-
9695
useEffect(() => {
9796
(async function runEs512Check() {
9897
setCanUseEs512(await isP521Supported());
@@ -107,18 +106,6 @@ export const WidgetAlgPickerComponent: React.FC<
107106
})();
108107
}, []);
109108

110-
/* const noneAlgOptions: DebuggerPickerOptionModel[] = useMemo(() => {
111-
return Object.entries(
112-
jwsExampleAlgHeaderParameterValuesDictionary.unsecured
113-
).map((entry) => {
114-
const [key, value] = entry;
115-
116-
return {
117-
value: key,
118-
label: value.name,
119-
};
120-
});
121-
}, []); */
122109

123110
const symmetricAlgOptions: DebuggerPickerOptionModel[] = useMemo(() => {
124111
return Object.entries(jwsExampleAlgHeaderParameterValuesDictionary.mac).map(
@@ -197,16 +184,17 @@ export const WidgetAlgPickerComponent: React.FC<
197184
{dictionary.exampleAlgPicker.label}
198185
</label>
199186
</div>
200-
<DebuggerPickerComponent
201-
label={null}
202-
data-has-label={label !== null}
203-
languageCode={languageCode}
204-
handleSelection={selectExample}
205-
selectedOptionCode={null}
206-
options={algOptions}
207-
placeholder={dictionary.exampleAlgPicker.defaultValue}
208-
minWidth={null}
209-
/>
187+
<div className={styles.picker__container}>
188+
<DebuggerPickerComponent
189+
label={null}
190+
data-has-label={label !== null}
191+
languageCode={languageCode}
192+
handleSelection={selectExample}
193+
options={algOptions}
194+
placeholder={dictionary.exampleAlgPicker.defaultValue}
195+
minWidth={null}
196+
/>
197+
</div>
210198
</div>
211199
</div>
212200
</div>

src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
font-weight: 600;
6363
}
6464

65+
.picker__container {
66+
height: 2rem;
67+
}
68+
6569
.button {
6670
color: var(--color_fg_on_button);
6771
background-color: var(--color_bg_button);
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
@use "@/libs/theme/styles/variables" as *;
2+
3+
.container {
4+
display: flex;
5+
align-items: center;
6+
gap: .5rem;
7+
}
8+
9+
.label {
10+
display: flex;
11+
flex-direction: column;
12+
text-transform: uppercase;
13+
font-size: .75rem;
14+
line-height: 1.25rem;
15+
color: var(--color_fg_default);
16+
letter-spacing: .1px;
17+
}
18+
19+
.fullLabel {
20+
display: none;
21+
font-size: .8125rem;
22+
font-weight: 500;
23+
@media #{$breakpoint-dimension-sm} {
24+
display: unset;
25+
}
26+
}
27+
28+
.input {
29+
opacity: 0;
30+
width: 0;
31+
height: 0;
32+
}
33+
34+
.switch__container {
35+
position: relative;
36+
display: inline-block;
37+
width: 40px;
38+
height: 24px;
39+
transition: all .25s cubic-bezier(.17,.67,.83,.67);
40+
}
41+
42+
.picker__round {
43+
border-radius: 24px;
44+
&::before {
45+
border-radius: 50%;
46+
}
47+
}
48+
49+
.picker__slider {
50+
position: absolute;
51+
cursor: pointer;
52+
top: 0;
53+
left: 0;
54+
right: 0;
55+
bottom: 0;
56+
background-color: var(--color_bg_layer_bold);
57+
border: 1px solid var(--color_border_default);
58+
box-shadow: 0 0 1px rgba(0,0,0,.06),0 0 1px rgba(0,0,0,.06),inset 0 1px 1px .5px rgba(0,0,0,.04);
59+
transition: background-color .25s cubic-bezier(.17,.67,.83,.67),border .25s ease;
60+
&::before {
61+
position: absolute;
62+
content: "";
63+
height: 16px;
64+
width: 16px;
65+
top: 3px;
66+
left: 3px;
67+
background: linear-gradient(180deg,transparent,rgba(0,0,0,.08)),#fff;
68+
box-shadow: 0 2px 2px -1px rgba(0,0,0,.2),0 2px 4px -2px rgba(0,0,0,.2),inset 0 .5px .5px hsla(0,0%,100%,.12);
69+
transition: transform .25s cubic-bezier(.34,1.56,.64,1),background-color .2s ease;
70+
will-change: transform;
71+
}
72+
}
73+
74+
input:checked+.picker__slider {
75+
background-color: var(--color_fg_bold);
76+
border: 1px solid var(--color_fg_bold);
77+
&::before {
78+
transform: translateX(16px);
79+
background-color: var(--color_fg_on_state_success);
80+
}
81+
}
82+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { ChangeEvent, useEffect, useState } from "react";
2+
import styles from "./encoding-format-toggle-switch.module.scss";
3+
import { EncodingValues } from "@/features/common/values/encoding.values";
4+
import { useDecoderStore } from "@/features/decoder/services/decoder.store";
5+
import { getPickersUiDictionary } from "@/features/localization/services/ui-language-dictionary.service";
6+
import { Switch } from "react-aria-components";
7+
import clsx from "clsx";
8+
9+
interface EncodingFormatToggleSwitchComponentProps {
10+
languageCode: string;
11+
}
12+
13+
export const EncodingFormatToggleSwitchComponent: React.FC<
14+
EncodingFormatToggleSwitchComponentProps
15+
> = ({ languageCode }) => {
16+
const dictionary = getPickersUiDictionary(languageCode);
17+
18+
const handleSymmetricSecretKeyEncodingChange = useDecoderStore(
19+
(state) => state.handleSymmetricSecretKeyEncodingChange
20+
);
21+
22+
const onSecretEncodingFormatChange = (event: ChangeEvent<HTMLInputElement>) => {
23+
handleSymmetricSecretKeyEncodingChange(event.target.checked ? EncodingValues.BASE64URL : EncodingValues.UTF8);
24+
};
25+
26+
return (
27+
<div className={styles.container}>
28+
<div className={styles.label}>
29+
<span className={styles.fullLabel}>Base64URL Encoded?</span>
30+
</div>
31+
<label className={styles.switch__container}>
32+
<input type="checkbox" role="switch" className={styles.input} onChange={onSecretEncodingFormatChange}/>
33+
<span
34+
className={clsx(
35+
styles.picker__round,
36+
styles.picker__slider
37+
)}
38+
></span>
39+
</label>
40+
</div>
41+
);
42+
};

0 commit comments

Comments
 (0)