diff --git a/theme/src/components/__snapshots__/home-navigation.spec.js.snap b/theme/src/components/__snapshots__/home-navigation.spec.js.snap deleted file mode 100644 index 782086a2..00000000 --- a/theme/src/components/__snapshots__/home-navigation.spec.js.snap +++ /dev/null @@ -1,175 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`HomeNavigation matches the snapshot 1`] = ` -
- -
-`; diff --git a/theme/src/components/home-navigation.spec.js b/theme/src/components/home-navigation.spec.js index 9c7eca1e..f52d6c73 100644 --- a/theme/src/components/home-navigation.spec.js +++ b/theme/src/components/home-navigation.spec.js @@ -1,6 +1,6 @@ import React from 'react' -import renderer from 'react-test-renderer' - +import { render, screen, fireEvent } from '@testing-library/react' +import '@testing-library/jest-dom' import HomeNavigation from './home-navigation' import useSiteMetadata from '../hooks/use-site-metadata' @@ -8,25 +8,63 @@ jest.mock('../hooks/use-site-metadata') const mockSiteMetadata = { widgets: { - github: { - widgetDataSource: 'https://fake-api.chrisvogt.me/social/github' - }, - goodreads: { - widgetDataSource: 'https://fake-api.chrisvogt.me/social/goodreads' - }, - instagram: { - widgetDataSource: 'https://fake-api.chrisvogt.me/social/instagram' - }, - spotify: { - widgetDataSource: 'https://fake-api.chrisvogt.me/social/spotify' - } + github: { widgetDataSource: 'https://fake-api.chrisvogt.me/social/github' }, + goodreads: { widgetDataSource: 'https://fake-api.chrisvogt.me/social/goodreads' }, + instagram: { widgetDataSource: 'https://fake-api.chrisvogt.me/social/instagram' }, + spotify: { widgetDataSource: 'https://fake-api.chrisvogt.me/social/spotify' } } } describe('HomeNavigation', () => { - useSiteMetadata.mockImplementation(() => mockSiteMetadata) - it('matches the snapshot', () => { - const tree = renderer.create().toJSON() - expect(tree).toMatchSnapshot() + beforeEach(() => { + useSiteMetadata.mockImplementation(() => mockSiteMetadata) + }) + + it('renders all links when all widgets are enabled', () => { + render() + expect(screen.getByText('Home')).toBeInTheDocument() + expect(screen.getByText('Latest Posts')).toBeInTheDocument() + expect(screen.getByText('Instagram')).toBeInTheDocument() + expect(screen.getByText('GitHub')).toBeInTheDocument() + expect(screen.getByText('Goodreads')).toBeInTheDocument() + expect(screen.getByText('Spotify')).toBeInTheDocument() + }) + + it('renders only mandatory links when no widgets are enabled', () => { + useSiteMetadata.mockImplementation(() => ({ widgets: {} })) + render() + expect(screen.getByText('Home')).toBeInTheDocument() + expect(screen.getByText('Latest Posts')).toBeInTheDocument() + expect(screen.queryByText('Instagram')).not.toBeInTheDocument() + expect(screen.queryByText('GitHub')).not.toBeInTheDocument() + expect(screen.queryByText('Goodreads')).not.toBeInTheDocument() + expect(screen.queryByText('Spotify')).not.toBeInTheDocument() + }) + + it('highlights the active section on scroll', () => { + render() + + const instagramSection = document.createElement('div') + instagramSection.id = 'instagram' + document.body.appendChild(instagramSection) + instagramSection.getBoundingClientRect = jest.fn(() => ({ + top: window.innerHeight / 2 - 1 // Simulate it being in view + })) + + fireEvent.scroll(window) + expect(screen.getByText('Instagram').classList).toContain('active') + }) + + it('does not break when an invalid icon is provided', () => { + useSiteMetadata.mockImplementation(() => ({ widgets: {} })) + render() + expect(screen.queryByRole('img')).not.toBeInTheDocument() // No icons should render + }) + + it('renders the correct aria-label for navigation', () => { + render() + const nav = document.querySelector('nav[aria-label="On-page navigation"]') + expect(nav).not.toBeNull() + expect(nav.getAttribute('aria-label')).toBe('On-page navigation') }) }) diff --git a/theme/src/gatsby-plugin-theme-ui/__snapshots__/theme.spec.js.snap b/theme/src/gatsby-plugin-theme-ui/__snapshots__/theme.spec.js.snap new file mode 100644 index 00000000..b1c30ef6 --- /dev/null +++ b/theme/src/gatsby-plugin-theme-ui/__snapshots__/theme.spec.js.snap @@ -0,0 +1,1254 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Theme Configuration a snapshot of the configuration matches the snapshot 1`] = ` +{ + "badges": { + "outline": { + "bg": "transparent", + "boxShadow": "inset 0 0 0 1px", + "color": "primary", + "fontSize": 1, + }, + "primary": { + "bg": "primary", + "color": "background", + }, + }, + "borderWidths": { + "0": "0px", + "2": "2px", + "4": "4px", + "8": "8px", + "default": "1px", + }, + "breakpoints": [ + "640px", + "768px", + "1024px", + "1280px", + "1536px", + ], + "buttons": { + "3D": { + "&:hover": { + "transform": "translateY(-1px)", + }, + "backgroundColor": "primary", + "border": "none", + "borderBottomColor": "primaryHover", + "borderBottomStyle": "solid", + "borderBottomWidth": "4px", + "borderRadius": "default", + "color": "white", + "cursor": "pointer", + "fontSize": "100%", + "fontWeight": "bold", + "lineHeight": "inherit", + "px": 3, + "py": 2, + "transition": "transform 0.3s ease-in-out", + }, + "bordered": { + "&:hover": { + "backgroundColor": "primaryHover", + }, + "backgroundColor": "primary", + "borderColor": "primaryHover", + "borderRadius": "default", + "borderStyle": "solid", + "borderWidth": "1px", + "color": "white", + "cursor": "pointer", + "fontSize": "100%", + "fontWeight": "bold", + "lineHeight": "inherit", + "px": 3, + "py": 2, + }, + "disabled": { + "backgroundColor": "primary", + "border": "none", + "borderRadius": "default", + "color": "white", + "cursor": "not-allowed", + "fontSize": "100%", + "fontWeight": "bold", + "lineHeight": "inherit", + "opacity": 0.5, + "px": 3, + "py": 2, + }, + "elevated": { + "&:hover": { + "backgroundColor": "gray.1", + }, + "backgroundColor": "white", + "borderColor": "gray.4", + "borderRadius": "default", + "borderStyle": "solid", + "borderWidth": "1px", + "boxShadow": "default", + "color": "text", + "cursor": "pointer", + "fontSize": "100%", + "fontWeight": "bold", + "lineHeight": "inherit", + "px": 3, + "py": 2, + }, + "gray": { + "bg": "gray", + "color": "background", + }, + "outline": { + "&:hover": { + "backgroundColor": "primary", + "borderColor": "transparent", + "color": "white", + }, + "backgroundColor": "transparent", + "borderColor": "primary", + "borderRadius": "default", + "borderStyle": "solid", + "borderWidth": "1px", + "color": "primary", + "cursor": "pointer", + "fontSize": "100%", + "fontWeight": "semibold", + "lineHeight": "inherit", + "px": 3, + "py": 2, + }, + "pill": { + "&:hover": { + "backgroundColor": "primaryHover", + }, + "backgroundColor": "primary", + "border": "none", + "borderRadius": "full", + "color": "white", + "cursor": "pointer", + "fontSize": "100%", + "fontWeight": "bold", + "lineHeight": "inherit", + "px": 3, + "py": 2, + }, + "primary": { + "bg": "primary", + "color": "background", + }, + "secondary": { + "bg": "secondary", + "color": "background", + }, + "simple": { + "&:hover": { + "backgroundColor": "primaryHover", + }, + "backgroundColor": "primary", + "border": "none", + "borderRadius": "default", + "color": "white", + "cursor": "pointer", + "fontSize": "100%", + "fontWeight": "bold", + "lineHeight": "inherit", + "px": 3, + "py": 2, + }, + }, + "cards": { + "PostCard": { + "&:hover .read-more-icon": { + "opacity": 1, + "paddingLeft": "8px", + }, + "&:hover, &:focus": { + "boxShadow": "lg", + "transform": "scale(1.015)", + }, + ".card-media": { + "height": "100%", + "mb": 2, + "overflow": "hidden", + }, + ".read-more-icon": { + "display": "inline", + "opacity": 0, + "paddingLeft": 0, + "transition": "all 250ms ease-in", + }, + "WebkitBackdropFilter": "blur(10px)", + "backdropFilter": "blur(10px)", + "background": "var(--theme-ui-colors-panel-background)", + "backgroundColor": "var(--theme-ui-colors-panel-background)", + "border": "1px solid rgba(255, 255, 255, 0.15)", + "borderRadius": "10px", + "boxShadow": "0 4px 6px rgba(0, 0, 0, 0.1)", + "color": "var(--theme-ui-colors-panel-text)", + "display": "flex", + "flexDirection": "column", + "flexGrow": 1, + "fontSize": [ + 1, + 2, + ], + "height": "100%", + "padding": 3, + "textDecoration": "none", + "transition": "all 200ms ease-in-out", + }, + "StatusCardDark": { + "backgroundColor": "#1e2530", + }, + "UserProfile": { + "background": "none", + "border": "none", + "color": "white", + "padding": [Function], + }, + "UserProfileDark": { + "background": "var(--theme-ui-colors-panel-background)", + "backgroundColor": "none", + "borderBottom": "none", + "borderRadius": "card", + "boxShadow": "none", + "color": "white", + "flexGrow": 1, + "fontSize": [ + 1, + 2, + ], + "padding": [Function], + "textDecoration": "none", + }, + "actionCard": { + "&:hover, &:focus": { + "boxShadow": "lg", + "transform": "scale(1.015)", + }, + "WebkitBackdropFilter": "blur(10px)", + "a": { + ":hover": "pointer", + }, + "backdropFilter": "blur(10px)", + "background": "var(--theme-ui-colors-panel-background)", + "border": "1px solid rgba(255, 255, 255, 0.15)", + "borderLeft": [Function], + "borderRadius": "10px", + "boxShadow": "0 4px 6px rgba(0, 0, 0, 0.1)", + "color": "var(--theme-ui-colors-panel-text)", + "flexGrow": 1, + "fontSize": [ + 1, + 2, + ], + "padding": 3, + "textDecoration": "none", + "transition": "all 200ms ease-in-out", + }, + "metricCard": { + "background": "var(--theme-ui-colors-panel-background)", + "backgroundColor": "var(--theme-ui-colors-panel-background)", + "borderRadius": "card", + "boxShadow": "none", + "color": "var(--theme-ui-colors-panel-text)", + "flexGrow": 1, + "fontSize": [ + 1, + 2, + ], + "padding": 3, + "span": { + "fontFamily": "heading", + "fontWeight": "bold", + "padding": 2, + }, + "textDecoration": "none", + }, + "primary": { + "background": "var(--theme-ui-colors-panel-background)", + "borderRadius": "card", + "boxShadow": "default", + "color": "var(--theme-ui-colors-panel-text)", + "flexGrow": 1, + "fontSize": [ + 1, + 2, + ], + "padding": 3, + "textDecoration": "none", + }, + }, + "colors": { + "accent": "deeppink", + "amber": [ + "#fffbeb", + "#fef3c7", + "#fde68a", + "#fcd34d", + "#fbbf24", + "#f59e0b", + "#d97706", + "#b45309", + "#92400e", + "#78350f", + ], + "background": "#fcb8a2", + "black": "#000", + "blue": [ + "#eff6ff", + "#dbeafe", + "#bfdbfe", + "#93c5fd", + "#60a5fa", + "#3b82f6", + "#2563eb", + "#1d4ed8", + "#1e40af", + "#1e3a8a", + ], + "cyan": [ + "#ecfeff", + "#cffafe", + "#a5f3fc", + "#67e8f9", + "#22d3ee", + "#06b6d4", + "#0891b2", + "#0e7490", + "#155e75", + "#164e63", + ], + "danger": "#fca5a5", + "dark": "#1f2937", + "emerald": [ + "#ecfdf5", + "#d1fae5", + "#a7f3d0", + "#6ee7b7", + "#34d399", + "#10b981", + "#059669", + "#047857", + "#065f46", + "#064e3b", + ], + "fuchsia": [ + "#fdf4ff", + "#fae8ff", + "#f5d0fe", + "#f0abfc", + "#e879f9", + "#d946ef", + "#c026d3", + "#a21caf", + "#86198f", + "#701a75", + ], + "gray": [ + "#f9fafb", + "#f3f4f6", + "#e5e7eb", + "#d1d5db", + "#9ca3af", + "#6b7280", + "#4b5563", + "#374151", + "#1f2937", + "#111827", + ], + "grayDark": "#1f2937", + "green": [ + "#f0fdf4", + "#dcfce7", + "#bbf7d0", + "#86efac", + "#4ade80", + "#22c55e", + "#16a34a", + "#15803d", + "#166534", + "#14532d", + ], + "indigo": [ + "#eef2ff", + "#e0e7ff", + "#c7d2fe", + "#a5b4fc", + "#818cf8", + "#6366f1", + "#4f46e5", + "#4338ca", + "#3730a3", + "#312e81", + ], + "info": "#60a5fa", + "light": "#f3f4f6", + "lime": [ + "#f7fee7", + "#ecfccb", + "#d9f99d", + "#bef264", + "#a3e635", + "#84cc16", + "#65a30d", + "#4d7c0f", + "#3f6212", + "#365314", + ], + "modes": { + "dark": { + "background": "#1e1e2f", + "panel-background": "rgba(1, 1, 1, 0.28)", + "panel-divider": [Function], + "panel-highlight": [Function], + "primary": "#1E90FF", + "text": "#fff", + "textMuted": "#d8d8d8", + }, + }, + "muted": "#d1d5db", + "neutral": [ + "#fafafa", + "#f5f5f5", + "#e5e5e5", + "#d4d4d4", + "#a3a3a3", + "#737373", + "#525252", + "#404040", + "#262626", + "#171717", + ], + "orange": [ + "#fff7ed", + "#ffedd5", + "#fed7aa", + "#fdba74", + "#fb923c", + "#f97316", + "#ea580c", + "#c2410c", + "#9a3412", + "#7c2d12", + ], + "panel-background": "rgba(255, 229, 224, 0.10)", + "panel-divider": [Function], + "panel-highlight": [Function], + "pink": [ + "#fdf2f8", + "#fce7f3", + "#fbcfe8", + "#f9a8d4", + "#f472b6", + "#ec4899", + "#db2777", + "#be185d", + "#9d174d", + "#831843", + ], + "primary": "#422EA3", + "primaryHover": "#1e40af", + "purple": [ + "#faf5ff", + "#f3e8ff", + "#e9d5ff", + "#d8b4fe", + "#c084fc", + "#a855f7", + "#9333ea", + "#7e22ce", + "#6b21a8", + "#581c87", + ], + "red": [ + "#fef2f2", + "#fee2e2", + "#fecaca", + "#fca5a5", + "#f87171", + "#ef4444", + "#dc2626", + "#b91c1c", + "#991b1b", + "#7f1d1d", + ], + "rose": [ + "#fff1f2", + "#ffe4e6", + "#fecdd3", + "#fda4af", + "#fb7185", + "#f43f5e", + "#e11d48", + "#be123c", + "#9f1239", + "#881337", + ], + "secondary": "#711E9B", + "secondaryGradient": "linear-gradient(45deg, #4527a0 0%, #711e9b 100%)", + "sky": [ + "#f0f9ff", + "#e0f2fe", + "#bae6fd", + "#7dd3fc", + "#38bdf8", + "#0ea5e9", + "#0284c7", + "#0369a1", + "#075985", + "#0c4a6e", + ], + "slate": [ + "#f8fafc", + "#f1f5f9", + "#e2e8f0", + "#cbd5e1", + "#94a3b8", + "#64748b", + "#475569", + "#334155", + "#1e293b", + "#0f172a", + ], + "stone": [ + "#fafaf9", + "#f5f5f4", + "#e7e5e4", + "#d6d3d1", + "#a8a29e", + "#78716c", + "#57534e", + "#44403c", + "#292524", + "#1c1917", + ], + "success": "#86efac", + "tableText": "#111", + "teal": [ + "#f0fdfa", + "#ccfbf1", + "#99f6e4", + "#5eead4", + "#2dd4bf", + "#14b8a6", + "#0d9488", + "#0f766e", + "#115e59", + "#134e4a", + ], + "text": "#111", + "textMuted": "#333", + "transparent": "transparent", + "violet": [ + "#f5f3ff", + "#ede9fe", + "#ddd6fe", + "#c4b5fd", + "#a78bfa", + "#8b5cf6", + "#7c3aed", + "#6d28d9", + "#5b21b6", + "#4c1d95", + ], + "warning": "#fde047", + "white": "#fff", + "yellow": [ + "#fefce8", + "#fef9c3", + "#fef08a", + "#fde047", + "#facc15", + "#eab308", + "#ca8a04", + "#a16207", + "#854d0e", + "#713f12", + ], + "zinc": [ + "#fafafa", + "#f4f4f5", + "#e4e4e7", + "#d4d4d8", + "#a1a1aa", + "#71717a", + "#52525b", + "#3f3f46", + "#27272a", + "#18181b", + ], + }, + "config": { + "initialColorModeName": "dark", + "useColorSchemeMediaQuery": false, + "useLocalStorage": true, + }, + "fontSizes": [ + ".875rem", + "1rem", + "1.25rem", + "1.375rem", + "1.5rem", + "1.875rem", + "2.25rem", + "3rem", + "4rem", + "4.5rem", + ], + "fontWeights": { + "black": 900, + "body": 400, + "bold": 700, + "extrabold": 800, + "hairline": 100, + "heading": 700, + "light": 300, + "medium": 500, + "normal": 400, + "semibold": 600, + "thin": 200, + }, + "fonts": { + "body": "Crimson Text, Georgia, Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol", + "heading": "-apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial, sans-serif", + "mono": "ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace", + "monospace": "Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace", + "sans": "-apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial, sans-serif", + "serif": "Crimson Text, Georgia, Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol", + }, + "global": { + "@keyframes wobble": { + "0%, 100%": { + "transform": "rotate(0deg)", + }, + "15%": { + "transform": "rotate(-15deg)", + }, + "30%": { + "transform": "rotate(10deg)", + }, + "45%": { + "transform": "rotate(-10deg)", + }, + "60%": { + "transform": "rotate(5deg)", + }, + "75%": { + "transform": "rotate(-5deg)", + }, + }, + "@media (prefers-reduced-motion: reduce)": { + ".emoji": { + "animation": "none !important", + }, + }, + }, + "inputs": { + "inline": { + "&:focus": { + "backgroundColor": "white", + "borderColor": "primary", + "outline": "none", + }, + "appearance": "none", + "backgroundColor": "gray.2", + "borderColor": "gray.2", + "borderRadius": "default", + "borderStyle": "solid", + "borderWidth": "2px", + "color": "gray.7", + "fontSize": "100%", + "lineHeight": "tight", + "px": 3, + "py": 2, + }, + "shadow": { + "&:focus": { + "boxShadow": "outline", + "outline": "none", + }, + "appearance": "none", + "border": "none", + "borderRadius": "default", + "boxShadow": "default", + "color": "gray.7", + "fontSize": "100%", + "lineHeight": "tight", + "px": 3, + "py": 2, + }, + "underline": { + "&:focus": { + "backgroundColor": "white", + "borderColor": "primary", + "outline": "none", + }, + "appearance": "none", + "backgroundColor": "transparent", + "border": "none", + "borderBottomColor": "primary", + "borderBottomStyle": "solid", + "borderBottomWidth": "2px", + "borderRadius": "0px", + "color": "gray.7", + "fontSize": "100%", + "lineHeight": "tight", + "px": 3, + "py": 2, + }, + }, + "layout": { + "container": { + "maxWidth": [ + "", + "98%", + "", + "", + "1440px", + ], + "px": [ + 3, + 4, + ], + "py": [ + 2, + 3, + ], + }, + }, + "letterSpacings": { + "normal": "0em", + "tight": "-0.025em", + "tighter": "-0.05em", + "wide": "0.025em", + "wider": "0.05em", + "widest": "0.1em", + }, + "lineHeights": { + "10": "2.5rem", + "3": ".75rem", + "4": "1rem", + "5": "1.25rem", + "6": "1.5rem", + "7": "1.75rem", + "8": "2rem", + "9": "2.25rem", + "body": "1.625", + "heading": "1.25", + "loose": "2", + "none": "1", + "normal": "1.5", + "relaxed": "1.625", + "snug": "1.375", + "tight": "1.25", + }, + "links": { + "homeNavigation": { + "&:hover, &:focus": { + "backgroundColor": "var(--theme-ui-colors-panel-background)", + }, + "&:not(:last-of-type)": { + "borderBottom": "var(--theme-ui-colors-panel-divider)", + }, + "color": "primary", + "display": "block", + "py": 2, + "textDecoration": "none", + }, + }, + "radii": { + "2xl": "1rem", + "3xl": "1.5rem", + "card": "8px", + "default": "4px", + "full": "9999px", + "lg": "0.5rem", + "md": "0.375rem", + "none": "0px", + "sm": "0.125rem", + "xl": "0.75rem", + }, + "shadows": { + "2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)", + "default": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", + "inner": "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)", + "lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", + "md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)", + "sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)", + "xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)", + }, + "sizes": { + "0": "0", + "1": "0.25rem", + "1/12": "8.333333%", + "1/2": "50%", + "1/3": "33.333333%", + "1/4": "25%", + "1/5": "20%", + "1/6": "16.666667%", + "10": "2.5rem", + "10/12": "83.333333%", + "11/12": "91.666667%", + "12": "3rem", + "16": "4rem", + "2": "0.5rem", + "2/12": "16.666667%", + "2/3": "66.666667%", + "2/4": "50%", + "2/5": "40%", + "2/6": "33.333333%", + "20": "5rem", + "24": "6rem", + "2xl": "42rem", + "3": "0.75rem", + "3/12": "25%", + "3/4": "75%", + "3/5": "60%", + "3/6": "50%", + "32": "8rem", + "3xl": "48rem", + "4": "1rem", + "4/12": "33.333333%", + "4/5": "80%", + "4/6": "66.666667%", + "40": "10rem", + "48": "12rem", + "4xl": "56rem", + "5": "1.25rem", + "5/12": "41.666667%", + "5/6": "83.333333%", + "56": "14rem", + "5xl": "64rem", + "6": "1.5rem", + "6/12": "50%", + "64": "16rem", + "6xl": "72rem", + "7/12": "58.333333%", + "7xl": "80rem", + "8": "2rem", + "8/12": "66.666667%", + "9/12": "75%", + "full": "100%", + "lg": "32rem", + "md": "28rem", + "prose": "65ch", + "px": "1px", + "screenHeight": "100vh", + "screenWidth": "100vw", + "sm": "24rem", + "xl": "36rem", + "xs": "20rem", + }, + "space": [ + "0", + "0.25rem", + "0.5rem", + "1rem", + "2rem", + "4rem", + "8rem", + "16rem", + "32rem", + ], + "styles": { + ".footnotes": { + "fontSize": [Function], + }, + ".text-center": { + "textAlign": "center", + }, + "Book": { + "&:hover, &:focus": { + "filter": [Function], + "transform": "scale(1.01)", + "transition": "all .35s ease-in-out", + }, + "filter": [Function], + }, + "Container": { + "px": [ + 3, + 4, + ], + "py": [ + 2, + 3, + ], + }, + "GitHubCardFooter": { + "display": "flex", + "justifyContent": "space-between", + "mt": 2, + }, + "GradientBanner": { + "@keyframes highlight": { + "100%": { + "backgroundPosition": "0 0, 0 0", + }, + }, + "alignItems": "center", + "animation": "highlight 3s infinite alternate", + "backgroundImage": " + linear-gradient(white, white), + linear-gradient(180deg, cornflowerblue, purple 50%, cornflowerblue)", + "backgroundOrigin": "padding-box, border-box", + "backgroundPosition": "0 0, 0 100%", + "backgroundRepeat": "no-repeat", + "backgroundSize": "100% 100%, 100% 200%", + "border": "20px solid transparent", + "boxSizing": "border-box", + "color": "black", + "display": "flex", + "height": "340px", + "justifyContent": "center", + "maxWidth": "100%", + "padding": "1rem", + }, + "GradientBannerDark": { + "@keyframes highlight": { + "100%": { + "backgroundPosition": "0 0, 0 0", + }, + }, + "alignItems": "center", + "animation": "highlight 3s infinite alternate", + "backgroundImage": " + linear-gradient(#252e3c, #252e3c), + linear-gradient(270deg, #00D7B9, #B95DD7 50%, #FFB367 100%);", + "backgroundOrigin": "padding-box, border-box", + "backgroundPosition": "0 0, 0 100%", + "backgroundRepeat": "no-repeat", + "backgroundSize": "100% 100%, 100% 200%", + "border": "20px solid transparent", + "boxSizing": "border-box", + "color": "light", + "display": "flex", + "height": "340px", + "justifyContent": "center", + "maxWidth": "100%", + "padding": "1rem", + }, + "Header": { + "alignItems": "center", + "color": "text", + "display": "block", + "transition": "all 0.3s ease-in-out", + "width": "100%", + }, + "InstagramItem": { + "&:hover, &:focus": { + "boxShadow": "lg", + "transform": "scale(1.015)", + }, + "background": "none", + "border": "none", + "borderRadius": "8px", + "boxShadow": "md", + "cursor": "pointer", + "overflow": "hidden", + "p": 0, + "transition": "all 200ms ease-in-out", + }, + "IntroExperienceSlide": { + "&.active-slide": { + "display": "block", + "height": "auto", + "opacity": 1, + "visibility": "initial", + }, + "display": "flex", + "height": 0, + "opacity": 0, + "visibility": "hidden", + }, + "PageFooter": { + "a": { + "color": "text", + }, + "color": "text", + "display": "block", + "width": "100%", + "zIndex": "10", + }, + "TopNavigation": { + "color": "white", + }, + "VideoWrapper": { + "height": 0, + "iframe": { + "height": "100%", + "left": 0, + "position": "absolute", + "top": 0, + "width": "100%", + }, + "paddingBottom": "56.25%", + "paddingTop": "25px", + "position": "relative", + }, + "WidgetFooter": { + "color": "text", + "fontFamily": "heading", + "textAlign": [ + "center", + "right", + ], + }, + "a": { + ":hover": { + "textDecoration": "underline", + }, + "color": "primary", + "textDecoration": "none", + }, + "code": {}, + "h1": { + "fontFamily": "heading", + "fontSize": 6, + "fontWeight": "heading", + "lineHeight": "heading", + "m": 0, + "mb": 1, + "mt": 2, + }, + "h2": { + "fontFamily": "heading", + "fontSize": 5, + "fontWeight": "heading", + "lineHeight": "heading", + "m": 0, + "mb": 1, + "mt": 2, + }, + "h3": { + "fontFamily": "heading", + "fontSize": 4, + "fontWeight": "heading", + "lineHeight": "heading", + "m": 0, + "mb": 1, + "mt": 3, + }, + "h4": { + "fontFamily": "heading", + "fontSize": 3, + "fontWeight": "heading", + "lineHeight": "heading", + "m": 0, + "mb": 1, + }, + "h5": { + "fontFamily": "heading", + "fontSize": 2, + "fontWeight": "heading", + "lineHeight": "heading", + "m": 0, + "mb": 1, + }, + "h6": { + "fontFamily": "heading", + "fontSize": 1, + "fontWeight": "heading", + "lineHeight": "heading", + "m": 0, + "mb": 2, + }, + "hr": { + "bg": "muted", + "border": 0, + "height": "1px", + "m": 3, + }, + "outlined": { + "border": "4px solid #efefef", + }, + "p": { + "fontSize": [ + 2, + 3, + ], + }, + "pre": {}, + "root": { + "color": "text", + "display": "flex", + "flexDirection": "column", + "fontFamily": "body", + "fontWeight": "body", + "lineHeight": "body", + "minHeight": "100vh", + }, + "table": { + "backgroundColor": "light", + "borderCollapse": "collapse", + "borderRadius": "10px", + "borderSpacing": 0, + "boxShadow": "0 0 10px rgba(0, 0, 0, 0.1)", + "color": "tableText", + "marginBottom": "1.5rem", + "overflow": "hidden", + "tbody tr:nth-of-type(odd)": { + "backgroundColor": "#fafafa", + }, + "th": { + "backgroundColor": "#f4f4f9", + "borderColor": "muted", + "borderTop": "2px solid", + "fontWeight": "bold", + "letterSpacing": "0.05em", + "textTransform": "uppercase", + }, + "th, td": { + "borderBottom": "1px solid", + "borderColor": "muted", + "fontSize": "1.125em", + "padding": "12px 15px", + "textAlign": "left", + }, + "width": "100%", + }, + "text": { + "inverse": { + "color": "muted", + }, + "title": { + "fontFamily": "fonts.sans", + }, + }, + "ul": { + "fontSize": [ + 2, + 3, + ], + }, + }, + "text": { + "title": { + "color": "primary", + "fontFamily": "heading", + "fontSize": [ + 1, + 2, + ], + "fontWeight": "550", + "textTransform": "uppercase", + }, + }, + "transforms": { + "rotate": { + "-180": "-180deg", + "-45": "-45deg", + "-90": "-90deg", + "0": "0", + "180": "180deg", + "45": "45deg", + "90": "90deg", + }, + "scale": { + "0": "0", + "100": "1", + "105": "1.05", + "110": "1.1", + "125": "1.25", + "150": "1.5", + "50": ".5", + "75": ".75", + "90": ".9", + "95": ".95", + }, + "skew": { + "-12": "-12deg", + "-3": "-3deg", + "-6": "-6deg", + "0": "0", + "12": "12deg", + "3": "3deg", + "6": "6deg", + }, + "transformOrigin": { + "bottom": "bottom", + "bottom-left": "bottom left", + "bottom-right": "bottom right", + "center": "center", + "left": "left", + "right": "right", + "top": "top", + "top-left": "top left", + "top-right": "top right", + }, + "translate": { + "-1/2": "-50%", + "-full": "-100%", + "0": "0", + "1": "0.25rem", + "1/2": "50%", + "10": "2.5rem", + "12": "3rem", + "16": "4rem", + "2": "0.5rem", + "20": "5rem", + "24": "6rem", + "3": "0.75rem", + "32": "8rem", + "4": "1rem", + "40": "10rem", + "48": "12rem", + "5": "1.25rem", + "56": "14rem", + "6": "1.5rem", + "64": "16rem", + "8": "2rem", + "full": "100%", + "px": "1px", + }, + }, + "transitions": { + "duration": { + "100": "100ms", + "1000": "1000ms", + "150": "150ms", + "200": "200ms", + "300": "300ms", + "500": "500ms", + "700": "700ms", + "75": "75ms", + "default": "150ms", + }, + "property": { + "all": "all", + "colors": "background-color, border-color, color, fill, stroke", + "default": "background-color, border-color, color, fill, stroke, opacity, box-shadow, transform", + "none": "none", + "opacity": "opacity", + "shadow": "box-shadow", + "transform": "transform", + }, + "timingFunction": { + "default": "cubic-bezier(0.4, 0, 0.2, 1)", + "in": "cubic-bezier(0.4, 0, 1, 1)", + "in-out": "cubic-bezier(0.4, 0, 0.2, 1)", + "linear": "linear", + "out": "cubic-bezier(0, 0, 0.2, 1)", + }, + }, + "variants": { + "cards": { + "dark": { + "backgroundColor": "teal", + }, + }, + }, + "zIndices": { + "0": 0, + "10": 10, + "20": 20, + "30": 30, + "40": 40, + "50": 50, + "auto": "auto", + }, +} +`; diff --git a/theme/src/gatsby-plugin-theme-ui/theme.spec.js b/theme/src/gatsby-plugin-theme-ui/theme.spec.js index e9aa1c3e..e2334c6d 100644 --- a/theme/src/gatsby-plugin-theme-ui/theme.spec.js +++ b/theme/src/gatsby-plugin-theme-ui/theme.spec.js @@ -3,139 +3,147 @@ import { tailwind } from '@theme-ui/presets' import { merge } from 'theme-ui' describe('Theme Configuration', () => { - it('merges with Tailwind preset', () => { - const mergedTheme = merge(tailwind, theme) - expect(mergedTheme).toBeTruthy() - }) - - it('defaults the color mode to dark', () => { - expect(theme.config.initialColorModeName).toBe('dark') - expect(theme.config.useColorSchemeMediaQuery).toBe(false) - expect(theme.config).toHaveProperty('useLocalStorage') - }) - - it('contains custom fonts', () => { - expect(theme.fonts).toHaveProperty('sans') - expect(theme.fonts).toHaveProperty('serif') - expect(theme.fonts).toHaveProperty('mono') - }) - - it('has font sizes', () => { - expect(theme.fontSizes).toContain('.875rem') - expect(theme.fontSizes).toContain('4rem') - }) - - it('has color modes configured', () => { - expect(theme.colors.modes.dark).toHaveProperty('background', '#1e1e2f') - expect(theme.colors.modes.dark).toHaveProperty('text', '#fff') - }) - - it('contains custom card styles', () => { - expect(theme.cards.primary).toHaveProperty('background') - expect(theme.cards.actionCard).toHaveProperty('borderLeft') - }) - - it('has styles for gradient banners', () => { - expect(theme.styles.GradientBanner).toHaveProperty('backgroundImage') - }) - - it('defines card variants', () => { - expect(theme.variants.cards.dark).toHaveProperty('backgroundColor', 'teal') - }) - - it('exports floatOnHover animation', () => { - expect(floatOnHover).toHaveProperty('transition') - }) - - it('applies floatOnHover to PostCard', () => { - const postCardStyles = theme.cards.PostCard - expect(postCardStyles).toMatchObject(floatOnHover) - }) - - it('has reduced motion preference for emojis', () => { - const reducedMotionStyles = theme.global['@media (prefers-reduced-motion: reduce)'] - expect(reducedMotionStyles['.emoji']).toHaveProperty('animation', 'none !important') - }) - - it('defines glassmorphism panel styles', () => { - const panelStyles = theme.cards.PostCard - expect(panelStyles).toHaveProperty('borderRadius', '10px') - }) - - it('has layout configuration', () => { - const containerStyles = theme.layout.container - expect(containerStyles.maxWidth).toContain('1440px') - }) - - it('defines highlight keyframe animation', () => { - const highlightAnimation = theme.styles.GradientBanner['@keyframes highlight'] - expect(highlightAnimation).toHaveProperty('100%') - expect(highlightAnimation['100%']).toHaveProperty('backgroundPosition', '0 0, 0 0') - }) - - it('defines wobble keyframe animation', () => { - const wobbleAnimation = theme.global['@keyframes wobble'] - expect(wobbleAnimation['0%, 100%']).toHaveProperty('transform', 'rotate(0deg)') - expect(wobbleAnimation['15%']).toHaveProperty('transform', 'rotate(-15deg)') - }) - - it('defines button variants', () => { - expect(theme.buttons.primary).toHaveProperty('bg', 'primary') - expect(theme.buttons.secondary).toHaveProperty('bg', 'secondary') - expect(theme.buttons.gray).toHaveProperty('bg', 'gray') - }) - - it('defines badge variants', () => { - expect(theme.badges.primary).toHaveProperty('bg', 'primary') - expect(theme.badges.outline).toHaveProperty('boxShadow', 'inset 0 0 0 1px') - }) - - it('defines GitHubCardFooter styles', () => { - const footerStyles = theme.styles.GitHubCardFooter - expect(footerStyles).toHaveProperty('display', 'flex') - expect(footerStyles).toHaveProperty('justifyContent', 'space-between') - }) - - it('defines PageFooter styles', () => { - const pageFooterStyles = theme.styles.PageFooter - expect(pageFooterStyles).toHaveProperty('zIndex', '10') - expect(pageFooterStyles.a).toHaveProperty('color', 'text') - }) - - it('defines Book component styles', () => { - const bookStyles = theme.styles.Book - expect(bookStyles).toHaveProperty('filter') - expect(bookStyles['&:hover, &:focus']).toHaveProperty('transform', 'scale(1.01)') - }) - - it('defines responsive container styles', () => { - const containerStyles = theme.layout.container - expect(containerStyles).toHaveProperty('py', [2, 3]) - expect(containerStyles).toHaveProperty('px', [3, 4]) - }) - - it('defines UserProfile styles', () => { - const userProfileStyles = theme.cards.UserProfile - expect(userProfileStyles.padding(theme)).toEqual(['none', `0 ${theme.space[3]} 0 0`]) - expect(userProfileStyles).toHaveProperty('color', 'white') - }) - - it('defines InstagramItem styles', () => { - const instagramStyles = theme.styles.InstagramItem - expect(instagramStyles).toHaveProperty('cursor', 'pointer') - expect(instagramStyles).toHaveProperty('borderRadius', '8px') - }) - - it('defines Header styles', () => { - const headerStyles = theme.styles.Header - expect(headerStyles).toHaveProperty('alignItems', 'center') - expect(headerStyles).toHaveProperty('transition', 'all 0.3s ease-in-out') - }) - - it('defines VideoWrapper styles', () => { - const videoWrapperStyles = theme.styles.VideoWrapper - expect(videoWrapperStyles).toHaveProperty('position', 'relative') - expect(videoWrapperStyles).toHaveProperty('paddingBottom', '56.25%') - expect(videoWrapperStyles.iframe).toHaveProperty('position', 'absolute') + describe('a snapshot of the configuration', () => { + it('matches the snapshot', () => { + expect(theme).toMatchSnapshot() + }) + }) + + describe('properties that are expected to remain static', () => { + it('merges with Tailwind preset', () => { + const mergedTheme = merge(tailwind, theme) + expect(mergedTheme).toBeTruthy() + }) + + it('defaults the color mode to dark', () => { + expect(theme.config.initialColorModeName).toBe('dark') + expect(theme.config.useColorSchemeMediaQuery).toBe(false) + expect(theme.config).toHaveProperty('useLocalStorage') + }) + + it('contains custom fonts', () => { + expect(theme.fonts).toHaveProperty('sans') + expect(theme.fonts).toHaveProperty('serif') + expect(theme.fonts).toHaveProperty('mono') + }) + + it('has font sizes', () => { + expect(theme.fontSizes).toContain('.875rem') + expect(theme.fontSizes).toContain('4rem') + }) + + it('has color modes configured', () => { + expect(theme.colors.modes.dark).toHaveProperty('background', '#1e1e2f') + expect(theme.colors.modes.dark).toHaveProperty('text', '#fff') + }) + + it('contains custom card styles', () => { + expect(theme.cards.primary).toHaveProperty('background') + expect(theme.cards.actionCard).toHaveProperty('borderLeft') + }) + + it('has styles for gradient banners', () => { + expect(theme.styles.GradientBanner).toHaveProperty('backgroundImage') + }) + + it('defines card variants', () => { + expect(theme.variants.cards.dark).toHaveProperty('backgroundColor', 'teal') + }) + + it('exports floatOnHover animation', () => { + expect(floatOnHover).toHaveProperty('transition') + }) + + it('applies floatOnHover to PostCard', () => { + const postCardStyles = theme.cards.PostCard + expect(postCardStyles).toMatchObject(floatOnHover) + }) + + it('has reduced motion preference for emojis', () => { + const reducedMotionStyles = theme.global['@media (prefers-reduced-motion: reduce)'] + expect(reducedMotionStyles['.emoji']).toHaveProperty('animation', 'none !important') + }) + + it('defines glassmorphism panel styles', () => { + const panelStyles = theme.cards.PostCard + expect(panelStyles).toHaveProperty('borderRadius', '10px') + }) + + it('has layout configuration', () => { + const containerStyles = theme.layout.container + expect(containerStyles.maxWidth).toContain('1440px') + }) + + it('defines highlight keyframe animation', () => { + const highlightAnimation = theme.styles.GradientBanner['@keyframes highlight'] + expect(highlightAnimation).toHaveProperty('100%') + expect(highlightAnimation['100%']).toHaveProperty('backgroundPosition', '0 0, 0 0') + }) + + it('defines wobble keyframe animation', () => { + const wobbleAnimation = theme.global['@keyframes wobble'] + expect(wobbleAnimation['0%, 100%']).toHaveProperty('transform', 'rotate(0deg)') + expect(wobbleAnimation['15%']).toHaveProperty('transform', 'rotate(-15deg)') + }) + + it('defines button variants', () => { + expect(theme.buttons.primary).toHaveProperty('bg', 'primary') + expect(theme.buttons.secondary).toHaveProperty('bg', 'secondary') + expect(theme.buttons.gray).toHaveProperty('bg', 'gray') + }) + + it('defines badge variants', () => { + expect(theme.badges.primary).toHaveProperty('bg', 'primary') + expect(theme.badges.outline).toHaveProperty('boxShadow', 'inset 0 0 0 1px') + }) + + it('defines GitHubCardFooter styles', () => { + const footerStyles = theme.styles.GitHubCardFooter + expect(footerStyles).toHaveProperty('display', 'flex') + expect(footerStyles).toHaveProperty('justifyContent', 'space-between') + }) + + it('defines PageFooter styles', () => { + const pageFooterStyles = theme.styles.PageFooter + expect(pageFooterStyles).toHaveProperty('zIndex', '10') + expect(pageFooterStyles.a).toHaveProperty('color', 'text') + }) + + it('defines Book component styles', () => { + const bookStyles = theme.styles.Book + expect(bookStyles).toHaveProperty('filter') + expect(bookStyles['&:hover, &:focus']).toHaveProperty('transform', 'scale(1.01)') + }) + + it('defines responsive container styles', () => { + const containerStyles = theme.layout.container + expect(containerStyles).toHaveProperty('py', [2, 3]) + expect(containerStyles).toHaveProperty('px', [3, 4]) + }) + + it('defines UserProfile styles', () => { + const userProfileStyles = theme.cards.UserProfile + expect(userProfileStyles.padding(theme)).toEqual(['none', `0 ${theme.space[3]} 0 0`]) + expect(userProfileStyles).toHaveProperty('color', 'white') + }) + + it('defines InstagramItem styles', () => { + const instagramStyles = theme.styles.InstagramItem + expect(instagramStyles).toHaveProperty('cursor', 'pointer') + expect(instagramStyles).toHaveProperty('borderRadius', '8px') + }) + + it('defines Header styles', () => { + const headerStyles = theme.styles.Header + expect(headerStyles).toHaveProperty('alignItems', 'center') + expect(headerStyles).toHaveProperty('transition', 'all 0.3s ease-in-out') + }) + + it('defines VideoWrapper styles', () => { + const videoWrapperStyles = theme.styles.VideoWrapper + expect(videoWrapperStyles).toHaveProperty('position', 'relative') + expect(videoWrapperStyles).toHaveProperty('paddingBottom', '56.25%') + expect(videoWrapperStyles.iframe).toHaveProperty('position', 'absolute') + }) }) }) diff --git a/theme/src/selectors/metadata.js b/theme/src/selectors/metadata.js index cd7e0795..4f79d168 100644 --- a/theme/src/selectors/metadata.js +++ b/theme/src/selectors/metadata.js @@ -12,7 +12,7 @@ export const getGithubWidgetDataSource = metadata => metadata?.widgets?.github?. export const getGoodreadsUsername = metadata => metadata?.widgets?.goodreads?.username -export const getGoodreadsWidgetDataSource = metadata => metadata?.widgets.goodreads.widgetDataSource +export const getGoodreadsWidgetDataSource = metadata => metadata?.widgets?.goodreads?.widgetDataSource export const getHeadline = metadata => metadata?.headline