diff --git a/.storybook/main.js b/.storybook/main.js index d49fffc40..4ef614adb 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -13,7 +13,7 @@ module.exports = { return config; }, addons: [ - "@storybook/addon-knobs", + "@storybook/addon-toolbars", "@storybook/addon-viewport", { name: "@storybook/addon-storysource", @@ -26,6 +26,5 @@ module.exports = { "@storybook/addon-a11y", "@storybook/addon-actions", "storybook-addon-performance", - "./nds-theme/register.tsx", ], }; diff --git a/.storybook/nds-theme/ThemeInput.jsx b/.storybook/nds-theme/ThemeInput.jsx deleted file mode 100644 index b0900af9d..000000000 --- a/.storybook/nds-theme/ThemeInput.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import styled from "styled-components"; - -export const ThemeSelect = styled.select(({ theme }) => ({ - fontFamily: `${theme.fonts.mono} !important`, - padding: 0, - width: "100%", - fontSize: theme.fontSizes.small, - border: 0, - borderBottom: "1px solid #000", - transition: ".2s", - "&:focus": { - outline: "none", - boxShadow: "1px 1px 1px 0px rgba(0,0,0,1)", - }, - lineHeight: theme.lineHeights.base, -})); - -export const ThemeOption = styled.option(({ theme }) => ({ - fontFamily: `${theme.fonts.mono} !important`, - padding: 0, - width: "100%", - fontSize: theme.fontSizes.small, - border: 0, - borderBottom: "1px solid #000", - transition: ".2s", - "&:focus": { - outline: "none", - boxShadow: "1px 1px 1px 0px rgba(0,0,0,1)", - }, - lineHeight: theme.lineHeights.base, -})); diff --git a/.storybook/nds-theme/index.tsx b/.storybook/nds-theme/index.tsx deleted file mode 100644 index 92182e7d6..000000000 --- a/.storybook/nds-theme/index.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; -import { select } from "@storybook/addon-knobs"; -import { NDSProvider } from "../../src"; -import { ALL_NDS_LOCALES } from "../../src/locales.const"; -import { ComponentVariant } from "../../src/NDSProvider/ComponentVariantContext"; -import { useLocalStorage } from "./useLocalStorage/useLocalStorage"; - -const localeKnobOptions = ALL_NDS_LOCALES.reduce( - (obj, i) => ({ - ...obj, - [`${i.label} "${i.value}"`]: i.value, - }), - {} -); - -const StorybookNDSProvider = ({ children }) => { - const [themeVariant] = useLocalStorage("nds-sb-theme-variant", "desktop"); - - return ( - - {children} - - ); -}; - -export default StorybookNDSProvider; diff --git a/.storybook/nds-theme/register.tsx b/.storybook/nds-theme/register.tsx deleted file mode 100644 index 059ee5eea..000000000 --- a/.storybook/nds-theme/register.tsx +++ /dev/null @@ -1,64 +0,0 @@ -// .storybook/my-addon/register.js - -import React from "react"; -import { addons, types, RenderOptions } from "@storybook/addons"; -import { AddonPanel } from "@storybook/components"; -import { Box, Flex, NDSProvider, Heading3, Heading2, QuietButton } from "../../src"; -import { ComponentVariant } from "../../src/NDSProvider/ComponentVariantContext"; -import { ThemeOption, ThemeSelect } from "./ThemeInput"; -import { useLocalStorage } from "./useLocalStorage/useLocalStorage"; - -const ADDON_ID = "ndsThemeAddon"; -const PANEL_ID = `${ADDON_ID}/panel`; - -const DEFAULT_THEME_VARIANT = "desktop"; - -const ThemePanel = () => { - const [themeVariant, setThemeVariant] = useLocalStorage( - "nds-sb-theme-variant", - DEFAULT_THEME_VARIANT - ); - - const onVariantChange = (e) => { - const variant = e.target.value; - setThemeVariant(variant); - }; - - const reset = () => { - setThemeVariant(DEFAULT_THEME_VARIANT); - }; - - return ( - - - - - Theme - - - Reset all - - - Variant - - Desktop - Touch - - - - ); -}; - -const ThemeAddonPanel = ({ active, key }: RenderOptions) => ( - - - -); - -addons.register(ADDON_ID, () => { - addons.add(PANEL_ID, { - type: types.PANEL, - title: "Theme", - render: ThemeAddonPanel, - }); -}); diff --git a/.storybook/nds-theme/useLocalStorage/useEventCallback.ts b/.storybook/nds-theme/useLocalStorage/useEventCallback.ts deleted file mode 100644 index df62dcf18..000000000 --- a/.storybook/nds-theme/useLocalStorage/useEventCallback.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { useCallback, useRef } from "react"; -import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"; - -export function useEventCallback(fn: (...args: Args) => R): (...args: Args) => R; -export function useEventCallback( - fn: ((...args: Args) => R) | undefined -): ((...args: Args) => R) | undefined; - -export function useEventCallback( - fn: ((...args: Args) => R) | undefined -): ((...args: Args) => R) | undefined { - const ref = useRef(() => { - throw new Error("Cannot call an event handler while rendering."); - }); - - useIsomorphicLayoutEffect(() => { - ref.current = fn; - }, [fn]); - - return useCallback((...args: Args) => ref.current?.(...args), [ref]) as (...args: Args) => R; -} diff --git a/.storybook/nds-theme/useLocalStorage/useEventListener.ts b/.storybook/nds-theme/useLocalStorage/useEventListener.ts deleted file mode 100644 index b10d39882..000000000 --- a/.storybook/nds-theme/useLocalStorage/useEventListener.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { useEffect, useRef } from "react"; - -import type { RefObject } from "react"; -import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"; - -// MediaQueryList Event based useEventListener interface -function useEventListener( - eventName: K, - handler: (event: MediaQueryListEventMap[K]) => void, - element: RefObject, - options?: boolean | AddEventListenerOptions -): void; - -// Window Event based useEventListener interface -function useEventListener( - eventName: K, - handler: (event: WindowEventMap[K]) => void, - element?: undefined, - options?: boolean | AddEventListenerOptions -): void; - -// Element Event based useEventListener interface -function useEventListener< - K extends keyof HTMLElementEventMap & keyof SVGElementEventMap, - T extends Element = K extends keyof HTMLElementEventMap ? HTMLDivElement : SVGElement ->( - eventName: K, - handler: ((event: HTMLElementEventMap[K]) => void) | ((event: SVGElementEventMap[K]) => void), - element: RefObject, - options?: boolean | AddEventListenerOptions -): void; - -// Document Event based useEventListener interface -function useEventListener( - eventName: K, - handler: (event: DocumentEventMap[K]) => void, - element: RefObject, - options?: boolean | AddEventListenerOptions -): void; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -function useEventListener< - KW extends keyof WindowEventMap, - KH extends keyof HTMLElementEventMap & keyof SVGElementEventMap, - KM extends keyof MediaQueryListEventMap, - T extends HTMLElement | SVGAElement | MediaQueryList = HTMLElement ->( - eventName: KW | KH | KM, - handler: ( - event: WindowEventMap[KW] | HTMLElementEventMap[KH] | SVGElementEventMap[KH] | MediaQueryListEventMap[KM] | Event - ) => void, - element?: RefObject, - options?: boolean | AddEventListenerOptions -) { - // Create a ref that stores handler - const savedHandler = useRef(handler); - - useIsomorphicLayoutEffect(() => { - savedHandler.current = handler; - }, [handler]); - - useEffect(() => { - // Define the listening target - const targetElement: T | Window = element?.current ?? window; - - if (!(targetElement && targetElement.addEventListener)) return; - - // Create event listener that calls handler function stored in ref - const listener: typeof handler = (event) => { - savedHandler.current(event); - }; - - targetElement.addEventListener(eventName, listener, options); - - // Remove event listener on cleanup - return () => { - targetElement.removeEventListener(eventName, listener, options); - }; - }, [eventName, element, options]); -} - -export { useEventListener }; diff --git a/.storybook/nds-theme/useLocalStorage/useIsomorphicLayoutEffect.ts b/.storybook/nds-theme/useLocalStorage/useIsomorphicLayoutEffect.ts deleted file mode 100644 index fb2161a30..000000000 --- a/.storybook/nds-theme/useLocalStorage/useIsomorphicLayoutEffect.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { useEffect, useLayoutEffect } from "react"; - -export const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect; diff --git a/.storybook/nds-theme/useLocalStorage/useLocalStorage.ts b/.storybook/nds-theme/useLocalStorage/useLocalStorage.ts deleted file mode 100644 index c601c8b35..000000000 --- a/.storybook/nds-theme/useLocalStorage/useLocalStorage.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import type { Dispatch, SetStateAction } from "react"; -import { useEventCallback } from "./useEventCallback"; -import { useEventListener } from "./useEventListener"; - -declare global { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - interface WindowEventMap { - "local-storage": CustomEvent; - } -} - -type UseLocalStorageOptions = { - serializer?: (value: T) => string; - deserializer?: (value: string) => T; - initializeWithValue?: boolean; -}; - -const IS_SERVER = typeof window === "undefined"; - -export function useLocalStorage( - key: string, - initialValue: T | (() => T), - options: UseLocalStorageOptions = {} -): [T, Dispatch>, () => void] { - const { initializeWithValue = true } = options; - - const serializer = useCallback<(value: T) => string>( - (value) => { - if (options.serializer) { - return options.serializer(value); - } - - return JSON.stringify(value); - }, - [options] - ); - - const deserializer = useCallback<(value: string) => T>( - (value) => { - if (options.deserializer) { - return options.deserializer(value); - } - // Support 'undefined' as a value - if (value === "undefined") { - return undefined as unknown as T; - } - - const defaultValue = initialValue instanceof Function ? initialValue() : initialValue; - - let parsed: unknown; - try { - parsed = JSON.parse(value); - } catch (error) { - console.error("Error parsing JSON:", error); - return defaultValue; // Return initialValue if parsing fails - } - - return parsed as T; - }, - [options, initialValue] - ); - - // Get from local storage then - // parse stored json or return initialValue - const readValue = useCallback((): T => { - const initialValueToUse = initialValue instanceof Function ? initialValue() : initialValue; - - // Prevent build error "window is undefined" but keep working - if (IS_SERVER) { - return initialValueToUse; - } - - try { - const raw = window.localStorage.getItem(key); - return raw ? deserializer(raw) : initialValueToUse; - } catch (error) { - console.warn(`Error reading localStorage key “${key}”:`, error); - return initialValueToUse; - } - }, [initialValue, key, deserializer]); - - const [storedValue, setStoredValue] = useState(() => { - if (initializeWithValue) { - return readValue(); - } - - return initialValue instanceof Function ? initialValue() : initialValue; - }); - - // Return a wrapped version of useState's setter function that ... - // ... persists the new value to localStorage. - const setValue: Dispatch> = useEventCallback((value) => { - // Prevent build error "window is undefined" but keeps working - if (IS_SERVER) { - console.warn(`Tried setting localStorage key “${key}” even though environment is not a client`); - } - - try { - // Allow value to be a function so we have the same API as useState - const newValue = value instanceof Function ? value(readValue()) : value; - - // Save to local storage - window.localStorage.setItem(key, serializer(newValue)); - - // Save state - setStoredValue(newValue); - - // We dispatch a custom event so every similar useLocalStorage hook is notified - window.dispatchEvent(new StorageEvent("local-storage", { key })); - } catch (error) { - console.warn(`Error setting localStorage key “${key}”:`, error); - } - }); - - const removeValue = useEventCallback(() => { - // Prevent build error "window is undefined" but keeps working - if (IS_SERVER) { - console.warn(`Tried removing localStorage key “${key}” even though environment is not a client`); - } - - const defaultValue = initialValue instanceof Function ? initialValue() : initialValue; - - // Remove the key from local storage - window.localStorage.removeItem(key); - - // Save state with default value - setStoredValue(defaultValue); - - // We dispatch a custom event so every similar useLocalStorage hook is notified - window.dispatchEvent(new StorageEvent("local-storage", { key })); - }); - - useEffect(() => { - setStoredValue(readValue()); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [key]); - - const handleStorageChange = useCallback( - (event: StorageEvent | CustomEvent) => { - if ((event as StorageEvent).key && (event as StorageEvent).key !== key) { - return; - } - setStoredValue(readValue()); - }, - [key, readValue] - ); - - // this only works for other documents, not the current one - useEventListener("storage", handleStorageChange); - - // this is a custom event, triggered in writeValueToLocalStorage - // See: useLocalStorage() - useEventListener("local-storage", handleStorageChange); - - return [storedValue, setValue, removeValue]; -} diff --git a/.storybook/preview.jsx b/.storybook/preview.jsx deleted file mode 100644 index 41c1c1e5b..000000000 --- a/.storybook/preview.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from "react"; -import { create } from "@storybook/theming"; -import { desktop as theme } from "../src/theme"; -import StorybookNDSProvider from "./nds-theme"; - -const newViewports = { - extraSmall: { - name: "Extra small", - styles: { - width: "320px", - height: "100%", - }, - }, - small: { - name: "Small", - styles: { - width: theme.breakpoints.small, - height: "100%", - }, - }, - medium: { - name: "Medium", - styles: { - width: theme.breakpoints.medium, - height: "100%", - }, - }, - large: { - name: "Large", - styles: { - width: theme.breakpoints.large, - height: "100%", - }, - }, - extraLarge: { - name: "Extra Large", - styles: { - width: theme.breakpoints.extraLarge, - height: "100%", - }, - }, -}; - -export const parameters = { - viewport: { viewports: newViewports }, - layout: "padded", - options: { - storySort: { - method: "alphabetical", - }, - theme: create({ - gridCellSize: 8, - }), - }, -}; - -export const decorators = [ - (Story) => ( - - - - ), -]; diff --git a/package.json b/package.json index 8a19ea09b..168187cbe 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "ci": "yarn && yarn build && yarn test && yarn run check", "new": "plop", - "generate:theme": "npx tsx src/scripts/generateTheme.ts && prettier -w src/theme.ts", + "generate:theme": "npx tsx src/scripts/generateTheme.ts && prettier -w src/theme/theme.ts", "start": "concurrently \"yarn build --watch\" \"yarn start:storybook\"", "start:cypress": "yarn concurrently --kill-others \"yarn start --ci\" \"yarn wait-on http://localhost:9999 && cypress open\"", "start:storybook": "start-storybook -p 9999", @@ -82,7 +82,8 @@ "@storybook/addon-docs": "6.1.9", "@storybook/addon-knobs": "^6.1.9", "@storybook/addon-storysource": "^6.1.9", - "@storybook/addon-viewport": "^7.6.6", + "@storybook/addon-toolbars": "^6.1.9", + "@storybook/addon-viewport": "^6.1.9", "@storybook/codemod": "^6.1.9", "@storybook/react": "^6.3.12", "@storybook/theming": "^6.1.9", diff --git a/src/BottomSheet/BottomSheet.parts.story.tsx b/src/BottomSheet/BottomSheet.parts.story.tsx new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/BottomSheet/BottomSheet.parts.story.tsx @@ -0,0 +1 @@ + diff --git a/src/BrandedNavBar/DesktopMenu.tsx b/src/BrandedNavBar/DesktopMenu.tsx index 02da158bc..de529df44 100644 --- a/src/BrandedNavBar/DesktopMenu.tsx +++ b/src/BrandedNavBar/DesktopMenu.tsx @@ -2,7 +2,7 @@ import React from "react"; import styled from "styled-components"; import type { CSSObject } from "styled-components"; import { Icon } from "../Icon"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import MenuTrigger from "./MenuTrigger"; import type { MenuType } from "./MenuTrigger"; @@ -17,7 +17,7 @@ const getSharedStyles = (color, theme): CSSObject => { backgroundColor: "transparent", verticalAlign: "middle", lineHeight: theme.lineHeights.base, - fontSize: `${theme.fontSizes.medium}`, + fontSize: `${theme.fontSizes.base}`, padding: `${theme.space.x1} ${theme.space.x2}`, borderRadius: theme.radii.medium, }; diff --git a/src/BrandedNavBar/MenuTriggerButton.tsx b/src/BrandedNavBar/MenuTriggerButton.tsx index cf527e800..e6a54d5e9 100644 --- a/src/BrandedNavBar/MenuTriggerButton.tsx +++ b/src/BrandedNavBar/MenuTriggerButton.tsx @@ -2,7 +2,7 @@ import React from "react"; import styled, { CSSObject } from "styled-components"; import { themeGet } from "@styled-system/theme-get"; import { Icon } from "../Icon"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type StyledButtonProps = React.ComponentPropsWithRef<"button"> & { color?: string; @@ -23,7 +23,7 @@ const StyledButton = styled.button( textDecoration: "none", lineHeight: theme.lineHeights.base, transition: "background-color .2s", - fontSize: `${theme.fontSizes.medium}`, + fontSize: `${theme.fontSizes.base}`, padding: `${theme.space.x1} 28px ${theme.space.x1} ${theme.space.x2}`, borderRadius: theme.radii.medium, "&:hover, &:focus": { diff --git a/src/BrandedNavBar/NavBar.story.tsx b/src/BrandedNavBar/NavBar.story.tsx index ef22dce62..f8fb50699 100644 --- a/src/BrandedNavBar/NavBar.story.tsx +++ b/src/BrandedNavBar/NavBar.story.tsx @@ -5,7 +5,7 @@ import { BrowserRouter, Link as ReactRouterLink } from "react-router-dom"; import { Heading1 } from "../Type"; import { Icon } from "../Icon"; import { DropdownButton, DropdownLink } from "../DropdownMenu"; -import { desktop as theme } from "../theme"; +import { legacy as theme } from "../theme/theme"; import { Button } from "../Button"; import { Text } from "../Type"; import { BrandedNavBar as NDSBrandedNavBar } from "./index"; diff --git a/src/BrandedNavBar/NavBarBackground.tsx b/src/BrandedNavBar/NavBarBackground.tsx index d35e37aa8..fd2d540f9 100644 --- a/src/BrandedNavBar/NavBarBackground.tsx +++ b/src/BrandedNavBar/NavBarBackground.tsx @@ -1,5 +1,5 @@ import styled, { CSSObject } from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { Flex } from "../Flex"; import { addStyledProps, StyledProps } from "../StyledProps"; diff --git a/src/BrandedNavBar/SmallNavBar.story.tsx b/src/BrandedNavBar/SmallNavBar.story.tsx index e4d9165e3..d31bdd600 100644 --- a/src/BrandedNavBar/SmallNavBar.story.tsx +++ b/src/BrandedNavBar/SmallNavBar.story.tsx @@ -1,13 +1,13 @@ +import { select } from "@storybook/addon-knobs"; import React from "react"; import styled from "styled-components"; -import { select } from "@storybook/addon-knobs"; -import { Heading1 } from "../Type"; import { Branding } from "../Branding"; -import { Link } from "../Link"; import { Button, SmallNavBarProps } from "../index"; +import { Link } from "../Link"; +import { legacy as theme } from "../theme/theme"; +import { Heading1 } from "../Type"; import BrandLogoContainer from "./BrandLogoContainer"; import { SmallNavBar } from "./index"; -import { desktop as theme } from "../theme"; const ResetStorybookView = styled.div({ position: "absolute", diff --git a/src/BrandedNavBar/SmallNavBar.tsx b/src/BrandedNavBar/SmallNavBar.tsx index f5e2ab6b4..49102d2e4 100644 --- a/src/BrandedNavBar/SmallNavBar.tsx +++ b/src/BrandedNavBar/SmallNavBar.tsx @@ -2,7 +2,7 @@ import styled, { CSSObject, useTheme } from "styled-components"; import { useTranslation } from "react-i18next"; import React, { useEffect } from "react"; import { Icon } from "../Icon"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { Flex } from "../Flex"; import NavBarSearch from "../NavBarSearch/NavBarSearch"; import { PreventBodyElementScrolling, withMenuState, WithMenuStateProps, AcceptsMenuStateProps } from "../utils"; diff --git a/src/Branding/Branding.tsx b/src/Branding/Branding.tsx index a0a009515..affdbcd9c 100644 --- a/src/Branding/Branding.tsx +++ b/src/Branding/Branding.tsx @@ -4,7 +4,7 @@ import { Flex } from "../Flex"; import BrandingText from "./BrandingText"; import LettermarkLogo from "./LettermarkLogo"; import WordmarkLogo from "./WordmarkLogo"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type BrandingProps = { logoType?: "wordmark" | "lettermark"; diff --git a/src/Breadcrumbs/BreadcrumbsListItem.tsx b/src/Breadcrumbs/BreadcrumbsListItem.tsx index 10bcdae2b..56a6d9257 100644 --- a/src/Breadcrumbs/BreadcrumbsListItem.tsx +++ b/src/Breadcrumbs/BreadcrumbsListItem.tsx @@ -10,7 +10,7 @@ export const BreadcrumbsListSeparator = styled.li( alignSelf: "center", color: theme.colors.midGrey, "a, p": { - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, }, "a:visited": { color: theme.colors.darkBlue, @@ -48,7 +48,7 @@ export const BreadcrumbsListItem = styled.li<{ variant: ComponentVariant }>( "a, p": { py: "x2", px: "x0", - fontSize: "medium", + fontSize: "base", }, }, desktop: { diff --git a/src/Button/Button.tsx b/src/Button/Button.tsx index b43307260..50497c86e 100644 --- a/src/Button/Button.tsx +++ b/src/Button/Button.tsx @@ -2,7 +2,7 @@ import React from "react"; import styled, { useTheme } from "styled-components"; import { space, SpaceProps, variant } from "styled-system"; import { Icon } from "../Icon"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { useComponentVariant, ComponentVariant as ContextComponentSize, @@ -35,7 +35,7 @@ const WrapperButton = styled.button( display: "inline-flex", justifyContent: "center", alignItems: "center", - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, fontWeight: theme.fontWeights.medium, textDecoration: "none", verticalAlign: "middle", @@ -78,11 +78,19 @@ const WrapperButton = styled.button( }, medium: { - fontSize: "medium", + fontSize: "base", padding: `${subPx(theme.space.x1)} ${theme.space.x2}`, }, }, }), + variant({ + variants: { + touch: { + fontSize: "md", + lineHeight: "base", + }, + }, + }), space ); diff --git a/src/Button/DangerButton.tsx b/src/Button/DangerButton.tsx index 6695ab758..f6d6ade67 100644 --- a/src/Button/DangerButton.tsx +++ b/src/Button/DangerButton.tsx @@ -1,7 +1,7 @@ import styled from "styled-components"; import { darken } from "polished"; import Button, { ButtonProps } from "./Button"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type DangerButtonProps = ButtonProps & { disabled?: boolean; diff --git a/src/Button/IconicButton.tsx b/src/Button/IconicButton.tsx index 66d7b7feb..dfc710e9d 100644 --- a/src/Button/IconicButton.tsx +++ b/src/Button/IconicButton.tsx @@ -6,7 +6,7 @@ import { transparentize } from "polished"; import icons from "@nulogy/icons"; import { Icon } from "../Icon"; import { Text } from "../Type"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { ComponentVariant, useComponentVariant } from "../NDSProvider/ComponentVariantContext"; interface BaseProps { diff --git a/src/Checkbox/Checkbox.tsx b/src/Checkbox/Checkbox.tsx index 1b0ba3e99..3f8e1dde3 100644 --- a/src/Checkbox/Checkbox.tsx +++ b/src/Checkbox/Checkbox.tsx @@ -6,7 +6,7 @@ import { Box } from "../Box"; import { Text } from "../Type"; import { ClickInputLabel } from "../utils"; import { getSubset, omitSubset } from "../utils/subset"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { addStyledProps } from "../StyledProps"; import { ComponentVariant, useComponentVariant } from "../NDSProvider/ComponentVariantContext"; diff --git a/src/DatePicker/DatePicker.tsx b/src/DatePicker/DatePicker.tsx index eed4e4be6..b1bd30f7f 100644 --- a/src/DatePicker/DatePicker.tsx +++ b/src/DatePicker/DatePicker.tsx @@ -146,6 +146,7 @@ const DatePicker = forwardRef( {({ locale }) => ( (({ theme }) => ({ ".nds-date-picker": { @@ -49,7 +49,7 @@ export const DatePickerStyles = createGlobalStyle<{ theme: DefaultNDSThemeType } }, }, ".react-datepicker__day": { - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, borderRadius: theme.radii.medium, color: theme.colors.darkGrey, border: "2px solid transparent", @@ -83,10 +83,9 @@ export const DatePickerStyles = createGlobalStyle<{ theme: DefaultNDSThemeType } cursor: "pointer", }, }, - ".react-datepicker__day--disabled:hover,.react-datepicker__month-text--disabled:hover,.react-datepicker__quarter-text--disabled:hover": - { - backgroundColor: "transparent", - }, + ".react-datepicker__day--disabled:hover,.react-datepicker__month-text--disabled:hover,.react-datepicker__quarter-text--disabled:hover": { + backgroundColor: "transparent", + }, ".react-datepicker__day-names, .react-datepicker__week": { whiteSpace: "nowrap", }, diff --git a/src/DropdownMenu/DropdownButton.tsx b/src/DropdownMenu/DropdownButton.tsx index 12ce79e4e..e4d9eb15e 100644 --- a/src/DropdownMenu/DropdownButton.tsx +++ b/src/DropdownMenu/DropdownButton.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled from "styled-components"; import { variant } from "styled-system"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { addStyledProps, StyledProps } from "../StyledProps"; import { ComponentVariant } from "../NDSProvider/ComponentVariantContext"; @@ -25,7 +25,7 @@ const DropdownButton = styled.button( textAlign: "left", backgroundColor: "transparent", lineHeight: theme.lineHeights.base, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, transition: ".2s", borderLeft: `${theme.space.half} solid transparent`, paddingTop: theme.space.x1, diff --git a/src/DropdownMenu/DropdownItem.tsx b/src/DropdownMenu/DropdownItem.tsx index eeb3271ae..521701151 100644 --- a/src/DropdownMenu/DropdownItem.tsx +++ b/src/DropdownMenu/DropdownItem.tsx @@ -19,7 +19,7 @@ const DropdownItem = styled.div( backgroundColor: "transparent", lineHeight: theme.lineHeights.base, transition: ".2s", - fontSize: `${theme.fontSizes.medium}`, + fontSize: `${theme.fontSizes.base}`, padding: `${theme.space.x1} ${theme.space.x2}`, "&:hover, &:focus": { outline: "none", diff --git a/src/DropdownMenu/DropdownLink.tsx b/src/DropdownMenu/DropdownLink.tsx index 3eac019a0..fc7de76dd 100644 --- a/src/DropdownMenu/DropdownLink.tsx +++ b/src/DropdownMenu/DropdownLink.tsx @@ -26,7 +26,7 @@ const DropdownLink = styled.a.withConfig({ borderColor: "transparent", backgroundColor: "transparent", lineHeight: theme.lineHeights.base, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, transition: ".2s", borderLeft: `${theme.space.half} solid transparent`, "&:visited": { diff --git a/src/DropdownMenu/DropdownMenuContainer.tsx b/src/DropdownMenu/DropdownMenuContainer.tsx index 17116e550..71a83f357 100644 --- a/src/DropdownMenu/DropdownMenuContainer.tsx +++ b/src/DropdownMenu/DropdownMenuContainer.tsx @@ -1,7 +1,7 @@ import styled from "styled-components"; import { color } from "styled-system"; import { Box } from "../Box"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type DropdownMenuContainerProps = { id?: string; diff --git a/src/Form/Form.tsx b/src/Form/Form.tsx index 61df2078e..9735565a9 100644 --- a/src/Form/Form.tsx +++ b/src/Form/Form.tsx @@ -4,7 +4,7 @@ import { space } from "styled-system"; import type { SpaceProps } from "styled-system"; import { Heading2 } from "../Type"; import { Alert } from "../Alert"; -import type { ThemeType } from "../theme.type"; +import type { ThemeType } from "../theme"; import Field from "./Field"; import Fieldset from "./Fieldset"; import FormSection from "./FormSection"; diff --git a/src/Input/InputField.tsx b/src/Input/InputField.tsx index 4e4e767a7..a96f24258 100644 --- a/src/Input/InputField.tsx +++ b/src/Input/InputField.tsx @@ -6,7 +6,7 @@ import { Box, BoxProps } from "../Box"; import { Flex } from "../Flex"; import { subPx } from "../utils"; import { MaybeFieldLabel } from "../FieldLabel"; -import type { DefaultNDSThemeType } from "../theme.type"; +import type { DefaultNDSThemeType } from "../theme"; import { ComponentVariant, useComponentVariant } from "../NDSProvider/ComponentVariantContext"; import Prefix from "./Prefix"; import Suffix from "./Suffix"; @@ -109,7 +109,7 @@ const StyledInput = styled.input( flexGrow: 1, border: "1px solid", borderRadius: theme.radii.medium, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, lineHeight: theme.lineHeights.base, margin: theme.space.none, minHeight: theme.space.x5, diff --git a/src/Layout/Header.story.tsx b/src/Layout/Header.story.tsx index 2315f19d5..912dfe2e4 100644 --- a/src/Layout/Header.story.tsx +++ b/src/Layout/Header.story.tsx @@ -17,7 +17,7 @@ import SummaryItem from "../Summary/SummaryItem"; import SummaryDivider from "../Summary/SummaryDivider"; import DropdownMenu from "../DropdownMenu/DropdownMenu"; import numberFromDimension from "../utils/numberFromDimension"; -import { desktop as theme } from "../theme"; +import { legacy as theme } from "../theme/theme"; export const Default = () => (
( ...resetButtonStyles, padding: as === "button" ? "0" : undefined, textDecoration: underline ? "underline" : "none", - fontSize: props.theme.fontSizes.medium, + fontSize: props.theme.fontSizes.base, color: getColor(props), "&:hover": { cursor: "pointer", diff --git a/src/Modal/Modal.tsx b/src/Modal/Modal.tsx index 50013fe15..206aa2e10 100644 --- a/src/Modal/Modal.tsx +++ b/src/Modal/Modal.tsx @@ -54,7 +54,7 @@ const StyledReactModal = styled(ReactModal)( boxSizing: "border-box", }, color: theme.colors.black, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, lineHeight: theme.lineHeights.base, WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale", diff --git a/src/Modal/ModalContent.tsx b/src/Modal/ModalContent.tsx index f44806218..88da3feaa 100644 --- a/src/Modal/ModalContent.tsx +++ b/src/Modal/ModalContent.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type ModalContentProps = React.ComponentPropsWithRef<"div"> & { hasFooter?: any; diff --git a/src/Modal/ModalHeader.tsx b/src/Modal/ModalHeader.tsx index 8e35a65de..97c5ec3f5 100644 --- a/src/Modal/ModalHeader.tsx +++ b/src/Modal/ModalHeader.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled, { CSSObject } from "styled-components"; import { transparentize } from "polished"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; const getHeaderPaddingRight = (closeButtonIncluded?: boolean, theme?: DefaultNDSThemeType) => closeButtonIncluded ? theme.space.x8 : theme.space.x3; diff --git a/src/NDSProvider/ComponentVariantContext.tsx b/src/NDSProvider/ComponentVariantContext.tsx index ba753b5df..6bd3a79f6 100644 --- a/src/NDSProvider/ComponentVariantContext.tsx +++ b/src/NDSProvider/ComponentVariantContext.tsx @@ -7,12 +7,12 @@ type ComponentVariantContextValue = { children?: React.ReactNode; }; +export const ComponentVariantContext = createContext(undefined); + export default function ComponentVariantContextProvider({ variant, children }: ComponentVariantContextValue) { return {children}; } -export const ComponentVariantContext = createContext(undefined); - export function useComponentVariant(selectedVariant?: ComponentVariant) { const context = useContext(ComponentVariantContext); if (!context) { diff --git a/src/NDSProvider/GlobalStyles.tsx b/src/NDSProvider/GlobalStyles.tsx index 644838cfb..8430e4961 100644 --- a/src/NDSProvider/GlobalStyles.tsx +++ b/src/NDSProvider/GlobalStyles.tsx @@ -1,37 +1,39 @@ import styled, { CSSObject } from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; export type GlobalStylesProps = { theme?: DefaultNDSThemeType; locale?: string; }; -const GlobalStyles = styled.div(({ theme, locale }: GlobalStylesProps): CSSObject => { - const fontFamily = locale === "zh_CN" ? theme.fonts.sc : theme.fonts.base; - return { - color: theme.colors.black, - fontFamily, - fontSize: theme.fontSizes.medium, - lineHeight: theme.lineHeights.base, - "-webkit-font-smoothing": "antialiased", - "-moz-osx-font-smoothing": "grayscale", - "*": { - boxSizing: "border-box", - }, - img: { - maxWidth: "100%", - height: "auto", - }, - button: { +const GlobalStyles = styled.div( + ({ theme, locale }: GlobalStylesProps): CSSObject => { + const fontFamily = locale === "zh_CN" ? theme.fonts.sc : theme.fonts.base; + return { + color: theme.colors.black, fontFamily, - }, - input: { - fontFamily, - }, - textarea: { - fontFamily, - }, - }; -}); + fontSize: theme.fontSizes.base, + lineHeight: theme.lineHeights.base, + "-webkit-font-smoothing": "antialiased", + "-moz-osx-font-smoothing": "grayscale", + "*": { + boxSizing: "border-box", + }, + img: { + maxWidth: "100%", + height: "auto", + }, + button: { + fontFamily, + }, + input: { + fontFamily, + }, + textarea: { + fontFamily, + }, + }; + } +); export default GlobalStyles; diff --git a/src/NDSProvider/GlobalStylesComposer.tsx b/src/NDSProvider/GlobalStylesComposer.tsx index ec89ce351..3ecde70e1 100644 --- a/src/NDSProvider/GlobalStylesComposer.tsx +++ b/src/NDSProvider/GlobalStylesComposer.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import Reset from "./Reset"; import ModalStyleOverride from "./ModalStyleOverride"; import GlobalStyles from "./GlobalStyles"; diff --git a/src/NDSProvider/ModalStyleOverride.tsx b/src/NDSProvider/ModalStyleOverride.tsx index c2f4b01dd..9830827e7 100644 --- a/src/NDSProvider/ModalStyleOverride.tsx +++ b/src/NDSProvider/ModalStyleOverride.tsx @@ -10,7 +10,7 @@ const ModalStyleOverride = createGlobalStyle(({ theme, locale }: GlobalStylesPro "*": { boxSizing: "border-box" }, color: theme.colors.black, fontFamily, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, lineHeight: theme.lineHeights.base, img: { maxWidth: "100%", diff --git a/src/NDSProvider/NDSProvider.tsx b/src/NDSProvider/NDSProvider.tsx index 903b2f7da..f120fdce9 100644 --- a/src/NDSProvider/NDSProvider.tsx +++ b/src/NDSProvider/NDSProvider.tsx @@ -1,12 +1,12 @@ import React, { useEffect } from "react"; -import { ThemeProvider } from "styled-components"; import { I18nextProvider } from "react-i18next"; import i18n from "../i18n"; -import { ThemeType } from "../theme.type"; -import { LocaleContext } from "./LocaleContext"; +import { ThemeType } from "../theme"; +import NDSThemeProvider from "../theme/NDSThemeProvider"; import ComponentVariantContextProvider, { ComponentVariant } from "./ComponentVariantContext"; +import FutureFlagsContextProvider, { FutureFlags } from "./FutureFlagsContext"; import GlobalStylesComposer from "./GlobalStylesComposer"; -import { useNDSTheme } from "./useNDSTheme"; +import { LocaleContext } from "./LocaleContext"; type NDSProviderProps = { theme?: ThemeType; @@ -14,6 +14,7 @@ type NDSProviderProps = { disableGlobalStyles?: boolean; children?: React.ReactNode; variant?: ComponentVariant; + futureFlags?: FutureFlags; }; function NDSProvider({ @@ -22,22 +23,27 @@ function NDSProvider({ disableGlobalStyles = false, locale = "en_US", variant = "desktop", + futureFlags = { + newDesktopTypographyScale: false, + }, }: NDSProviderProps) { useEffect(() => { i18n.changeLanguage(locale); }, [locale]); - const theme = useNDSTheme(variant, customTheme); - return ( - - + + - {children} + + + {children} + + - - + + ); } diff --git a/src/NDSProvider/mergeThemes.spec.tsx b/src/NDSProvider/mergeThemes.spec.tsx deleted file mode 100644 index 310e5316c..000000000 --- a/src/NDSProvider/mergeThemes.spec.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { mergeThemes } from "./mergeThemes.util"; -import { desktop as NDSTheme } from "../theme"; - -describe("mergedThemes", () => { - it("returns the default nds theme if custom theme is undefined", () => { - const actual = mergeThemes(NDSTheme, undefined); - const expected = NDSTheme; - expect(actual).toEqual(expected); - }); - it("uses the custom theme for properties that are set and uses the default theme for the rest", () => { - const actual = mergeThemes(NDSTheme, { - fontSizes: { - medium: "14px", - small: "12px", - smaller: "12px", - }, - }); - const expected = { - ...NDSTheme, - fontSizes: { - ...NDSTheme.fontSizes, - medium: "14px", - small: "12px", - smaller: "12px", - }, - }; - expect(actual).toEqual(expected); - expect(actual.fontSizes.large).toEqual(expected.fontSizes.large); - expect(actual.colors).toEqual(expected.colors); - }); - it("uses the custom theme for multiple style groups that are set and uses the default theme for the rest", () => { - const actual = mergeThemes(NDSTheme, { - fontSizes: { - medium: "14px", - small: "12px", - smaller: "12px", - }, - colors: { - black: "#FFF", - }, - space: { - x1: "6px", - }, - }); - const expected = { - ...NDSTheme, - fontSizes: { - ...NDSTheme.fontSizes, - medium: "14px", - small: "12px", - }, - colors: { - ...NDSTheme.colors, - black: "#FFF", - }, - space: { - ...NDSTheme.space, - x1: "6px", - }, - }; - expect(actual).toEqual(expected); - expect(actual.fontSizes.large).toEqual(expected.fontSizes.large); - expect(actual.colors.white).toEqual(expected.colors.white); - }); -}); diff --git a/src/NDSProvider/mergeThemes.util.ts b/src/NDSProvider/mergeThemes.util.ts deleted file mode 100644 index 39a77df64..000000000 --- a/src/NDSProvider/mergeThemes.util.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { DefaultNDSThemeType, ThemeType } from "../theme.type"; - -export const mergeThemes = (theme: DefaultNDSThemeType, customTheme: ThemeType): DefaultNDSThemeType => - Object.keys(theme).reduce((mergedTheme, group) => { - if (customTheme && mergedTheme[group] && customTheme[group]) { - return { - ...mergedTheme, - [group]: { - ...mergedTheme[group], - ...customTheme[group], - }, - }; - } - return mergedTheme; - }, theme); diff --git a/src/NDSProvider/useNDSTheme.tsx b/src/NDSProvider/useNDSTheme.tsx deleted file mode 100644 index 634738bae..000000000 --- a/src/NDSProvider/useNDSTheme.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { useState, useEffect } from "react"; -import { desktop, themes } from "../theme"; -import { ThemeType, DefaultNDSThemeType, Breakpoints } from "../theme.type"; -import useMediaQuery from "../hooks/useMediaQuery"; -import { mergeThemes } from "./mergeThemes.util"; -import { ComponentVariant } from "./ComponentVariantContext"; - -const THEME_VARIANTS: ReadonlySet = new Set(["desktop", "touch"]); - -export const buildBreakPoints = (breakpointsConfig: Readonly) => ({ - ...breakpointsConfig, - map: function (fn: (value: string) => T) { - return Object.values(breakpointsConfig).map(fn); - }, -}); - -const validateVariantOrThrow = (variant: ComponentVariant): void => { - if (!THEME_VARIANTS.has(variant)) { - throw new Error( - `Invalid variant "${variant}" provided to NDSProvider. Valid variants are: ${Array.from(THEME_VARIANTS).join( - ", " - )}.` - ); - } -}; - -export const getThemeByVariant = (variant: ComponentVariant, isTabletSize: boolean): DefaultNDSThemeType => { - if (variant === "touch") { - return isTabletSize ? themes.tablet : themes.phone; - } - return themes.desktop; -}; - -export function useNDSTheme(variant: ComponentVariant = "desktop", customTheme?: ThemeType): DefaultNDSThemeType { - validateVariantOrThrow(variant); - - const [themeVariant, setThemeVariant] = useState(desktop); - const isTabletSize = useMediaQuery(`(min-width: ${desktop.breakpoints.small})`); - - useEffect(() => { - const newTheme = getThemeByVariant(variant, isTabletSize); - setThemeVariant(newTheme); - }, [variant, isTabletSize]); - - const mergedTheme = mergeThemes(themeVariant, customTheme); - return { - ...mergedTheme, - breakpoints: buildBreakPoints(mergedTheme.breakpoints), - }; -} diff --git a/src/Pagination/PaginationButton.tsx b/src/Pagination/PaginationButton.tsx index 57a93498f..1204f5b11 100644 --- a/src/Pagination/PaginationButton.tsx +++ b/src/Pagination/PaginationButton.tsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; const getHoverBackground = (currentPage: boolean, disabled: boolean, theme: DefaultNDSThemeType) => { if (currentPage) { diff --git a/src/Radio/Radio.tsx b/src/Radio/Radio.tsx index b992bc767..2fcaecb9a 100644 --- a/src/Radio/Radio.tsx +++ b/src/Radio/Radio.tsx @@ -5,7 +5,7 @@ import { SpaceProps } from "styled-system"; import { Box } from "../Box"; import { Text } from "../Type"; import { ClickInputLabel } from "../utils"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { getSubset, omitSubset } from "../utils/subset"; import { ComponentVariant, useComponentVariant } from "../NDSProvider/ComponentVariantContext"; diff --git a/src/Radio/RadioGroup.tsx b/src/Radio/RadioGroup.tsx index f757104c0..f91881525 100644 --- a/src/Radio/RadioGroup.tsx +++ b/src/Radio/RadioGroup.tsx @@ -3,7 +3,7 @@ import { CSSObject, ThemeContext, useTheme } from "styled-components"; import { HelpText, RequirementText } from "../FieldLabel"; import { InlineValidation } from "../Validation"; import { Fieldset } from "../Form"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import Radio from "./Radio"; interface RadioGroupProps { diff --git a/src/Select/customReactSelectStyles.spec.tsx b/src/Select/customReactSelectStyles.spec.tsx index 31083eeb5..d2cf415e5 100644 --- a/src/Select/customReactSelectStyles.spec.tsx +++ b/src/Select/customReactSelectStyles.spec.tsx @@ -1,4 +1,4 @@ -import { desktop as theme } from "../theme"; +import { desktop as theme } from "../theme/theme"; import { getControlBorderRadius, getMenuBorderRadius, showIndicatorSeparator } from "./customReactSelectStyles"; describe("custom react-select styles", () => { diff --git a/src/Select/customReactSelectStyles.tsx b/src/Select/customReactSelectStyles.tsx index b0ef73cfb..6485540fd 100644 --- a/src/Select/customReactSelectStyles.tsx +++ b/src/Select/customReactSelectStyles.tsx @@ -2,7 +2,7 @@ import { transparentize } from "polished"; import type { CSSObject } from "styled-components"; import type { GroupBase, MenuPlacement, StylesConfig } from "react-select"; import type { CSSProperties } from "react"; -import type { DefaultNDSThemeType } from "../theme.type"; +import type { DefaultNDSThemeType } from "../theme"; import type { ComponentVariant } from "../NDSProvider/ComponentVariantContext"; const getBorderColor = ({ @@ -115,7 +115,7 @@ const customStyles: & { breakpoint?: number | string; diff --git a/src/Switcher/Switch.tsx b/src/Switcher/Switch.tsx index 72e61a7be..1d3eae433 100644 --- a/src/Switcher/Switch.tsx +++ b/src/Switcher/Switch.tsx @@ -26,7 +26,7 @@ const SwitchButton = styled.button( cursor: "pointer", border: "none", borderRadius: 9999, // todo: move to a token - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, fontWeight: theme.fontWeights.medium, lineHeight: theme.lineHeights.base, textDecoration: "none", diff --git a/src/Table/BaseTable.story.tsx b/src/Table/BaseTable.story.tsx index 2f6e96731..ec4ec12ca 100644 --- a/src/Table/BaseTable.story.tsx +++ b/src/Table/BaseTable.story.tsx @@ -343,7 +343,7 @@ export const WithMetadata = () => ( headerFormatter: ({ label, metadata }) => ( {label} - + {metadata.helpText} diff --git a/src/Table/StyledTh.tsx b/src/Table/StyledTh.tsx index e0b0a981f..74c6137d6 100644 --- a/src/Table/StyledTh.tsx +++ b/src/Table/StyledTh.tsx @@ -1,5 +1,5 @@ import styled, { CSSObject } from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; const stickyStyles = (theme: DefaultNDSThemeType): CSSObject => ({ position: "sticky", diff --git a/src/Table/TableBody.tsx b/src/Table/TableBody.tsx index 36beeabd8..23e6d6f90 100644 --- a/src/Table/TableBody.tsx +++ b/src/Table/TableBody.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled from "styled-components"; import { Box } from "../Box"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import TableCell from "./TableCell"; const StyledMessageContainer = styled(Box)(({ theme }) => ({ diff --git a/src/Table/TableCell.tsx b/src/Table/TableCell.tsx index d51bf69ad..6572f0bc9 100644 --- a/src/Table/TableCell.tsx +++ b/src/Table/TableCell.tsx @@ -1,6 +1,6 @@ import React, { CSSProperties } from "react"; import styled, { CSSObject } from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type StyledTableCellProps = { align?: CSSProperties["textAlign"]; diff --git a/src/Tabs/Tab.tsx b/src/Tabs/Tab.tsx index c2447e9bb..b78dcf643 100644 --- a/src/Tabs/Tab.tsx +++ b/src/Tabs/Tab.tsx @@ -51,7 +51,7 @@ const TabButton = styled.button( width: fullWidth ? "100%" : undefined, fontWeight: theme.fontWeights.medium, textDecoration: "none", - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, lineHeight: theme.lineHeights.base, cursor: disabled ? "default" : "pointer", color: theme.colors.darkBlue, diff --git a/src/Textarea/StyledTextarea.tsx b/src/Textarea/StyledTextarea.tsx index aa4b22679..dcb5f5209 100644 --- a/src/Textarea/StyledTextarea.tsx +++ b/src/Textarea/StyledTextarea.tsx @@ -4,7 +4,7 @@ import { transparentize } from "polished"; import { SpaceProps, variant } from "styled-system"; import { space } from "styled-system"; import { subPx } from "../utils"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { ComponentVariant } from "../NDSProvider/ComponentVariantContext"; export type StyledTextareaProps = React.ComponentPropsWithRef<"textarea"> & @@ -52,7 +52,7 @@ const StyledTextarea = styled.textarea( width: "100%", border: "1px solid", borderRadius: theme.radii.medium, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, lineHeight: theme.lineHeights.base, minHeight: theme.space.x5, minWidth: "20em", diff --git a/src/ToastContainer/ToastContainer.tsx b/src/ToastContainer/ToastContainer.tsx index 016892afb..3bb9b42ea 100644 --- a/src/ToastContainer/ToastContainer.tsx +++ b/src/ToastContainer/ToastContainer.tsx @@ -1,10 +1,9 @@ import React, { useEffect } from "react"; import { toast as _toast, Toaster, ToasterProps, useToasterStore } from "react-hot-toast"; import { useTheme } from "styled-components"; -import numberFromDimension from "../utils/numberFromDimension"; import { TOAST_SHOW_DURATION } from "../Toast/Toast"; +import numberFromDimension from "../utils/numberFromDimension"; import { ToastOptions } from "./ToastFunction"; -import { DefaultNDSThemeType } from "../theme.type"; type ToastContainerProps = { gap?: number; diff --git a/src/Toggle/Toggle.tsx b/src/Toggle/Toggle.tsx index a5d8f6006..44ecb856f 100644 --- a/src/Toggle/Toggle.tsx +++ b/src/Toggle/Toggle.tsx @@ -8,7 +8,7 @@ import { Field } from "../Form"; import { Text } from "../Type"; import { ComponentVariant, useComponentVariant } from "../NDSProvider/ComponentVariantContext"; import { ClickInputLabel } from "../utils"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { getSubset, omitSubset } from "../utils/subset"; import ToggleButton from "./ToggleButton"; diff --git a/src/Toggle/ToggleButton.tsx b/src/Toggle/ToggleButton.tsx index e224deda5..33783a935 100644 --- a/src/Toggle/ToggleButton.tsx +++ b/src/Toggle/ToggleButton.tsx @@ -3,7 +3,7 @@ import { motion } from "framer-motion"; import type { TransformProperties } from "framer-motion/types/motion/types"; import type { Transition } from "framer-motion"; import styled, { CSSObject, useTheme } from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; import { AnimatedBox } from "../Box"; type SwitchProps = { diff --git a/src/Tooltip/TooltipContainer.tsx b/src/Tooltip/TooltipContainer.tsx index c54148572..5b957d8cd 100644 --- a/src/Tooltip/TooltipContainer.tsx +++ b/src/Tooltip/TooltipContainer.tsx @@ -1,7 +1,7 @@ import styled from "styled-components"; import { PositionProps } from "styled-system"; import { Box } from "../Box"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; type TooltipContainerProps = PositionProps & { theme?: DefaultNDSThemeType; diff --git a/src/Type/Text.tsx b/src/Type/Text.tsx index e8b04e01d..eab8fcf2a 100644 --- a/src/Type/Text.tsx +++ b/src/Type/Text.tsx @@ -29,7 +29,7 @@ const Text = styled.p( color: "currentColor", marginTop: 0, marginBottom: 0, - fontSize: theme.fontSizes.medium, + fontSize: theme.fontSizes.base, lineHeight: theme.lineHeights.base, opacity: disabled ? "0.7" : undefined, display: inline ? "inline" : undefined, diff --git a/src/index.ts b/src/index.ts index e7ac2219a..da6e4870a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -71,7 +71,7 @@ export { Table } from "./Table"; export type { TableCellInfoType, TableColumnType, TableProps, TableRowType } from "./Table"; export { Tab, Tabs } from "./Tabs"; export { Textarea } from "./Textarea"; -export type { ThemeType, DefaultNDSThemeType } from "./theme.type"; +export type { ThemeType, DefaultNDSThemeType } from "./theme"; export { TimePicker } from "./TimePicker"; export { TimeRange } from "./TimeRange"; export { Toast } from "./Toast"; diff --git a/src/scripts/generateTheme.ts b/src/scripts/generateTheme.ts index b47d6301a..d3c52f744 100644 --- a/src/scripts/generateTheme.ts +++ b/src/scripts/generateTheme.ts @@ -1,7 +1,7 @@ import fs from "fs"; import path from "path"; import * as tokens from "@nulogy/tokens"; -import { DefaultNDSThemeType } from "../theme.type"; +import { DefaultNDSThemeType } from "../theme"; const deviceBaseUnits = { tablet: 5.6, @@ -77,7 +77,7 @@ const BASE_THEME = { }, }; -const desktop: DefaultNDSThemeType = { +const legacy: DefaultNDSThemeType = { ...BASE_THEME, fontSizes: { smaller: tokens.size_font_smaller, @@ -86,6 +86,14 @@ const desktop: DefaultNDSThemeType = { large: tokens.size_font_large, larger: tokens.size_font_larger, largest: tokens.size_font_largest, + base: tokens.size_font_medium, + xxs: tokens.size_font_smaller, + xs: tokens.size_font_smaller, + sm: tokens.size_font_small, + md: tokens.size_font_medium, + lg: tokens.size_font_large, + xl: tokens.size_font_larger, + xxl: tokens.size_font_largest, heading1: tokens.size_font_heading_1, heading2: tokens.size_font_heading_2, heading3: tokens.size_font_heading_3, @@ -171,17 +179,26 @@ function generateThemeConfig(baseUnit: number): DefaultNDSThemeType { const fontSizes = { smaller: baseUnit * 3, small: baseUnit * 3.75, - medium: baseUnit * 4.5, + medium: baseUnit * 3.75, large: baseUnit * 5.25, larger: baseUnit * 6, largest: baseUnit * 7.5, + + xxs: baseUnit * 2.25, + xs: baseUnit * 3, + sm: baseUnit * 3.75, + md: baseUnit * 4.5, + lg: baseUnit * 5.25, + xl: baseUnit * 6, + xxl: baseUnit * 7.5, } as const; - const headings = { + const semanticFontSizes = { heading1: fontSizes.larger, heading2: fontSizes.large, heading3: fontSizes.medium, heading4: fontSizes.small, + base: fontSizes.small, } as const; const space = { @@ -209,23 +226,23 @@ function generateThemeConfig(baseUnit: number): DefaultNDSThemeType { ...BASE_THEME, fontSizes: { ...pxs(fontSizes), - ...pxs(headings), + ...pxs(semanticFontSizes), }, lineHeights: { - base: s((6 * baseUnit) / fontSizes.medium), - baseRelaxed: s((7 * baseUnit) / fontSizes.medium), + base: s((6 * baseUnit) / semanticFontSizes.base), + baseRelaxed: s((7 * baseUnit) / semanticFontSizes.base), smallTextBase: s((5 * baseUnit) / fontSizes.small), smallTextCompressed: s((5 * baseUnit) / fontSizes.small), smallRelaxed: s((6 * baseUnit) / fontSizes.small), smallerText: s((4 * baseUnit) / fontSizes.smaller), smallerRelaxed: s((5 * baseUnit) / fontSizes.smaller), - heading1: s((7 * baseUnit) / headings.heading1), - heading2: s((6 * baseUnit) / headings.heading2), - heading3: s((5 * baseUnit) / headings.heading3), - heading4: s((4 * baseUnit) / headings.heading4), - title: s((7 * baseUnit) / headings.heading1), - sectionTitle: s((6 * baseUnit) / headings.heading2), - subsectionTitle: s((5 * baseUnit) / headings.heading3), + heading1: s((7 * baseUnit) / semanticFontSizes.heading1), + heading2: s((6 * baseUnit) / semanticFontSizes.heading2), + heading3: s((5 * baseUnit) / semanticFontSizes.heading3), + heading4: s((4 * baseUnit) / semanticFontSizes.heading4), + title: s((7 * baseUnit) / semanticFontSizes.heading1), + sectionTitle: s((6 * baseUnit) / semanticFontSizes.heading2), + subsectionTitle: s((5 * baseUnit) / semanticFontSizes.heading3), }, space, sizes: space, @@ -241,7 +258,8 @@ function generateThemeConfig(baseUnit: number): DefaultNDSThemeType { } const generatedThemes = { - desktop, + legacy, + desktop: generateThemeConfig(deviceBaseUnits.desktop), tablet: generateThemeConfig(deviceBaseUnits.tablet), phone: generateThemeConfig(deviceBaseUnits.phone), }; @@ -250,14 +268,14 @@ const output = `// This file is auto-generated using "yarn generate:theme" // Do not edit directly. import { DefaultNDSThemeType } from "./theme.type"; -type ThemeKey = "desktop" | "tablet" | "phone"; +type ThemeKey = "legacy" | "desktop" | "tablet" | "phone"; export const themes: Record = ${JSON.stringify(generatedThemes, null, 2)}; -export const { desktop, tablet, phone } = themes; +export const { legacy, desktop, tablet, phone } = themes; `; -const outputPath = path.join(__dirname, "..", "theme.ts"); +const outputPath = path.join(__dirname, "..", "theme/theme.ts"); fs.writeFileSync(outputPath, output, "utf8"); console.info(`Theme file generated at: ${outputPath}`); diff --git a/src/styled.d.ts b/src/styled.d.ts index c46dd3c93..c95c326ab 100644 --- a/src/styled.d.ts +++ b/src/styled.d.ts @@ -1,4 +1,4 @@ -import { DefaultNDSThemeType } from "./theme.type"; +import { DefaultNDSThemeType } from "./theme/theme.type"; declare module "styled-components" { export interface DefaultTheme extends DefaultNDSThemeType {} diff --git a/src/theme.ts b/src/theme.ts deleted file mode 100644 index b04fd20b2..000000000 --- a/src/theme.ts +++ /dev/null @@ -1,430 +0,0 @@ -// This file is auto-generated using "yarn generate:theme" -// Do not edit directly. -import { DefaultNDSThemeType } from "./theme.type"; - -type ThemeKey = "desktop" | "tablet" | "phone"; - -export const themes: Record = { - desktop: { - colors: { - black: "#011e38", - blackBlue: "#122b47", - darkBlue: "#00438f", - blue: "#216beb", - lightBlue: "#e1ebfa", - darkGrey: "#434d59", - midGrey: "#6c7784", - grey: "#c0c8d1", - lightGrey: "#e4e7eb", - whiteGrey: "#f0f2f5", - white: "#ffffff", - yellow: "#ffbb00", - lightYellow: "#fcf5e3", - green: "#008059", - lightGreen: "#e9f7f2", - red: "#cc1439", - lightRed: "#fae6ea", - categorical1: "#19c4e6", - categorical2: "#8033cc", - categorical3: "#e372d0", - categorical4: "#55ddb0", - categorical5: "#ee5513", - categorical6: "#d3d322", - }, - fontWeights: { - light: 300, - normal: 400, - medium: 500, - bold: 600, - }, - fonts: { - base: "'IBM Plex Sans', sans-serif", - mono: "'IBM Plex Mono', monospace", - sc: "'Noto Sans SC', sans-serif", - }, - shadows: { - small: "0px 1px 2px 0px rgba(1, 30, 56, 0.25)", - medium: "0px 3px 8px 0px rgba(1, 30, 56, 0.18)", - large: "0px 6px 12px 2px rgba(1, 30, 56, 0.15)", - focus: "0px 0px 5px 0px rgba(33, 107, 235, .9)", - error: "0px 0px 5px 0px rgba(204, 20, 57, .9)", - }, - breakpoints: { - extraSmall: "0px", - small: "768px", - medium: "1024px", - large: "1360px", - extraLarge: "1920px", - }, - zIndices: { - content: 100, - tabsScollIndicator: 200, - tabsBar: 210, - overlay: 1000, - aboveOverlay: 1010, - tableHeader: 10, - modalHeaderAndFooter: 2, - openControl: 1000, - navBar: 900, - sidebar: 800, - }, - fontSizes: { - smaller: "12px", - small: "14px", - medium: "16px", - large: "24px", - larger: "30px", - largest: "32px", - heading1: "32px", - heading2: "30px", - heading3: "24px", - heading4: "18px", - }, - lineHeights: { - baseRelaxed: "1.75", - smallRelaxed: "1.7142857142857142", - smallerRelaxed: "1.6666666666666667", - base: "1.5", - smallTextBase: "1.71428571", - smallTextCompressed: "1.14285714", - smallerText: "1.33333333", - heading1: "1.25", - heading2: "1.33", - heading3: "1.33", - heading4: "1.33", - title: "1.25", - sectionTitle: "1.33", - subsectionTitle: "1.33", - }, - space: { - none: "0px", - half: "4px", - x0: "0px", - x0_25: "2px", - x0_5: "4px", - x0_75: "6px", - x1: "8px", - x1_25: "10px", - x1_5: "12px", - x1_75: "14px", - x2: "16px", - x2_5: "20px", - x3: "24px", - x4: "32px", - x5: "40px", - x6: "48px", - x7: "56px", - x8: "64px", - }, - sizes: { - none: "0px", - half: "4px", - x0: "0px", - x0_25: "2px", - x0_5: "4px", - x0_75: "6px", - x1: "8px", - x1_25: "10px", - x1_5: "12px", - x1_75: "14px", - x2: "16px", - x2_5: "20px", - x3: "24px", - x4: "32px", - x5: "40px", - x6: "48px", - x7: "56px", - x8: "64px", - }, - radii: { - small: "2px", - medium: "4px", - large: "8px", - circle: "50%", - rounded: "9999px", - }, - borders: [], - }, - tablet: { - colors: { - black: "#011e38", - blackBlue: "#122b47", - darkBlue: "#00438f", - blue: "#216beb", - lightBlue: "#e1ebfa", - darkGrey: "#434d59", - midGrey: "#6c7784", - grey: "#c0c8d1", - lightGrey: "#e4e7eb", - whiteGrey: "#f0f2f5", - white: "#ffffff", - yellow: "#ffbb00", - lightYellow: "#fcf5e3", - green: "#008059", - lightGreen: "#e9f7f2", - red: "#cc1439", - lightRed: "#fae6ea", - categorical1: "#19c4e6", - categorical2: "#8033cc", - categorical3: "#e372d0", - categorical4: "#55ddb0", - categorical5: "#ee5513", - categorical6: "#d3d322", - }, - fontWeights: { - light: 300, - normal: 400, - medium: 500, - bold: 600, - }, - fonts: { - base: "'IBM Plex Sans', sans-serif", - mono: "'IBM Plex Mono', monospace", - sc: "'Noto Sans SC', sans-serif", - }, - shadows: { - small: "0px 1px 2px 0px rgba(1, 30, 56, 0.25)", - medium: "0px 3px 8px 0px rgba(1, 30, 56, 0.18)", - large: "0px 6px 12px 2px rgba(1, 30, 56, 0.15)", - focus: "0px 0px 5px 0px rgba(33, 107, 235, .9)", - error: "0px 0px 5px 0px rgba(204, 20, 57, .9)", - }, - breakpoints: { - extraSmall: "0px", - small: "768px", - medium: "1024px", - large: "1360px", - extraLarge: "1920px", - }, - zIndices: { - content: 100, - tabsScollIndicator: 200, - tabsBar: 210, - overlay: 1000, - aboveOverlay: 1010, - tableHeader: 10, - modalHeaderAndFooter: 2, - openControl: 1000, - navBar: 900, - sidebar: 800, - }, - fontSizes: { - smaller: "16.799999999999997px", - small: "21px", - medium: "25.2px", - large: "29.4px", - larger: "33.599999999999994px", - largest: "42px", - heading1: "33.599999999999994px", - heading2: "29.4px", - heading3: "25.2px", - heading4: "21px", - }, - lineHeights: { - base: "1.333333333333333", - baseRelaxed: "1.5555555555555554", - smallTextBase: "1.3333333333333333", - smallTextCompressed: "1.3333333333333333", - smallRelaxed: "1.5999999999999996", - smallerText: "1.3333333333333335", - smallerRelaxed: "1.666666666666667", - heading1: "1.1666666666666667", - heading2: "1.1428571428571428", - heading3: "1.1111111111111112", - heading4: "1.0666666666666667", - title: "1.1666666666666667", - sectionTitle: "1.1428571428571428", - subsectionTitle: "1.1111111111111112", - }, - space: { - none: "0px", - x0: "0px", - x0_25: "2.8px", - half: "5.6px", - x0_5: "5.6px", - x0_75: "8.399999999999999px", - x1: "11.2px", - x1_25: "14px", - x1_5: "16.799999999999997px", - x1_75: "19.599999999999998px", - x2: "22.4px", - x2_5: "28px", - x3: "33.599999999999994px", - x4: "44.8px", - x5: "56px", - x6: "67.19999999999999px", - x7: "78.39999999999999px", - x8: "89.6px", - }, - sizes: { - none: "0px", - x0: "0px", - x0_25: "2.8px", - half: "5.6px", - x0_5: "5.6px", - x0_75: "8.399999999999999px", - x1: "11.2px", - x1_25: "14px", - x1_5: "16.799999999999997px", - x1_75: "19.599999999999998px", - x2: "22.4px", - x2_5: "28px", - x3: "33.599999999999994px", - x4: "44.8px", - x5: "56px", - x6: "67.19999999999999px", - x7: "78.39999999999999px", - x8: "89.6px", - }, - radii: { - small: "2.8px", - medium: "5.6px", - large: "11.2px", - circle: "50%", - rounded: "99999px", - }, - borders: [], - }, - phone: { - colors: { - black: "#011e38", - blackBlue: "#122b47", - darkBlue: "#00438f", - blue: "#216beb", - lightBlue: "#e1ebfa", - darkGrey: "#434d59", - midGrey: "#6c7784", - grey: "#c0c8d1", - lightGrey: "#e4e7eb", - whiteGrey: "#f0f2f5", - white: "#ffffff", - yellow: "#ffbb00", - lightYellow: "#fcf5e3", - green: "#008059", - lightGreen: "#e9f7f2", - red: "#cc1439", - lightRed: "#fae6ea", - categorical1: "#19c4e6", - categorical2: "#8033cc", - categorical3: "#e372d0", - categorical4: "#55ddb0", - categorical5: "#ee5513", - categorical6: "#d3d322", - }, - fontWeights: { - light: 300, - normal: 400, - medium: 500, - bold: 600, - }, - fonts: { - base: "'IBM Plex Sans', sans-serif", - mono: "'IBM Plex Mono', monospace", - sc: "'Noto Sans SC', sans-serif", - }, - shadows: { - small: "0px 1px 2px 0px rgba(1, 30, 56, 0.25)", - medium: "0px 3px 8px 0px rgba(1, 30, 56, 0.18)", - large: "0px 6px 12px 2px rgba(1, 30, 56, 0.15)", - focus: "0px 0px 5px 0px rgba(33, 107, 235, .9)", - error: "0px 0px 5px 0px rgba(204, 20, 57, .9)", - }, - breakpoints: { - extraSmall: "0px", - small: "768px", - medium: "1024px", - large: "1360px", - extraLarge: "1920px", - }, - zIndices: { - content: 100, - tabsScollIndicator: 200, - tabsBar: 210, - overlay: 1000, - aboveOverlay: 1010, - tableHeader: 10, - modalHeaderAndFooter: 2, - openControl: 1000, - navBar: 900, - sidebar: 800, - }, - fontSizes: { - smaller: "10.8px", - small: "13.5px", - medium: "16.2px", - large: "18.900000000000002px", - larger: "21.6px", - largest: "27px", - heading1: "21.6px", - heading2: "18.900000000000002px", - heading3: "16.2px", - heading4: "13.5px", - }, - lineHeights: { - base: "1.3333333333333335", - baseRelaxed: "1.5555555555555556", - smallTextBase: "1.3333333333333333", - smallTextCompressed: "1.3333333333333333", - smallRelaxed: "1.6", - smallerText: "1.3333333333333333", - smallerRelaxed: "1.6666666666666665", - heading1: "1.1666666666666665", - heading2: "1.1428571428571428", - heading3: "1.1111111111111112", - heading4: "1.0666666666666667", - title: "1.1666666666666665", - sectionTitle: "1.1428571428571428", - subsectionTitle: "1.1111111111111112", - }, - space: { - none: "0px", - x0: "0px", - x0_25: "1.8px", - half: "3.6px", - x0_5: "3.6px", - x0_75: "5.4px", - x1: "7.2px", - x1_25: "9px", - x1_5: "10.8px", - x1_75: "12.6px", - x2: "14.4px", - x2_5: "18px", - x3: "21.6px", - x4: "28.8px", - x5: "36px", - x6: "43.2px", - x7: "50.4px", - x8: "57.6px", - }, - sizes: { - none: "0px", - x0: "0px", - x0_25: "1.8px", - half: "3.6px", - x0_5: "3.6px", - x0_75: "5.4px", - x1: "7.2px", - x1_25: "9px", - x1_5: "10.8px", - x1_75: "12.6px", - x2: "14.4px", - x2_5: "18px", - x3: "21.6px", - x4: "28.8px", - x5: "36px", - x6: "43.2px", - x7: "50.4px", - x8: "57.6px", - }, - radii: { - small: "1.8px", - medium: "3.6px", - large: "7.2px", - circle: "50%", - rounded: "99999px", - }, - borders: [], - }, -}; - -export const { desktop, tablet, phone } = themes; diff --git a/src/theme.type.ts b/src/theme.type.ts deleted file mode 100644 index 90a5d1112..000000000 --- a/src/theme.type.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { RecursivePartial } from "./utils/ts/recursivePartial"; - -interface Colors { - black: string; - blackBlue: string; - darkBlue: string; - blue: string; - lightBlue: string; - darkGrey: string; - midGrey: string; - grey: string; - lightGrey: string; - whiteGrey: string; - white: string; - yellow: string; - lightYellow: string; - green: string; - lightGreen: string; - red: string; - lightRed: string; - categorical1: string; - categorical2: string; - categorical3: string; - categorical4: string; - categorical5: string; - categorical6: string; -} - -interface FontSizes { - smaller: string; - small: string; - medium: string; - large: string; - larger: string; - largest: string; - heading1: string; - heading2: string; - heading3: string; - heading4: string; -} - -interface LineHeights { - base: string; - baseRelaxed: string; - smallTextBase: string; - smallRelaxed: string; - smallTextCompressed: string; - smallerText: string; - smallerRelaxed: string; - heading1: string; - heading2: string; - heading3: string; - heading4: string; - title: string; - sectionTitle: string; - subsectionTitle: string; -} - -interface FontWeights { - light: number; - normal: number; - medium: number; - bold: number; -} - -interface Space { - none: string; - half: string; - x0: string; - x0_25: string; - x0_5: string; - x0_75: string; - x1: string; - x1_25: string; - x1_5: string; - x1_75: string; - x2: string; - x2_5: string; - x3: string; - x4: string; - x5: string; - x6: string; - x7: string; - x8: string; -} - -interface Fonts { - base: string; - mono: string; - sc: string; -} - -type Borders = Array; - -interface Shadows { - small: string; - medium: string; - large: string; - focus: string; - error: string; -} - -interface Radii { - small: string; - medium: string; - large: string; - circle: string; - rounded: string; -} - -export interface Breakpoints { - extraSmall: string; - small: string; - medium: string; - large: string; - extraLarge: string; -} - -interface ZIndices { - content: number; - tabsScollIndicator: number; - tabsBar: number; - overlay: number; - aboveOverlay: number; - tableHeader: number; - modalHeaderAndFooter: number; - openControl: number; - sidebar: number; - navBar: number; -} - -export interface DefaultNDSThemeType { - colors: Colors; - fontSizes: FontSizes; - lineHeights: LineHeights; - fontWeights: FontWeights; - space: Space; - sizes: Space; - fonts: Fonts; - borders: Borders; - shadows: Shadows; - radii: Radii; - breakpoints: Breakpoints; - zIndices: ZIndices; -} - -export type ThemeType = RecursivePartial; diff --git a/src/theme/theme.ts b/src/theme/theme.ts index f987a6d2a..088daf99f 100644 --- a/src/theme/theme.ts +++ b/src/theme/theme.ts @@ -76,6 +76,13 @@ export const themes: Record = { larger: "30px", largest: "32px", base: "16px", + xxs: "12px", + xs: "12px", + sm: "14px", + md: "16px", + lg: "24px", + xl: "30px", + xxl: "32px", heading1: "32px", heading2: "30px", heading3: "24px", diff --git a/src/theme/theme.type.ts b/src/theme/theme.type.ts index 8331539bc..a10d7420b 100644 --- a/src/theme/theme.type.ts +++ b/src/theme/theme.type.ts @@ -30,6 +30,7 @@ interface FontSizes { smaller: string; small: string; medium: string; + base: string; large: string; larger: string; largest: string; @@ -37,6 +38,13 @@ interface FontSizes { heading2: string; heading3: string; heading4: string; + xxs: string; + xs: string; + sm: string; + md: string; + lg: string; + xl: string; + xxl: string; } interface LineHeights { diff --git a/src/theme/useNDSTheme.tsx b/src/theme/useNDSTheme.tsx index 8460d2d36..4e59fd151 100644 --- a/src/theme/useNDSTheme.tsx +++ b/src/theme/useNDSTheme.tsx @@ -33,20 +33,21 @@ export const getThemeByVariant = ( if (variant === "touch") { return isTabletSize ? themes.tablet : themes.phone; } + return futureFlags.newDesktopTypographyScale ? themes.desktop : themes.legacy; }; export function useNDSTheme(variant: ComponentVariant = "desktop", customTheme?: ThemeType): DefaultNDSThemeType { validateVariantOrThrow(variant); - const futureFlags = useFutureFlags(); + const { newDesktopTypographyScale } = useFutureFlags(); const [themeVariant, setThemeVariant] = useState(legacy); const isTabletSize = useMediaQuery(`(min-width: ${legacy.breakpoints.small})`); useEffect(() => { - const newTheme = getThemeByVariant(variant, isTabletSize, futureFlags); + const newTheme = getThemeByVariant(variant, isTabletSize, { newDesktopTypographyScale }); setThemeVariant(newTheme); - }, [variant, isTabletSize, futureFlags]); + }, [variant, isTabletSize, newDesktopTypographyScale]); const mergedTheme = mergeThemes(themeVariant, customTheme); return { diff --git a/yarn.lock b/yarn.lock index 0298b4a61..81b8ae76c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4797,12 +4797,35 @@ react-syntax-highlighter "^13.5.3" regenerator-runtime "^0.13.7" -"@storybook/addon-viewport@^7.6.6": - version "7.6.6" - resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-7.6.6.tgz#814c1461ac56de0285e7ac843d2f0725419fd928" - integrity sha512-/ijbzDf1Iq30LvZW2NE8cO4TeHusw0N+jTDUK1+vhxGNMFo9DUIgRkAi6VpFEfS0aQ5d82523WSWzVso7b/Hmg== +"@storybook/addon-toolbars@^6.1.9": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.5.16.tgz#9de04f9cc64b68d6cb680aa1c4fbf874e11afa32" + integrity sha512-y3PuUKiwOWrAvqx1YdUvArg0UaAwmboXFeR2bkrowk1xcT+xnRO3rML4npFeUl26OQ1FzwxX/cw6nknREBBLEA== + dependencies: + "@storybook/addons" "6.5.16" + "@storybook/api" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/components" "6.5.16" + "@storybook/theming" "6.5.16" + core-js "^3.8.2" + regenerator-runtime "^0.13.7" + +"@storybook/addon-viewport@^6.1.9": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-6.5.16.tgz#226aa0ab93df68264269eb31adb104e7e48f6c68" + integrity sha512-1Vyqf1U6Qng6TXlf4SdqUKyizlw1Wn6+qW8YeA2q1lbkJqn3UlnHXIp8Q0t/5q1dK5BFtREox3+jkGwbJrzkmA== dependencies: + "@storybook/addons" "6.5.16" + "@storybook/api" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/components" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/theming" "6.5.16" + core-js "^3.8.2" + global "^4.4.0" memoizerific "^1.11.3" + prop-types "^15.7.2" + regenerator-runtime "^0.13.7" "@storybook/addons@6.1.9": version "6.1.9" @@ -4849,6 +4872,23 @@ global "^4.4.0" regenerator-runtime "^0.13.7" +"@storybook/addons@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.16.tgz#07e8f2205f86fa4c9dada719e3e096cb468e3cdd" + integrity sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ== + dependencies: + "@storybook/api" "6.5.16" + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.16" + "@storybook/theming" "6.5.16" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + "@storybook/api@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.9.tgz#3f9bf00b2b18fa02965079fe775bd713677b30a3" @@ -4926,6 +4966,29 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/api@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.16.tgz#897915b76de05587fd702951d5d836f708043662" + integrity sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA== + dependencies: + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.16" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.5.16" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/builder-webpack4@6.3.12": version "6.3.12" resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.3.12.tgz#288d541e2801892721c975259476022da695dbfe" @@ -5068,6 +5131,15 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/channels@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.16.tgz#3fb9a3b5666ecb951a2d0cf8b0699b084ef2d3c6" + integrity sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg== + dependencies: + core-js "^3.8.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/channels@7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.0.9.tgz#0308c6a714daf1088228b554fd56dc72f2921b76" @@ -5289,6 +5361,20 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/components@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.16.tgz#f8dc51213bc08fe32154be964e1e8b0e2f670ed6" + integrity sha512-LzBOFJKITLtDcbW9jXl0/PaG+4xAz25PK8JxPZpIALbmOpYWOAPcO6V9C2heX6e6NgWFMUxjplkULEk9RCQMNA== + dependencies: + "@storybook/client-logger" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/theming" "6.5.16" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + util-deprecate "^1.0.2" + "@storybook/core-client@6.3.12": version "6.3.12" resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.3.12.tgz#fd01bfbc69c331f4451973a4e7597624dc3737e5" @@ -5387,6 +5473,13 @@ dependencies: core-js "^3.8.2" +"@storybook/core-events@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.16.tgz#b1c265dac755007dae172d9d4b72656c9e5d7bb3" + integrity sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g== + dependencies: + core-js "^3.8.2" + "@storybook/core-events@7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.0.9.tgz#4aa5913cfa3ccb40b83bf4ffbb6ef832aa8f5402" @@ -5594,6 +5687,13 @@ dependencies: lodash "^4.17.15" +"@storybook/csf@0.0.2--canary.4566f4d.1": + version "0.0.2--canary.4566f4d.1" + resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.0.2--canary.4566f4d.1.tgz#dac52a21c40ef198554e71fe4d20d61e17f65327" + integrity sha512-9OVvMVh3t9znYZwb0Svf/YQoxX2gVOeQTGe2bses2yj+a3+OJnCrUF3/hGv6Em7KujtOdL2LL+JnG49oMVGFgQ== + dependencies: + lodash "^4.17.15" + "@storybook/csf@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.0.tgz#62315bf9704f3aa4e0d4d909b9033833774ddfbe" @@ -5796,6 +5896,17 @@ qs "^6.10.0" ts-dedent "^2.0.0" +"@storybook/router@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.16.tgz#28fb4d34e8219351a40bee1fc94dcacda6e1bd8b" + integrity sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ== + dependencies: + "@storybook/client-logger" "6.5.16" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + "@storybook/router@7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-7.0.9.tgz#f892fa7b1d92a7664f36f287e985d733a5db09d6" @@ -5900,6 +6011,16 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" +"@storybook/theming@6.5.16", "@storybook/theming@^6.1.9": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.16.tgz#b999bdb98945b605b93b9dfdf7408535b701e2aa" + integrity sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ== + dependencies: + "@storybook/client-logger" "6.5.16" + core-js "^3.8.2" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + "@storybook/theming@7.0.9", "@storybook/theming@^7.0.0-beta.12": version "7.0.9" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-7.0.9.tgz#88060a48c22ad72c065f175c1332d22f599f7d15" @@ -5910,16 +6031,6 @@ "@storybook/global" "^5.0.0" memoizerific "^1.11.3" -"@storybook/theming@^6.1.9": - version "6.5.16" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.16.tgz#b999bdb98945b605b93b9dfdf7408535b701e2aa" - integrity sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ== - dependencies: - "@storybook/client-logger" "6.5.16" - core-js "^3.8.2" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - "@storybook/types@7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.0.9.tgz#745c74ab88ed911dd75246de3ec3f84e71844f76" @@ -22127,6 +22238,20 @@ telejson@^5.0.2, telejson@^5.3.2: lodash "^4.17.21" memoizerific "^1.11.3" +telejson@^6.0.8: + version "6.0.8" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-6.0.8.tgz#1c432db7e7a9212c1fbd941c3e5174ec385148f7" + integrity sha512-nerNXi+j8NK1QEfBHtZUN/aLdDcyupA//9kAboYLrtzZlPLpUfqbVGWb9zz91f/mIjRbAYhbgtnJHY8I1b5MBg== + dependencies: + "@types/is-function" "^1.0.0" + global "^4.4.0" + is-function "^1.0.2" + is-regex "^1.1.2" + is-symbol "^1.0.3" + isobject "^4.0.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + telejson@^7.0.3: version "7.1.0" resolved "https://registry.yarnpkg.com/telejson/-/telejson-7.1.0.tgz#1ef7a0dd57eeb52cde933126f61bcc296c170f52"