diff --git a/package.json b/package.json index 80e42f3..c8027d7 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,10 @@ }, "dependencies": { "focus-trap-react": "^10.2.3", + "keen-slider": "^6.8.6", + "next": "14.2.3", "react": "^18", - "react-dom": "^18", - "next": "14.2.3" + "react-dom": "^18" }, "devDependencies": { "@svgr/webpack": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab9efee..7057d91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: focus-trap-react: specifier: ^10.2.3 version: 10.2.3(prop-types@15.8.1)(react-dom@18.3.1)(react@18.3.1) + keen-slider: + specifier: ^6.8.6 + version: 6.8.6 next: specifier: 14.2.3 version: 14.2.3(@babel/core@7.24.5)(react-dom@18.3.1)(react@18.3.1)(sass@1.77.1) @@ -1653,6 +1656,7 @@ packages: engines: { node: '>=6.9.0' } dependencies: regenerator-runtime: 0.14.1 + dev: true /@babel/template@7.24.0: resolution: @@ -2001,293 +2005,6 @@ packages: engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } dev: true - /@radix-ui/primitive@1.0.1: - resolution: - { - integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== - } - dependencies: - '@babel/runtime': 7.24.5 - dev: false - - /@radix-ui/react-accordion@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): - resolution: - { - integrity: sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg== - } - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-direction': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): - resolution: - { - integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg== - } - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@radix-ui/react-collection@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): - resolution: - { - integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA== - } - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-context@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-direction@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-id@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): - resolution: - { - integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== - } - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): - resolution: - { - integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== - } - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@radix-ui/react-slot@1.0.2(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - - /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.2)(react@18.3.1): - resolution: - { - integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== - } - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 - react: 18.3.1 - dev: false - /@rushstack/eslint-patch@1.10.2: resolution: { @@ -2540,6 +2257,7 @@ packages: { integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== } + dev: true /@types/react-dom@18.3.0: resolution: @@ -3314,6 +3032,7 @@ packages: { integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== } + dev: true /damerau-levenshtein@1.0.8: resolution: @@ -5049,6 +4768,13 @@ packages: object.values: 1.2.0 dev: true + /keen-slider@6.8.6: + resolution: + { + integrity: sha512-dcEQ7GDBpCjUQA8XZeWh3oBBLLmyn8aoeIQFGL/NTVkoEOsmlnXqA4QykUm/SncolAZYGsEk/PfUhLZ7mwMM2w== + } + dev: false + /keyv@4.5.4: resolution: { @@ -5838,6 +5564,7 @@ packages: { integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== } + dev: true /regenerator-transform@0.15.2: resolution: diff --git a/src/app/Home.scss b/src/app/Home.scss index 63328ec..54555fc 100644 --- a/src/app/Home.scss +++ b/src/app/Home.scss @@ -38,12 +38,15 @@ @media (min-width: $mobile-breakpoint) { padding-block: $main-padding-desktop-block; padding-inline: $main-padding-desktop-inline; - height: 100vh; h2 { margin-bottom: 40px; } } + + @media (min-width: $tablet-breakpoint) { + height: 100vh; + } } } } diff --git a/src/app/assets/images/pomegranate.webp b/src/app/assets/images/pomegranate.webp new file mode 100644 index 0000000..d8e7f76 Binary files /dev/null and b/src/app/assets/images/pomegranate.webp differ diff --git a/src/app/components/ThemesSlider/SliderArrow/SliderArrow.scss b/src/app/components/ThemesSlider/SliderArrow/SliderArrow.scss new file mode 100644 index 0000000..1e37305 --- /dev/null +++ b/src/app/components/ThemesSlider/SliderArrow/SliderArrow.scss @@ -0,0 +1,28 @@ +.slider-arrow { + border: none; + background-color: $primary-black; + padding: 10px 18px; + + svg { + width: 10px; + height: 15px; + fill: none; + stroke: $primary-white; + stroke-width: 2px; + cursor: pointer; + } + + &.arrow--left { + border-radius: 5px 0 0 5px; + } + + &.arrow--right { + border-radius: 0 5px 5px 0; + } + + &.arrow--disabled { + svg { + stroke: $outline-gray; + } + } +} diff --git a/src/app/components/ThemesSlider/SliderArrow/SliderArrow.tsx b/src/app/components/ThemesSlider/SliderArrow/SliderArrow.tsx new file mode 100644 index 0000000..175d2f9 --- /dev/null +++ b/src/app/components/ThemesSlider/SliderArrow/SliderArrow.tsx @@ -0,0 +1,35 @@ +/*eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }]*/ + +import './SliderArrow.scss'; + +type SliderArrowProps = { + disabled: boolean; + left?: boolean; + onClick: (_e: any) => void; +}; + +// TODO: consider replacing svgs with react svg element + +export default function SliderArrow({ + disabled, + left, + onClick +}: SliderArrowProps) { + const disabledClass = disabled ? ' arrow--disabled' : ''; + return ( + + ); +} diff --git a/src/app/components/ThemesSlider/ThemeSlide/ThemeSlide.scss b/src/app/components/ThemesSlider/ThemeSlide/ThemeSlide.scss new file mode 100644 index 0000000..73d66b0 --- /dev/null +++ b/src/app/components/ThemesSlider/ThemeSlide/ThemeSlide.scss @@ -0,0 +1,88 @@ +.theme-slide { + /* variables */ + $slide-margin: 20px; + + margin: $slide-margin; + border: none; + + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 420px; + max-height: 575px; + + .top-section { + h3 { + display: inline-block; + border-radius: 5px; + padding: 10px; + line-height: 1; + font-size: $p-size; + } + } + + .bottom-section { + hr { + border: 1px solid #bababa; + margin-block: $slide-margin; + } + } + + h4 { + text-transform: uppercase; + font-size: $h3-size; + } + + p { + margin-block-start: $slide-margin; + } + + .non-profit-container { + display: flex; + flex-wrap: wrap; + gap: 1rem; + padding-left: 0; + list-style-type: none; + max-width: 80%; + + @media (min-width: $mobile-breakpoint) { + max-width: 100%; + } + + .non-profit { + a { + text-decoration: none; + font-family: $p-font; + outline: none; + background-color: white; + display: flex; + flex-wrap: wrap; + padding: 10px; + line-height: 1; + border: 1px solid $primary-black; + border-radius: 5px; + margin-block-start: 0; + cursor: pointer; + transition: + background-color 0.3s, + color 0.3s; + + &:is(:hover, :focus-visible) { + background-color: $primary-black; + color: white; + } + } + } + } + + @media (min-width: $mobile-breakpoint) { + padding: $slide-margin; + border: 1px solid $outline-gray; + } + + @media (min-width: $tablet-breakpoint) { + margin: 0; + min-height: auto; + height: 100%; + } +} diff --git a/src/app/components/ThemesSlider/ThemeSlide/ThemeSlide.tsx b/src/app/components/ThemesSlider/ThemeSlide/ThemeSlide.tsx new file mode 100644 index 0000000..a425354 --- /dev/null +++ b/src/app/components/ThemesSlider/ThemeSlide/ThemeSlide.tsx @@ -0,0 +1,34 @@ +import './ThemeSlide.scss'; +import type { SlideContent } from '../ThemesSlider'; + +type content = { + content: SlideContent; +}; + +export default function ThemeSlide({ content }: content) { + return ( +
+
+

