diff --git a/src/features/common/components/card/card.component.tsx b/src/features/common/components/card/card.component.tsx index 504f2df9..cb72669a 100644 --- a/src/features/common/components/card/card.component.tsx +++ b/src/features/common/components/card/card.component.tsx @@ -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; @@ -150,10 +154,10 @@ export const CardComponent: React.FC = (props) => { > {messages.success.map((line, index) => { return ( - <> - - {line} - +
+ + {line} +
); })} @@ -197,31 +201,40 @@ export const CardWithHeadlineComponent: React.FC< CardWithHeadlineComponentProps > = ({ sectionHeadline, languageCode, ...props }) => { const regionId = useId(); + const alg$ = useDecoderStore((state) => state.alg); return (
{sectionHeadline && ( - <> -

- {sectionHeadline.title} - {sectionHeadline.titleTag && ( - - {sectionHeadline.titleTag} - +
+
+

+ {sectionHeadline.title} + {sectionHeadline.titleTag && ( + + {sectionHeadline.titleTag} + + )} +

+ {sectionHeadline.description && ( +

+ {sectionHeadline.description} +

)} -

- {sectionHeadline.description && ( -

- {sectionHeadline.description} -

+
+ + {isHmacAlg(alg$) ? ( + + ) : ( + )} - + )} diff --git a/src/features/common/components/card/card.module.scss b/src/features/common/components/card/card.module.scss index 382be7c2..5472c0c4 100644 --- a/src/features/common/components/card/card.module.scss +++ b/src/features/common/components/card/card.module.scss @@ -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; diff --git a/src/features/common/components/debugger-picker/debugger-picker.component.tsx b/src/features/common/components/debugger-picker/debugger-picker.component.tsx index 450e9619..c62873c2 100644 --- a/src/features/common/components/debugger-picker/debugger-picker.component.tsx +++ b/src/features/common/components/debugger-picker/debugger-picker.component.tsx @@ -40,7 +40,7 @@ interface DebuggerPickerComponentProps { GroupBase >; isGrouped?: boolean; - selectedOptionCode: DebuggerPickerOptionModel | null; + selectedOptionCode?: DebuggerPickerOptionModel | null; handleSelection: ( selection: string, parentLabel?: LibraryFilterLabel @@ -54,6 +54,7 @@ export const DebuggerPickerComponent: React.FC< > = ({ label, options, + selectedOptionCode, handleSelection, placeholder, minWidth, @@ -93,6 +94,7 @@ export const DebuggerPickerComponent: React.FC< classNamePrefix={"react-select"} isSearchable={false} placeholder={placeholder} + value={selectedOptionCode} styles={{ control: (base) => ({ ...base, diff --git a/src/features/common/components/debugger-picker/debugger-picker.module.scss b/src/features/common/components/debugger-picker/debugger-picker.module.scss index ab3f065d..d8944919 100644 --- a/src/features/common/components/debugger-picker/debugger-picker.module.scss +++ b/src/features/common/components/debugger-picker/debugger-picker.module.scss @@ -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); @@ -55,4 +52,5 @@ $picker-list-offset-lg: calc(($picker-list-width-lg - $picker-width-lg) / 2); .picker__fullName { display: flex; + font-weight: 600; } \ No newline at end of file diff --git a/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.component.tsx b/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.component.tsx index 3242b44f..c407e3b4 100644 --- a/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.component.tsx +++ b/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.component.tsx @@ -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 { @@ -92,7 +92,6 @@ export const WidgetAlgPickerComponent: React.FC< setPickerState(PickerStates.IDLE); }; - useEffect(() => { (async function runEs512Check() { setCanUseEs512(await isP521Supported()); @@ -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( @@ -197,16 +184,17 @@ export const WidgetAlgPickerComponent: React.FC< {dictionary.exampleAlgPicker.label} - +
+ +
diff --git a/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.module.scss b/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.module.scss index 48f7278b..a195930a 100644 --- a/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.module.scss +++ b/src/features/debugger/components/debugger-alg-picker/debugger-alg-picker.module.scss @@ -62,6 +62,10 @@ font-weight: 600; } +.picker__container { + height: 2rem; +} + .button { color: var(--color_fg_on_button); background-color: var(--color_bg_button); diff --git a/src/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch.module.scss b/src/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch.module.scss new file mode 100644 index 00000000..377661de --- /dev/null +++ b/src/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch.module.scss @@ -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); + } +} + diff --git a/src/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch.tsx b/src/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch.tsx new file mode 100644 index 00000000..5d29db85 --- /dev/null +++ b/src/features/decoder/components/encoding-format-toggle-swith/encoding-format-toggle-switch.tsx @@ -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) => { + handleSymmetricSecretKeyEncodingChange(event.target.checked ? EncodingValues.BASE64URL : EncodingValues.UTF8); + }; + + return ( +
+
+ Base64URL Encoded? +
+ +
+ ); +}; diff --git a/src/features/decoder/components/secret-key-input.component.tsx b/src/features/decoder/components/secret-key-input.component.tsx index 919a6f88..0cb09328 100644 --- a/src/features/decoder/components/secret-key-input.component.tsx +++ b/src/features/decoder/components/secret-key-input.component.tsx @@ -19,6 +19,7 @@ import { CardToolbarComponent } from "@/features/common/components/card-toolbar/ import { CardToolbarCopyButtonComponent } from "@/features/common/components/card-toolbar-buttons/card-toolbar-copy-button/card-toolbar-copy-button.component"; import { CardToolbarClearButtonComponent } from "@/features/common/components/card-toolbar-buttons/card-toolbar-clear-button/card-toolbar-clear-button.component"; import { NOOP_ALG } from "@/features/common/values/constants"; +import { EncodingFormatToggleSwitchComponent } from "./encoding-format-toggle-swith/encoding-format-toggle-switch"; type SecretKeyInputComponentProps = { languageCode: string; @@ -58,7 +59,7 @@ export const SecretKeyInputComponent: React.FC< decoderInputs$.algType === SigningAlgCategoryValues.SYMMETRIC && decoderInputs$.symmetricSecretKey ? decoderInputs$.symmetricSecretKey - : DEFAULT_JWT.secret, + : DEFAULT_JWT.secret ); const [publicKey, setPublicKey] = useState(""); @@ -162,6 +163,11 @@ export const SecretKeyInputComponent: React.FC< /> ), + /* footer: isHmacAlg(alg$) ? ( + + ) : ( + + ), */ }} > {isHmacAlg(alg$) && ( diff --git a/src/features/decoder/components/token-decoder-key-format-picker.module.scss b/src/features/decoder/components/token-decoder-key-format-picker.module.scss index c172cbca..d85867ad 100644 --- a/src/features/decoder/components/token-decoder-key-format-picker.module.scss +++ b/src/features/decoder/components/token-decoder-key-format-picker.module.scss @@ -12,11 +12,17 @@ } .label { - color: var(--color_fg_default); - font-size: 0.875rem; - line-height: 1.375rem; - font-weight: 500; - letter-spacing: 0.1px; + 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%; } .select { diff --git a/src/libs/theme/styles/globals.scss b/src/libs/theme/styles/globals.scss index 4b320253..83dd4895 100644 --- a/src/libs/theme/styles/globals.scss +++ b/src/libs/theme/styles/globals.scss @@ -507,7 +507,6 @@ $picker-list-offset-lg: calc(($picker-list-width-lg - $picker-width-lg) / 2); background: transparent; color: var(--color_fg_bold); font-family: var(--font-primary), monospace !important; - height: 2rem !important; } .react-select__control { @@ -557,7 +556,7 @@ $picker-list-offset-lg: calc(($picker-list-width-lg - $picker-width-lg) / 2); border: 1px solid var(--color_border_default); padding: 0.25rem; overflow: hidden; - min-width: 240px; + min-width: 6.125rem; } .react-select__menu-portal {