Skip to content
61 changes: 37 additions & 24 deletions src/features/common/components/card/card.component.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React, { PropsWithChildren, useId } from "react";
import styles from "./card.module.scss";
import { clsx } from "clsx";
import { getLocalizedSecondaryFont, MonoFont } from "@/libs/theme/fonts";
import { getLocalizedSecondaryFont } from "@/libs/theme/fonts";
import { CardMessageComponent } from "@/features/common/components/card-message/card-message.component";
import { HeaderIcon } from "../icons/header/header-icon";
import { CheckIcon } from "../icons/check/check-icon";
import { EncodingFormatToggleSwitchComponent } from "@/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch";
import { useDecoderStore } from "@/features/decoder/services/decoder.store";
import { isHmacAlg } from "../../services/jwt.service";
import { TokenDecoderKeyFormatPickerComponent } from "@/features/decoder/components/token-decoder-key-format-picker.component";

export interface CardComponentProps extends PropsWithChildren {
id: string;
Expand Down Expand Up @@ -150,10 +154,10 @@ export const CardComponent: React.FC<CardComponentProps> = (props) => {
>
{messages.success.map((line, index) => {
return (
<>
<CheckIcon />
<CardMessageComponent key={index}>{line}</CardMessageComponent>
</>
<div key={index} style={{ display: "flex" }}>
<CheckIcon />
<CardMessageComponent key={index}>{line}</CardMessageComponent>
</div>
);
})}
</div>
Expand Down Expand Up @@ -197,31 +201,40 @@ export const CardWithHeadlineComponent: React.FC<
CardWithHeadlineComponentProps
> = ({ sectionHeadline, languageCode, ...props }) => {
const regionId = useId();
const alg$ = useDecoderStore((state) => state.alg);

return (
<div role="region" aria-labelledby={regionId}>
{sectionHeadline && (
<>
<h3
id={regionId}
className={clsx(
styles.cardHeadline__title,
getLocalizedSecondaryFont(languageCode)
)}
>
{sectionHeadline.title}
{sectionHeadline.titleTag && (
<span className={styles.cardHeadline__titleTag}>
{sectionHeadline.titleTag}
</span>
<div className={styles.title__container}>
<div>
<h3
id={regionId}
className={clsx(
styles.cardHeadline__title,
getLocalizedSecondaryFont(languageCode)
)}
>
{sectionHeadline.title}
{sectionHeadline.titleTag && (
<span className={styles.cardHeadline__titleTag}>
{sectionHeadline.titleTag}
</span>
)}
</h3>
{sectionHeadline.description && (
<p className={styles.cardHeadline__description}>
{sectionHeadline.description}
</p>
)}
</h3>
{sectionHeadline.description && (
<p className={styles.cardHeadline__description}>
{sectionHeadline.description}
</p>
</div>

{isHmacAlg(alg$) ? (
<EncodingFormatToggleSwitchComponent languageCode={languageCode} />
) : (
<TokenDecoderKeyFormatPickerComponent languageCode={languageCode} />
)}
</>
</div>
)}
<CardComponent languageCode={languageCode} {...props} />
</div>
Expand Down
12 changes: 12 additions & 0 deletions src/features/common/components/card/card.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@
}
}

.title__container {
grid-column: 1/-1;
width: 100%;
color: var(--color_fg_bold);
font-size: 1.75rem;
font-weight: 500;
line-height: 1.5;
margin-bottom: .5rem;
display: flex;
justify-content: space-between;
}

.card {
isolation: isolate;
grid-column: span 6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface DebuggerPickerComponentProps {
GroupBase<DebuggerPickerOptionModel>
>;
isGrouped?: boolean;
selectedOptionCode: DebuggerPickerOptionModel | null;
selectedOptionCode?: DebuggerPickerOptionModel | null;
handleSelection: (
selection: string,
parentLabel?: LibraryFilterLabel
Expand All @@ -54,6 +54,7 @@ export const DebuggerPickerComponent: React.FC<
> = ({
label,
options,
selectedOptionCode,
handleSelection,
placeholder,
minWidth,
Expand Down Expand Up @@ -93,6 +94,7 @@ export const DebuggerPickerComponent: React.FC<
classNamePrefix={"react-select"}
isSearchable={false}
placeholder={placeholder}
value={selectedOptionCode}
styles={{
control: (base) => ({
...base,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,17 @@ $picker-list-offset-lg: calc(($picker-list-width-lg - $picker-width-lg) / 2);
}

.picker__label {
display: flex;
align-items: center;
justify-content: center;
padding: 0;
list-style-type: none;
margin: 0;
gap: 0.5rem;
font-size: 0.8125rem;
line-height: 1.3125rem;
letter-spacing: -0.05px;

width: 100%;

height: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
padding: 0;
list-style-type: none;
margin: 0;
gap: .5rem;
font-size: .875rem;
line-height: 1.35;
width: 100%;
height: 100%;

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

.picker__fullName {
display: flex;
font-weight: 600;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
algDictionary,
jwsExampleAlgHeaderParameterValuesDictionary,
} from "@/features/common/values/jws-alg-header-parameter-values.dictionary";
import { useButton } from "@react-aria/button"
import { useButton } from "@react-aria/button";
import { DebuggerPickerOptionModel } from "@/features/common/models/debugger-picker-option.model";

enum PickerStates {
Expand Down Expand Up @@ -92,7 +92,6 @@ export const WidgetAlgPickerComponent: React.FC<
setPickerState(PickerStates.IDLE);
};


useEffect(() => {
(async function runEs512Check() {
setCanUseEs512(await isP521Supported());
Expand All @@ -107,18 +106,6 @@ export const WidgetAlgPickerComponent: React.FC<
})();
}, []);

/* const noneAlgOptions: DebuggerPickerOptionModel[] = useMemo(() => {
return Object.entries(
jwsExampleAlgHeaderParameterValuesDictionary.unsecured
).map((entry) => {
const [key, value] = entry;

return {
value: key,
label: value.name,
};
});
}, []); */

const symmetricAlgOptions: DebuggerPickerOptionModel[] = useMemo(() => {
return Object.entries(jwsExampleAlgHeaderParameterValuesDictionary.mac).map(
Expand Down Expand Up @@ -197,16 +184,17 @@ export const WidgetAlgPickerComponent: React.FC<
{dictionary.exampleAlgPicker.label}
</label>
</div>
<DebuggerPickerComponent
label={null}
data-has-label={label !== null}
languageCode={languageCode}
handleSelection={selectExample}
selectedOptionCode={null}
options={algOptions}
placeholder={dictionary.exampleAlgPicker.defaultValue}
minWidth={null}
/>
<div className={styles.picker__container}>
<DebuggerPickerComponent
label={null}
data-has-label={label !== null}
languageCode={languageCode}
handleSelection={selectExample}
options={algOptions}
placeholder={dictionary.exampleAlgPicker.defaultValue}
minWidth={null}
/>
</div>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
font-weight: 600;
}

.picker__container {
height: 2rem;
}

.button {
color: var(--color_fg_on_button);
background-color: var(--color_bg_button);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
@use "@/libs/theme/styles/variables" as *;

.container {
display: flex;
align-items: center;
gap: .5rem;
}

.label {
display: flex;
flex-direction: column;
text-transform: uppercase;
font-size: .75rem;
line-height: 1.25rem;
color: var(--color_fg_default);
letter-spacing: .1px;
}

.fullLabel {
display: none;
font-size: .8125rem;
font-weight: 500;
@media #{$breakpoint-dimension-sm} {
display: unset;
}
}

.input {
opacity: 0;
width: 0;
height: 0;
}

.switch__container {
position: relative;
display: inline-block;
width: 40px;
height: 24px;
transition: all .25s cubic-bezier(.17,.67,.83,.67);
}

.picker__round {
border-radius: 24px;
&::before {
border-radius: 50%;
}
}

.picker__slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--color_bg_layer_bold);
border: 1px solid var(--color_border_default);
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);
transition: background-color .25s cubic-bezier(.17,.67,.83,.67),border .25s ease;
&::before {
position: absolute;
content: "";
height: 16px;
width: 16px;
top: 3px;
left: 3px;
background: linear-gradient(180deg,transparent,rgba(0,0,0,.08)),#fff;
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);
transition: transform .25s cubic-bezier(.34,1.56,.64,1),background-color .2s ease;
will-change: transform;
}
}

input:checked+.picker__slider {
background-color: var(--color_fg_bold);
border: 1px solid var(--color_fg_bold);
&::before {
transform: translateX(16px);
background-color: var(--color_fg_on_state_success);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { ChangeEvent, useEffect, useState } from "react";
import styles from "./encoding-format-toggle-switch.module.scss";
import { EncodingValues } from "@/features/common/values/encoding.values";
import { useDecoderStore } from "@/features/decoder/services/decoder.store";
import { getPickersUiDictionary } from "@/features/localization/services/ui-language-dictionary.service";
import { Switch } from "react-aria-components";
import clsx from "clsx";

interface EncodingFormatToggleSwitchComponentProps {
languageCode: string;
}

export const EncodingFormatToggleSwitchComponent: React.FC<
EncodingFormatToggleSwitchComponentProps
> = ({ languageCode }) => {
const dictionary = getPickersUiDictionary(languageCode);

const handleSymmetricSecretKeyEncodingChange = useDecoderStore(
(state) => state.handleSymmetricSecretKeyEncodingChange
);

const onSecretEncodingFormatChange = (event: ChangeEvent<HTMLInputElement>) => {
handleSymmetricSecretKeyEncodingChange(event.target.checked ? EncodingValues.BASE64URL : EncodingValues.UTF8);
};

return (
<div className={styles.container}>
<div className={styles.label}>
<span className={styles.fullLabel}>Base64URL Encoded?</span>
</div>
<label className={styles.switch__container}>
<input type="checkbox" role="switch" className={styles.input} onChange={onSecretEncodingFormatChange}/>
<span
className={clsx(
styles.picker__round,
styles.picker__slider
)}
></span>
</label>
</div>
);
};
Loading