From a07d1c7b206904c2ed9a73d18a72ba16a92f58cd Mon Sep 17 00:00:00 2001 From: Steve Paul Date: Tue, 19 Nov 2024 23:55:11 +0530 Subject: [PATCH] Update transitions to persist theme color smoothly --- src/components/Card.css | 81 ++-- src/components/Card.jsx | 26 +- src/components/CardsContainer.jsx | 44 +- src/components/CategoryNavItem.jsx | 66 +-- src/components/Dashboard.jsx | 19 +- src/layouts/Layout.astro | 670 +++++++++++++++++------------ src/layouts/theme.js | 53 --- 7 files changed, 510 insertions(+), 449 deletions(-) delete mode 100644 src/layouts/theme.js diff --git a/src/components/Card.css b/src/components/Card.css index c4775d0..5fb8526 100644 --- a/src/components/Card.css +++ b/src/components/Card.css @@ -1,53 +1,58 @@ .link-card { - list-style: none; - display: flex; - background-color: var(--background-secondary); - background-position: 100%; - border-radius: var(--spacing-03); - height: 8.5rem; - position: relative; - --shadow-color: rgb(0 0 0 / 0.04); - box-shadow: 0px 0px 0px 1px var(--background-selected), - 0px 1px 1px -0.5px var(--shadow-color), - 0px 3px 3px -1.5px var(--shadow-color), - 0px 12px 12px -6px var(--shadow-color); - transition:all .2s ease-out; + list-style: none; + display: flex; + background-color: var(--background-secondary); + background-position: 100%; + border-radius: var(--spacing-03); + height: 8.5rem; + position: relative; + --shadow-color: rgb(0 0 0 / 0.04); + box-shadow: + 0px 0px 0px 1px var(--background-selected), + 0px 1px 1px -0.5px var(--shadow-color), + 0px 3px 3px -1.5px var(--shadow-color), + 0px 12px 12px -6px var(--shadow-color); + content-visibility: auto; + contain-intrinsic-size: 8.5rem; + will-change: transform; + transition: box-shadow 0.2s ease-out; } -.link-card>a { - width: 100%; - text-decoration: none; - padding: 0.8rem 1.2rem; - color: var(--support-info); - justify-content: space-between; +.link-card > a { + width: 100%; + text-decoration: none; + padding: 0.8rem 1.2rem; + color: var(--support-info); + justify-content: space-between; } p { - color: var(--text-secondary); + color: var(--text-secondary); } .link-card:is(:hover, :focus-within) { - background-position: 0; - box-shadow: 0px 0px 0px 2px var(--link), - 0px 1px 1px -0.5px var(--shadow-color), - 0px 3px 3px -1.5px var(--shadow-color), - 0px 12px 12px -6px var(--shadow-color); + background-position: 0; + box-shadow: + 0px 0px 0px 2px var(--link), + 0px 1px 1px -0.5px var(--shadow-color), + 0px 3px 3px -1.5px var(--shadow-color), + 0px 12px 12px -6px var(--shadow-color); } p.distribution { - margin: var(--spacing-00); - position: absolute; - bottom: var(--spacing-06); + margin: var(--spacing-00); + position: absolute; + bottom: var(--spacing-06); } span.tag { - background-color: var(--background-selected); - padding: calc(.25rem - 1px) calc(.5rem - 1px); - border-radius: var(--spacing-02); - display: inline-block; - color: var(--text-secondary); - margin-top: var(--spacing-08); - font-size: var(--desktop-caption); - line-height: var(--lh-desktop-caption); - font-family: var(--body-copy); -} \ No newline at end of file + background-color: var(--background-selected); + padding: calc(0.25rem - 1px) calc(0.5rem - 1px); + border-radius: var(--spacing-02); + display: inline-block; + color: var(--text-secondary); + margin-top: var(--spacing-08); + font-size: var(--desktop-caption); + line-height: var(--lh-desktop-caption); + font-family: var(--body-copy); +} diff --git a/src/components/Card.jsx b/src/components/Card.jsx index 83bcfad..533052c 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -1,19 +1,17 @@ import "./Card.css"; export default function Card(props) { - const {href, title, body, tag} = props; + const { href, title, body, tag } = props; - return
  • - - - {title} - -

    - {body} -

    -

    - {tag} -

    -
    -
  • + return ( +
  • + + {title} +

    {body}

    +

    + {tag} +

    +
    +
  • + ); } diff --git a/src/components/CardsContainer.jsx b/src/components/CardsContainer.jsx index e54aa6b..3afbb76 100644 --- a/src/components/CardsContainer.jsx +++ b/src/components/CardsContainer.jsx @@ -1,33 +1,29 @@ +import { useMemo } from "react"; import Card from "./Card"; import "./CardsContainer.css"; +import data from "../data/tools.json"; -import data from "../data/tools.json" +export default function CardsContainer({ filter }) { + const filteredCards = useMemo(() => { + return data.tools + .filter((item) => filter === "all" || filter === item.category) + .flatMap((item) => item.content) + .sort((a, b) => a.title.localeCompare(b.title)); + }, [filter]); -export default function CardsContainer(props) { - const { filter } = props; - - return
    -
    -} \ No newline at end of file + ))} + + + ); +} diff --git a/src/components/CategoryNavItem.jsx b/src/components/CategoryNavItem.jsx index 527028b..dab0fea 100644 --- a/src/components/CategoryNavItem.jsx +++ b/src/components/CategoryNavItem.jsx @@ -4,39 +4,47 @@ import data from "../data/tools.json"; import "./CategoryNavItem.css"; export default function CategoryNavItem(props) { - const { title, category, filter } = props; - const [isActive, setIsActive] = useState(false); + const { title, category, filter } = props; + const [isActive, setIsActive] = useState(false); - const getCategoryCount = () => { - if (category === "all") { - return data.tools.reduce((acc, item) => acc + item.content.length, 0); - } + const handleNavigation = (e) => { + e.preventDefault(); + navigate(`/categories/${category}`, { + history: "push", + state: { category }, + }); + }; - const navItemData = data.tools.filter((item) => item.category === category); - return navItemData[0]?.content.length; - }; + const getCategoryCount = () => { + if (category === "all") { + return data.tools.reduce((acc, item) => acc + item.content.length, 0); + } - useEffect(() => { - let subscription = true; + const navItemData = data.tools.filter((item) => item.category === category); + return navItemData[0]?.content.length; + }; - if (filter === category) { - setIsActive(true); - } else { - setIsActive(false); - } + useEffect(() => { + let subscription = true; - return () => (subscription = !subscription); - }, [filter]); + if (filter === category) { + setIsActive(true); + } else { + setIsActive(false); + } - return ( - - ); + return () => (subscription = !subscription); + }, [filter]); + + return ( + + ); } diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index a59b712..0a68a73 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -1,11 +1,18 @@ +import { useEffect, useState } from "react"; import CategoryNav from "./CategoryNav"; import CardsContainer from "./CardsContainer"; export default function Dashboard({ category }) { - return ( - <> - - - - ); + const [currentCategory, setCurrentCategory] = useState(category); + + useEffect(() => { + setCurrentCategory(category); + }, [category]); + + return ( + <> + + + + ); } diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 54c4124..b5323e6 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,8 +1,10 @@ --- +import { ViewTransitions } from "astro:transitions"; + export interface Props { - site: string; - title: string; - tagline: string; + site: string; + title: string; + tagline: string; } const { site, title, tagline } = Astro.props; @@ -10,308 +12,406 @@ const { site, title, tagline } = Astro.props; - - - - - - - {site} — Discover AI tools curated for makers and SMBs. - - - - - - - - - + + + + + + + {site} — Discover AI tools curated for makers and SMBs. + + + + + + + + + - -
    - -
    - Submit a Tool - -
    -
    + +
    + +
    + Submit a Tool + +
    +
    -
    -
    -

    - {title} -

    -

    {tagline}

    -
    -
    - +
    +
    +

    + {title} +

    +

    + {tagline} +

    +
    +
    + - - - + + - - + + diff --git a/src/layouts/theme.js b/src/layouts/theme.js deleted file mode 100644 index 5ffce6a..0000000 --- a/src/layouts/theme.js +++ /dev/null @@ -1,53 +0,0 @@ -const storageKey = 'theme-preference' - -const onClick = () => { - // flip current value - theme.value = theme.value === 'light' - ? 'dark' - : 'light' - - setPreference() -} - -const getColorPreference = () => { - if (localStorage.getItem(storageKey)) - return localStorage.getItem(storageKey) - else - return window.matchMedia('(prefers-color-scheme: dark)').matches - ? 'dark' - : 'light' -} - -const setPreference = () => { - localStorage.setItem(storageKey, theme.value) - reflectPreference() -} - -const reflectPreference = () => { - document.firstElementChild - .setAttribute('data-new-ui-theme', theme.value) - - document - .querySelector('#theme-toggle') - ?.setAttribute('aria-label', theme.value) -} - -const theme = { - value: getColorPreference(), -} - -reflectPreference() - -window.onload = () => { - reflectPreference() - document - .querySelector('#theme-toggle') - .addEventListener('click', onClick) -} - -window - .matchMedia('(prefers-color-scheme: dark)') - .addEventListener('change', ({matches:isDark}) => { - theme.value = isDark ? 'dark' : 'light' - setPreference() - }) \ No newline at end of file