From cef6fd45a98c8ad6a8b8ea6e3a30a7dc790daa0f Mon Sep 17 00:00:00 2001 From: romanjaros Date: Thu, 2 Nov 2023 20:10:26 +0100 Subject: [PATCH 1/2] Minor auth and api updates + rename Title component --- packages/api/src/components/FetchLoader.tsx | 2 +- packages/api/src/query.ts | 6 +- packages/auth/src/hook/useAuthCode.ts | 38 ++++++++++ packages/auth/src/hook/useLogin.ts | 29 ++++++++ packages/auth/src/hook/useOAuth.ts | 72 ------------------- packages/auth/src/slice.ts | 4 +- packages/auth/src/types.ts | 8 +-- .../src/Calendar/components/Calendar.tsx | 5 +- packages/components/src/Section.tsx | 19 ++--- packages/components/src/Text.tsx | 25 +++++++ packages/components/src/Title.tsx | 39 ---------- packages/constants/src/empty.ts | 3 - .../src/{redux/index.ts => redux.ts} | 1 + stories/api/Codegen.mdx | 6 +- stories/api/Introduction.mdx | 14 +--- stories/auth/Introduction.mdx | 32 +++------ stories/auth/UseOAuth.mdx | 60 ---------------- stories/auth/helpers/hook.tsx | 26 ++++--- stories/components/Section.stories.tsx | 17 ++--- stories/components/Title.stories.tsx | 17 +++-- stories/components/Toasters.stories.tsx | 4 +- 21 files changed, 156 insertions(+), 271 deletions(-) create mode 100644 packages/auth/src/hook/useAuthCode.ts create mode 100644 packages/auth/src/hook/useLogin.ts delete mode 100644 packages/auth/src/hook/useOAuth.ts create mode 100644 packages/components/src/Text.tsx delete mode 100644 packages/components/src/Title.tsx delete mode 100644 packages/constants/src/empty.ts rename packages/constants/src/{redux/index.ts => redux.ts} (97%) delete mode 100644 stories/auth/UseOAuth.mdx diff --git a/packages/api/src/components/FetchLoader.tsx b/packages/api/src/components/FetchLoader.tsx index b57b7a00..af3a8180 100644 --- a/packages/api/src/components/FetchLoader.tsx +++ b/packages/api/src/components/FetchLoader.tsx @@ -10,5 +10,5 @@ export const FetchLoader: FC = ({ children, active, placeholde if (!active) { return <>{children}; } - return
{placeholder ?? null}
; + return
{placeholder}
; }; diff --git a/packages/api/src/query.ts b/packages/api/src/query.ts index 9700619a..13204f88 100644 --- a/packages/api/src/query.ts +++ b/packages/api/src/query.ts @@ -20,7 +20,7 @@ export type BaseQueryFetchParams = { url: string; }; -export type BaseQueryWithReauthParams = { +export type BaseQueryWithRefreshParams = { authentication: { baseUrl: string; clientId: string; @@ -70,11 +70,11 @@ export const baseQuery = } }; -export const baseQueryWithReauth = +export const baseQueryWithRefresh = ({ baseUrl, authentication, - }: BaseQueryWithReauthParams): BaseQueryFn, Response, FetchBaseQueryError> => + }: BaseQueryWithRefreshParams): BaseQueryFn, Response, FetchBaseQueryError> => async (args, api, extraOptions) => { const authReducer: any = (api.getState() as AuthRootState).procyon[AUTH_REDUCER_NAME]; const accessTokenExpired = new Date(authReducer.accessExpiresTime) < new Date(); diff --git a/packages/auth/src/hook/useAuthCode.ts b/packages/auth/src/hook/useAuthCode.ts new file mode 100644 index 00000000..b5c94f2b --- /dev/null +++ b/packages/auth/src/hook/useAuthCode.ts @@ -0,0 +1,38 @@ +import { useCallback } from 'react'; +import { useDispatch } from 'react-redux'; +import { useLocation } from 'wouter'; + +import { setAuthTokens } from '@procyon/auth/slice'; + +import { fetchTokens } from '../actions'; +import { UseAuthParams } from '../types'; + +export const useAuthCode = ({ baseUrl, clientId, tokenEndpoint, redirectUri }: UseAuthParams) => { + const dispatch = useDispatch(); + + const [, setLocation] = useLocation(); + + return useCallback(async (code: string) => { + const { data: tokens } = await fetchTokens({ + baseUrl, + tokenEndpoint, + clientId, + redirectUri: redirectUri, + grantType: 'authorization_code', + code, + }); + if (tokens) { + dispatch( + setAuthTokens({ + accessToken: tokens.access_token, + refreshToken: tokens.refresh_token, + idToken: tokens.id_token, + accessExpiresIn: tokens.expires_in, + refreshExpiresIn: tokens.refresh_expires_in, + sessionState: tokens.session_state, + }) + ); + setLocation('/'); + } + }, []); +}; diff --git a/packages/auth/src/hook/useLogin.ts b/packages/auth/src/hook/useLogin.ts new file mode 100644 index 00000000..5a012346 --- /dev/null +++ b/packages/auth/src/hook/useLogin.ts @@ -0,0 +1,29 @@ +import { useCallback } from 'react'; + +import { UseAuthParams } from '../types'; + +const generateState = () => + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + const r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + +export const useLogin = ({ baseUrl, clientId, authEndpoint, redirectUri }: UseAuthParams) => { + return useCallback(() => { + const state = generateState(); + const urlParams: Record = { + client_id: clientId, + redirect_uri: redirectUri, + response_mode: 'fragment', + response_type: 'code', + scope: 'openid profile', + state, + }; + const connectionURI = new URL(`${baseUrl}${authEndpoint}`); + for (const key of Object.keys(urlParams)) { + connectionURI.searchParams.append(key, urlParams[key]); + } + window.location.assign(connectionURI); + }, []); +}; diff --git a/packages/auth/src/hook/useOAuth.ts b/packages/auth/src/hook/useOAuth.ts deleted file mode 100644 index 01962707..00000000 --- a/packages/auth/src/hook/useOAuth.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { useCallback } from 'react'; -import { useDispatch } from 'react-redux'; -import { useLocation } from 'wouter'; - -import { setAuthTokens } from '@procyon/auth/slice'; - -import { fetchTokens } from '../actions'; -import { UseOAuthParams } from '../types'; - -const generateState = () => - 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - const r = (Math.random() * 16) | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); - -/** - * test - * @param param0 test - * @returns - */ -export const useOAuth = ({ baseUrl, clientId, authEndpoint, tokenEndpoint, redirectUri }: UseOAuthParams) => { - const dispatch = useDispatch(); - - const [, setLocation] = useLocation(); - - const redirect = useCallback(() => { - const state = generateState(); - const urlParams: Record = { - client_id: clientId, - redirect_uri: redirectUri, - response_mode: 'fragment', - response_type: 'code', - scope: 'openid profile', - state, - }; - const conectionURI = new URL(`${baseUrl}${authEndpoint}`); - for (const key of Object.keys(urlParams)) { - conectionURI.searchParams.append(key, urlParams[key]); - } - window.location.assign(conectionURI); - }, []); - - const obtainTokens = useCallback(async (code: string) => { - const { data: tokens } = await fetchTokens({ - baseUrl, - tokenEndpoint, - clientId, - redirectUri: redirectUri, - grantType: 'authorization_code', - code, - }); - if (tokens) { - dispatch( - setAuthTokens({ - accessToken: tokens.access_token, - refreshToken: tokens.refresh_token, - idToken: tokens.id_token, - accessExpiresIn: tokens.expires_in, - refreshExpiresIn: tokens.refresh_expires_in, - sessionState: tokens.session_state, - }) - ); - setLocation('/'); - } - }, []); - - return { - redirect, - obtainTokens, - }; -}; diff --git a/packages/auth/src/slice.ts b/packages/auth/src/slice.ts index 4ed11d7d..871963c1 100644 --- a/packages/auth/src/slice.ts +++ b/packages/auth/src/slice.ts @@ -1,7 +1,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { addSeconds } from 'date-fns'; -import { AUTH_REDUCER_NAME, AuthAttributes, AuthRootState, AuthTokens, ModifyAuthAttribute } from './types'; +import { AUTH_REDUCER_NAME, AuthAttributes, AuthRootState, AuthTokenPayload, ModifyAuthAttribute } from './types'; const initialState: AuthAttributes = { authenticated: undefined, @@ -19,7 +19,7 @@ const authSlice = createSlice({ name: AUTH_REDUCER_NAME, initialState, reducers: { - setAuthTokens: (_, action: PayloadAction) => { + setAuthTokens: (_, action: PayloadAction) => { const { accessExpiresIn, refreshExpiresIn } = action.payload; return { ...action.payload, diff --git a/packages/auth/src/types.ts b/packages/auth/src/types.ts index 96648886..90ef7676 100644 --- a/packages/auth/src/types.ts +++ b/packages/auth/src/types.ts @@ -2,7 +2,7 @@ import { ROOT_REDUCER_NAME } from '@procyon/constants/redux'; export const AUTH_REDUCER_NAME = 'auth'; -export type AuthTokens = { +export type AuthTokenPayload = { accessExpiresIn?: number; accessToken?: string; idToken?: string; @@ -16,7 +16,7 @@ export type AuthAttributes = { authenticated?: boolean; refreshExpiresTime?: string; } & CustomAttributes & - AuthTokens; + AuthTokenPayload; export type ModifyAuthAttribute

= { key: keyof AuthAttributes

; @@ -29,7 +29,7 @@ export type AuthRootState = { }; }; -export type UseOAuthParams = { +export type UseAuthParams = { authEndpoint: string; baseUrl: string; clientId: string; @@ -38,7 +38,7 @@ export type UseOAuthParams = { tokenEndpoint: string; }; -export type FetchTokensParams = Pick & { +export type FetchTokensParams = Pick & { code: string; grantType: 'authorization_code'; redirectUri: string; diff --git a/packages/components/src/Calendar/components/Calendar.tsx b/packages/components/src/Calendar/components/Calendar.tsx index 652d7395..aa6b2716 100644 --- a/packages/components/src/Calendar/components/Calendar.tsx +++ b/packages/components/src/Calendar/components/Calendar.tsx @@ -2,9 +2,10 @@ import React, { FC, Fragment, useEffect, useMemo, useState } from 'react'; import { range } from 'ramda'; import { add, endOfMonth, endOfWeek, getWeeksInMonth, startOfMonth, startOfWeek, sub } from 'date-fns'; +import { SizeEnum } from '@procyon/types/common'; import { isNilOrEmpty } from '@procyon/utils'; -import { Title, TitleSizeEnum } from '../../Title'; +import { Text } from '../../Text'; import { CalendarCell, CalendarCellProps } from './CalendarCell'; import { CalendarDays, CalendarDaysProps } from './CalendarDays'; import { Controller, ControllerProps } from './Controller'; @@ -181,7 +182,7 @@ export function Calendar({ return ( <> - {!isNilOrEmpty(title) && {title}} + {!isNilOrEmpty(title) && {title}} >; + className?: string; }; -const Section: FC = ({ Title, children, space = { [DirectionEnum.bottom]: 4 } }) => { - const spaces: string[] = []; - for (const direct in space) { - spaces.push(`m${direct}-${space[direct]}`); - } - return ( -

+export const Section: FC = ({ Title, children, className }) => ( +
{Title && } {children} </div> - ); -}; - -export default Section; + ) \ No newline at end of file diff --git a/packages/components/src/Text.tsx b/packages/components/src/Text.tsx new file mode 100644 index 00000000..22a3e932 --- /dev/null +++ b/packages/components/src/Text.tsx @@ -0,0 +1,25 @@ +import React, { FC, ReactElement } from 'react'; +import clsx from 'clsx'; + +import { SizeEnum } from '@procyon/types/common'; + +export type TextProps = { + children?: ReactElement | string; + className?: string; + size?: SizeEnum; +}; + +export const Text: FC<TextProps> = ({ size = SizeEnum.sm, children, className }) => ( + <div + className={clsx( + { + 'text-base': size === SizeEnum.sm, + 'text-2xl mb-1': size === SizeEnum.md, + 'text-3xl mb-2': size === SizeEnum.lg, + 'text-4xl mb-3': size === SizeEnum.xl, + }, + className + )}> + {children} + </div> + ) diff --git a/packages/components/src/Title.tsx b/packages/components/src/Title.tsx deleted file mode 100644 index f1eb07c9..00000000 --- a/packages/components/src/Title.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, { FC, ReactElement } from 'react'; -import clsx from 'clsx'; - -import { DirectionEnum, SizeEnum } from '@procyon/types/common'; - -export enum TitleSizeEnum { - lg = 'lg', - md = 'md', - xl = 'xl', -} - -export type TitleProps = { - children?: ReactElement | string; - className?: string; - margin?: Partial<Record<DirectionEnum, number>>; - size?: TitleSizeEnum; -}; - -export const Title: FC<TitleProps> = ({ size = SizeEnum.sm, children, className, margin }) => { - const margins: string[] = []; - for (const direct in margin) { - margins.push(`m${direct}-${margin[direct]}`); - } - return ( - <div - className={clsx( - { - 'text-base': size === SizeEnum.sm, - 'text-2xl mb-1': size === SizeEnum.md, - 'text-3xl mb-2': size === SizeEnum.lg, - 'text-4xl mb-3': size === SizeEnum.xl, - }, - margins, - className - )}> - {children} - </div> - ); -}; diff --git a/packages/constants/src/empty.ts b/packages/constants/src/empty.ts deleted file mode 100644 index dd93f1ed..00000000 --- a/packages/constants/src/empty.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const EMPTY_OBJECT = {}; - -export const EMPTY_ARRAY: [] = []; diff --git a/packages/constants/src/redux/index.ts b/packages/constants/src/redux.ts similarity index 97% rename from packages/constants/src/redux/index.ts rename to packages/constants/src/redux.ts index 031300a7..070836c2 100644 --- a/packages/constants/src/redux/index.ts +++ b/packages/constants/src/redux.ts @@ -1 +1,2 @@ + export const ROOT_REDUCER_NAME = 'procyon'; diff --git a/stories/api/Codegen.mdx b/stories/api/Codegen.mdx index 48be6cba..286ddb06 100644 --- a/stories/api/Codegen.mdx +++ b/stories/api/Codegen.mdx @@ -43,13 +43,11 @@ module.exports = config; <Unstyled> <Message status={StatusEnum.info}> - If you want to use automatical reobtain access token, do not forget to use `baseQueryWithReauth` instead of - `baseQuery` from `@procyon/api/query`. Pass same parameters as to `useOauth` hook. + If you want to use automatically extend access token, use `baseQueryWithRefresh` instead of + `baseQuery` from `@procyon/api/query`. </Message> </Unstyled> -<br /> - ```ts import { createApi } from '@reduxjs/toolkit/query/react'; diff --git a/stories/api/Introduction.mdx b/stories/api/Introduction.mdx index d39fb49d..1f4e7bb2 100644 --- a/stories/api/Introduction.mdx +++ b/stories/api/Introduction.mdx @@ -1,7 +1,4 @@ -import { Canvas, Meta, Source, Unstyled } from '@storybook/blocks'; - -import Message from '@procyon/components/Message'; -import { StatusEnum } from '@procyon/types/common'; +import { Canvas, Meta, Source } from '@storybook/blocks'; import apiContent from './helpers/api?raw'; import { FetchComponent } from './helpers/FetchComponent'; @@ -16,15 +13,6 @@ import reduxContent from './helpers/redux?raw'; `@procyon/api` module for fetch. -<Unstyled> - <Message status={StatusEnum.info}> - If you want to use automatical reobtain access token, do not forget to use `baseQueryWithReauth` instead of - `baseQuery` from `@procyon/api/query`. Pass same parameters as to `useOauth` hook. - </Message> -</Unstyled> - -<br /> - ## Preparation ### Define API via RTQuery diff --git a/stories/auth/Introduction.mdx b/stories/auth/Introduction.mdx index f4dbacfa..5b56737d 100644 --- a/stories/auth/Introduction.mdx +++ b/stories/auth/Introduction.mdx @@ -4,6 +4,7 @@ import Message from '@procyon/components/Message'; import { StatusEnum } from '@procyon/types/common'; import storeCode from './helpers/redux?raw'; +import hookCode from './helpers/hook?raw'; <Meta title="Auth/Introduction" /> @@ -11,44 +12,29 @@ import storeCode from './helpers/redux?raw'; `@procyon/auth` module for authenticated. -For work with IdP (Identity Provider server) use `useOAuth` hook. +For work with IdP (Identity Provider) server use `useLogin` and `useAuthCode` hooks. <Unstyled> <Message status={StatusEnum.info}> - After reload page, reducer data are synchronized with browser session storage. So they are saved until close browser - tab. + When refresh page, data are synchronized with browser session storage. </Message> </Unstyled> <br /> <Unstyled> - <Message status={StatusEnum.error}> - If you want to use automatical reobtain access token, do not forget to use `baseQueryWithReauth` instead of - `baseQuery` from `@procyon/api/query` and pass same parameters as to `useOauth` hook. + <Message status={StatusEnum.info}> + If you want to use automatically extend access token, use `baseQueryWithRefresh` instead of + `baseQuery` from `@procyon/api/query`. </Message> </Unstyled> <br /> -## Redux store - -Redux is used as storage. `@procyon/api` use this storage for pickup access token for fetch auth header. - -<Unstyled> - <Message status={StatusEnum.warning}> - Is important to to use auth reducer under <b>procyon</b> main reducer. - </Message> -</Unstyled> - -<br /> - -### example +### Redux storage <Source language="ts" code={storeCode} /> -### stored data - <PureArgsTable rows={{ authenticated: { @@ -86,3 +72,7 @@ Redux is used as storage. `@procyon/api` use this storage for pickup access toke }, }} /> + +### Sample source + +<Source language="ts" code={hookCode} /> \ No newline at end of file diff --git a/stories/auth/UseOAuth.mdx b/stories/auth/UseOAuth.mdx deleted file mode 100644 index 45d40ab5..00000000 --- a/stories/auth/UseOAuth.mdx +++ /dev/null @@ -1,60 +0,0 @@ -import { Meta, PureArgsTable, Source } from '@storybook/blocks'; - -import hookCode from './helpers/hook?raw'; - -<Meta title="Auth/useOAuth" /> - -# `useOAuth` hook - -`import { useOAuth } from @procyon/auth/hook/useOAuth` - -Hook will communicate with IdP server like a Keycloak. - -<Source language="ts" code={hookCode} /> - -### Params - -<PureArgsTable - rows={{ - baseUrl: { - description: 'Base Identity Provider URL.', - name: 'baseUrl', - }, - clientId: { - description: 'Client ID defined in IdP', - name: 'clientId', - }, - authEndpoint: { - description: 'URI for redirect to IdP login form', - name: 'authEndpoint', - }, - tokenEndpoint: { - description: 'Endpoint whitch is called for obtain tokends', - name: 'tokenEndpoint', - }, - logoutEndpoint: { - description: 'Endpoint for revoke session', - name: 'logoutEndpoint', - }, - redirectUrl: { - description: 'URL to redirect from IdP back to application', - name: 'redirectUrl', - }, - }} -/> - -### Returns - -<PureArgsTable - rows={{ - redirect: { - description: 'Function. When call, make redirecto to IdP login page', - name: 'redirect', - }, - obtainTokens: { - description: - 'Function. When return from IdP, app will obtain auth code which allow to fetch access tokens. After obtain tokens, make redirect to root route (/).', - name: 'obtainTokens', - }, - }} -/> diff --git a/stories/auth/helpers/hook.tsx b/stories/auth/helpers/hook.tsx index 102781f4..3563418c 100644 --- a/stories/auth/helpers/hook.tsx +++ b/stories/auth/helpers/hook.tsx @@ -1,32 +1,36 @@ import React, { FC } from 'react'; import { useLocation } from 'wouter'; -import { useOAuth } from '@procyon/auth/hook/useOAuth'; +import { useAuthCode } from '@procyon/auth/hook/useAuthCode'; +import { useLogin } from '@procyon/auth/hook/useLogin'; + +const authConfig = { + baseUrl: 'http://keycloak.local', + clientId: 'client_id', + tokenEndpoint: '/realm/localdev/token', + authEndpoint: '/realm/localdev/auth', + redirectUri: 'http://localhost:3330/login/callback', + logoutEndpoint: '/realm/localdev/logout', +}; export const Component: FC = () => { const [location] = useLocation(); - const { redirect, obtainTokens } = useOAuth({ - baseUrl: 'http://keycloak.local', - clientId: 'client_id', - tokenEndpoint: '/realm/localdev/token', - authEndpoint: '/realm/localdev/auth', - redirectUri: 'http://localhost:3330/login/callback', - logoutEndpoint: '/realm/localdev/logout', - }); + const doLogin = useLogin(authConfig); + const changeCodeForTokens = useAuthCode(authConfig); if (location === '/login/callback') { const params = new URLSearchParams(window.location.href); const code = params.get('code') ?? null; if (code) { - obtainTokens(code); + changeCodeForTokens(code); } return null; } return ( <> - <button onClick={redirect}>login</button> + <button onClick={doLogin}>login</button> </> ); }; diff --git a/stories/components/Section.stories.tsx b/stories/components/Section.stories.tsx index fc009cee..074e441a 100644 --- a/stories/components/Section.stories.tsx +++ b/stories/components/Section.stories.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react'; -import Section from '@procyon/components/Section'; -import { Title, TitleSizeEnum } from '@procyon/components/Title'; -import { DirectionEnum } from '@procyon/types/common'; +import { Section } from '@procyon/components/Section'; +import { Text } from '@procyon/components/Text'; +import { SizeEnum } from '@procyon/types/common'; type Story = StoryObj<typeof Section>; @@ -21,7 +21,7 @@ export default { export const Default: Story = { args: { - Title: () => <Title>Section, + Title: () => Section, children: 'Content', }, }; @@ -34,24 +34,21 @@ export const WithoutTitle: Story = { export const Medium: Story = { args: { - Title: () => Section, + Title: () => Section, children: 'content', - space: { [DirectionEnum.y]: 2 }, }, }; export const Large: Story = { args: { - Title: () => Section, + Title: () => Section, children: 'content', - space: { [DirectionEnum.y]: 2, [DirectionEnum.top]: 3 }, }, }; export const ExtraLarge: Story = { args: { - Title: () => Section, + Title: () => Section, children: 'content', - space: { [DirectionEnum.y]: 2, [DirectionEnum.top]: 4 }, }, }; diff --git a/stories/components/Title.stories.tsx b/stories/components/Title.stories.tsx index d5e0a305..56bc1240 100644 --- a/stories/components/Title.stories.tsx +++ b/stories/components/Title.stories.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react'; -import { Title, TitleSizeEnum } from '@procyon/components/Title'; -import { DirectionEnum } from '@procyon/types/common'; +import { Text } from '@procyon/components/Text'; +import { SizeEnum } from '@procyon/types/common'; -type Story = StoryObj; +type Story = StoryObj; export default { - component: Title, + component: Text, decorators: [ (Story) => ( <> @@ -19,7 +19,7 @@ export default { parameters: { docs: { description: { - component: "`import { Title } from '@procyon/components/Title';`", + component: "`import { Text } from '@procyon/components/Text';`", }, }, }, @@ -28,21 +28,20 @@ export default { export const Default: Story = { args: { - children: 'Default Title', + children: 'Default Text', }, }; export const Header: Story = { args: { children: 'Head title', - size: TitleSizeEnum.md, + size: SizeEnum.md, }, }; export const HeaderWithSpace: Story = { args: { children: 'Head title', - size: TitleSizeEnum.md, - margin: { [DirectionEnum.bottom]: 4 }, + size: SizeEnum.md, }, }; diff --git a/stories/components/Toasters.stories.tsx b/stories/components/Toasters.stories.tsx index e5455108..d93dab37 100644 --- a/stories/components/Toasters.stories.tsx +++ b/stories/components/Toasters.stories.tsx @@ -49,7 +49,7 @@ export const Hook: Story = { onClick={() => showToaster({ id: 'toaster1', - title: 'Title', + title: 'Text', message: 'Message', status: StatusEnum.info, }) @@ -76,7 +76,7 @@ export const OutsideReact: Story = { onClick={() => showToaster({ id: 'toaster2', - title: 'Title', + title: 'Text', message: 'Message', status: StatusEnum.success, }) From e8efe9859bd36a0fac44217474dd1f62e541c226 Mon Sep 17 00:00:00 2001 From: romanjaros Date: Thu, 2 Nov 2023 21:29:37 +0100 Subject: [PATCH 2/2] Typography - new small storybook section --- packages/constants/src/redux.ts | 1 - .../{Title.stories.tsx => Text.stories.tsx} | 20 +++++++++++--- stories/typography/Introduction.mdx | 27 +++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) rename stories/components/{Title.stories.tsx => Text.stories.tsx} (70%) create mode 100644 stories/typography/Introduction.mdx diff --git a/packages/constants/src/redux.ts b/packages/constants/src/redux.ts index 070836c2..031300a7 100644 --- a/packages/constants/src/redux.ts +++ b/packages/constants/src/redux.ts @@ -1,2 +1 @@ - export const ROOT_REDUCER_NAME = 'procyon'; diff --git a/stories/components/Title.stories.tsx b/stories/components/Text.stories.tsx similarity index 70% rename from stories/components/Title.stories.tsx rename to stories/components/Text.stories.tsx index 56bc1240..24d0474e 100644 --- a/stories/components/Title.stories.tsx +++ b/stories/components/Text.stories.tsx @@ -32,16 +32,30 @@ export const Default: Story = { }, }; -export const Header: Story = { +export const Standard: Story = { + args: { + children: 'Head title', + size: SizeEnum.sm, + }, +}; + +export const Middle: Story = { args: { children: 'Head title', size: SizeEnum.md, }, }; -export const HeaderWithSpace: Story = { +export const Large: Story = { args: { children: 'Head title', - size: SizeEnum.md, + size: SizeEnum.lg, + }, +}; + +export const ExtraLarge: Story = { + args: { + children: 'Head title', + size: SizeEnum.xl, }, }; diff --git a/stories/typography/Introduction.mdx b/stories/typography/Introduction.mdx new file mode 100644 index 00000000..57104856 --- /dev/null +++ b/stories/typography/Introduction.mdx @@ -0,0 +1,27 @@ +import { Meta } from '@storybook/blocks'; + + + +# Typography + +## Sizes + +Component for show text base on size is `Text` from `import { Text } from '@procyon/components/Text';` + +### Small (sm) + +- Standard font size for all page objects + +### Medium (md) + +- Section title +- Multiple times per page + +### Large (lg) + +- Page title +- Only once + +### Extra Large (xl) + +- For single page sections, like login or registration \ No newline at end of file