{content.theme}

+

{content.description}

+
+
+

Non-profits

+
+ +
+
+ ); +} diff --git a/src/app/components/ThemesSlider/ThemesSlider.scss b/src/app/components/ThemesSlider/ThemesSlider.scss new file mode 100644 index 0000000..58cd9ef --- /dev/null +++ b/src/app/components/ThemesSlider/ThemesSlider.scss @@ -0,0 +1,92 @@ +.theme-slider-container { + /* variables */ + $dot-size: 2px; + $dot-gap: 7px; + $hide-slides-gradient: linear-gradient( + 90deg, + $primary-white 0%, + rgba(252, 252, 252, 0) 22.19%, + rgba(252, 252, 252, 0) 78.04%, + $primary-white 100% + ); + + border: 1px solid $outline-gray; + + width: calc(100vw - 2 * $main-padding-mobile-inline); + margin-block-start: 10px; + padding: 0; + + .theme-slider-nav { + display: grid; + grid-template-rows: 1fr; + grid-template-columns: 1fr; + } + + .arrows { + display: none; + } + + .dots { + width: 100%; + padding: 10px 0; + display: flex; + align-items: center; + justify-content: center; + grid-area: 1 / 1 / 2 / 2; + + .dot { + background-color: $outline-gray; + border-color: transparent; + border-radius: 50%; + margin: 0 $dot-gap; + padding: $dot-size; + cursor: pointer; + } + + .dot.active { + background: $primary-black; + } + } + + @media ($mobile-breakpoint < width < $tablet-breakpoint) { + width: calc(100vw - 2 * $main-padding-desktop-inline); + + .keen-slider::before { + content: ''; + z-index: 1; + width: calc(100vw - 2 * clamp(50px, 25px + 1.8vw, 80px)); + height: 100%; + display: block; + position: absolute; + background: $hide-slides-gradient; + } + + .arrows { + display: flex; + gap: 2px; + grid-area: 1 / 1 / 2 / 2; + padding: 10px; + } + } + + @media (min-width: $tablet-breakpoint) { + height: 100%; + + .keen-slider { + height: 100%; + } + + & { + width: calc( + 100vw - clamp(250px, 200px + 11vw, 470px) - 2 * + $main-padding-desktop-inline + ); + + border: none; + } + + .dots { + display: none; + } + } +} diff --git a/src/app/components/ThemesSlider/ThemesSlider.tsx b/src/app/components/ThemesSlider/ThemesSlider.tsx new file mode 100644 index 0000000..1b1915d --- /dev/null +++ b/src/app/components/ThemesSlider/ThemesSlider.tsx @@ -0,0 +1,98 @@ +'use client'; + +import { useKeenSlider } from 'keen-slider/react'; +import 'keen-slider/keen-slider.min.css'; + +import './ThemesSlider.scss'; +import ThemeSlide from './ThemeSlide/ThemeSlide'; +import SliderArrow from './SliderArrow/SliderArrow'; + +import { useState } from 'react'; + +export type SlideContent = { + theme: string; + themeColor?: string; + description: string; + nonProfits: { + link: string; + text: string; + }[]; +}; + +export default function ThemesSlider({ + slidesContent +}: { + slidesContent: Array; +}) { + const [currentSlide, setCurrentSlide] = useState(0); + const [loaded, setLoaded] = useState(false); + + const [sliderRef, instanceRef] = useKeenSlider({ + initial: 0, + breakpoints: { + '(min-width: 550px)': { + slides: { origin: 'center', perView: 1.5, spacing: 10 } + }, + '(min-width: 979px)': { + slides: { perView: 3, spacing: 20 } + } + }, + slides: { + perView: 1 + }, + slideChanged(slider) { + setCurrentSlide(slider.track.details.rel); + }, + created() { + setLoaded(true); + } + }); + + //TODO: add aria controls and labels to slide navigation + + return ( +
+
+ {slidesContent.map(slide => ( +
+ +
+ ))} +
+ +
+ + {loaded && + [...Array(instanceRef.current?.slides.length)].map( + (_, slideIdx) => ( + + ) + )} + + + { + e.stopPropagation(); + instanceRef.current?.prev(); + }} + disabled={currentSlide === 0} + /> + { + e.stopPropagation(); + instanceRef.current?.next(); + }} + disabled={currentSlide === 2} + /> + +
+
+ ); +} diff --git a/src/app/pages/Themes/Themes.scss b/src/app/pages/Themes/Themes.scss index d7adcb8..139446b 100644 --- a/src/app/pages/Themes/Themes.scss +++ b/src/app/pages/Themes/Themes.scss @@ -1,2 +1,45 @@ #themes { + display: flex; + flex-direction: column; + position: relative; + + @media (min-width: $tablet-breakpoint) { + overflow: hidden; + } + + h2 { + margin-bottom: 0; + } + + .title-line { + border: 1px solid #bababa; + margin-block: 1rem; + + @media (min-width: $tablet-breakpoint) { + margin-block: 2rem; + } + } + + .pomegranate-container { + position: absolute; + // bottom: calc(-15% - 5vw); + bottom: 0; + right: -100px; + z-index: 1; + height: fit-content; + width: calc(160px + 8vw); + + .pomegranate { + transform: rotate(-20deg); + object-fit: contain; + width: 100%; + height: fit-content; + } + + @media (min-width: $tablet-breakpoint) { + right: auto; + bottom: max(calc(-75px - 6.5vw), -200px); + left: 150px; + } + } } diff --git a/src/app/pages/Themes/Themes.tsx b/src/app/pages/Themes/Themes.tsx index 2e96fcc..9fd9470 100644 --- a/src/app/pages/Themes/Themes.tsx +++ b/src/app/pages/Themes/Themes.tsx @@ -1,6 +1,11 @@ import './Themes.scss'; +import ThemesSlider from '@/components/ThemesSlider/ThemesSlider'; +import { ThemesContent } from './constants'; +import pomegranateImg from '@/assets/images/pomegranate.webp'; +import Image from 'next/image'; import { PageRef } from '@/page'; + type ThemesProps = { themesRef: PageRef; }; @@ -9,7 +14,13 @@ export default function Themes({ themesRef }: ThemesProps) { return (

.03 / Themes

-

{`What are this year's UP-Grade themes?`}

+

{`Get a Taste Of Our Fresh Themes.`}

+
+ {/*

Swipe right to see more.

*/} + +
+ Pomegranate +
); } diff --git a/src/app/pages/Themes/constants.ts b/src/app/pages/Themes/constants.ts new file mode 100644 index 0000000..d6c340b --- /dev/null +++ b/src/app/pages/Themes/constants.ts @@ -0,0 +1,54 @@ +export const ThemesContent = [ + { + theme: 'Sustainability', + themeColor: '#9BFF76', + description: + 'Sustainability nonprofits here in San Diego are dedicated to fostering a more just world, empowering people to take care of our planet through public policy, education, and outreach. Their work is vital in mobilizing local communities to drive greater environmental change.', + nonProfits: [ + { + text: 'MPA Collaborative Network', + link: 'https://www.mpacollaborative.org/' + }, + { + text: 'SanDiego360', + link: 'https://sandiego350.org/' + } + ] + }, + { + theme: 'Community', + themeColor: '#92E9FF', + description: + 'Community-focused nonprofit organizations here in San Diego tackle basic needs insecurities, like food, housing, and healthcare crises through accessible medical support, healthy meals, and services that aid the search for affordable housing. With remarkable resilience and innovation, these groups foster significant, empathetic change in their local communities', + nonProfits: [ + { + text: 'HandsOn San Diego', + link: 'https://www.handsonsandiego.org/' + }, + { + text: 'SAY San Diego', + link: 'https://sdmilitaryfamily.org' + }, + { + text: 'Vietnamese American Youth Alliance', + link: 'https://www.sdtet.com/' + } + ] + }, + { + theme: 'Education', + themeColor: '#FFA0DC', + description: + 'Nonprofit organizations here in San Diego thrive on their commitment to accessible education. From mentoring/tutoring services to outdoor recreational courses, these groups provide learning opportunities regardless of age, socio-economic status, and other barriers! They work hard to provide opportunities for local youth to develop the skills and knowledge they need to succeed.', + nonProfits: [ + { + text: 'The League of Amazing Programmers', + link: 'https://www.jointheleague.org/' + }, + { + text: 'Triton Consulting Group', + link: 'https://www.ucsdtcg.org/' + } + ] + } +]; diff --git a/src/app/styles/variables.scss b/src/app/styles/variables.scss index b3eea06..3f2027d 100644 --- a/src/app/styles/variables.scss +++ b/src/app/styles/variables.scss @@ -1,6 +1,9 @@ // Colors $primary-black: #212121; -$seondary-yellow: #f5ff85; + +$primary-white: #fcfcfc; +$secondary-yellow: #f5ff85; +$outline-gray: #bababa; // Font Families $p-font: var(--font-aspekta);