diff --git a/static/css/common.css b/static/css/common.css index c0c4d8dcbd..d5b68ac8e9 100644 --- a/static/css/common.css +++ b/static/css/common.css @@ -753,4 +753,27 @@ a:active { } .static label .int-he .sub{ margin-right: 4px; +} +.categoryColorLineRainbow { + top: 60px; + left: 0; + width: 100%; + height: 4px; + z-index: 101; + background: linear-gradient( + 90deg, + var(--tanakh-teal) 0% 10%, + var(--commentary-blue) 10% 20%, + var(--mussar-purple) 20% 30%, + var(--mishnah-blue) 30% 40%, + var(--talmud-gold) 40% 50%, + var(--midrash-green) 50% 60%, + var(--halakhah-red) 60% 70%, + var(--philosophy-purple) 70% 80%, + var(--taanitic-green) 80% 90%, + var(--chasidut-green) 90% 100% + ); +} +.categoryColorLineRainbow.fixedBar{ + position: fixed; } \ No newline at end of file diff --git a/static/css/s2.css b/static/css/s2.css index 9dbc6f74a7..bfd4663b15 100644 --- a/static/css/s2.css +++ b/static/css/s2.css @@ -4837,14 +4837,24 @@ body .ui-autocomplete.dictionary-toc-autocomplete .ui-menu-item a.ui-state-focus justify-content: center; } +.topic-landing-page-content{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.readerNavMenu .content .contentInner.topic-landing-page-content{ + width: 843px; +} + .interface-hebrew .topic-landing-page-wrapper{ direction: rtl; } .topic-landing-search-container{ - overflow: hidden; display: flex; align-items: center; + flex-direction: column; padding: 0; text-align: inherit; background: #EDEDEC; @@ -4856,6 +4866,7 @@ body .ui-autocomplete.dictionary-toc-autocomplete .ui-menu-item a.ui-state-focus .topic-landing-search-input-box-wrapper{ display: flex; + margin-top: 15px; } .topic-landing-search-input{ @@ -4875,14 +4886,12 @@ body .ui-autocomplete.dictionary-toc-autocomplete .ui-menu-item a.ui-state-focus display: flex; list-style-type: none; padding: 6px 12px; - /*font-family: 'EB Garamond';*/ font-family: 'Adobe Garamond Pro'; font-style: normal; font-weight: 400; font-size: 18px; line-height: 23px; cursor: pointer; - /*width: max-content;*/ flex-grow: 1; max-width: 100%; min-height: 10px; @@ -4900,17 +4909,13 @@ body .ui-autocomplete.dictionary-toc-autocomplete .ui-menu-item a.ui-state-focus .topic-landing-search-dropdown{ background: #FFFFFF; - position: absolute; - top: 218px; - /*width: auto;*/ - /*max-width: 130%;*/ width: 606px; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); border-radius: 0px 0px 6px 4px; padding: 10px; max-height: calc(1.9em * 10 + 2em); /* 2.5em is an estimate of the height per suggestion, and 2em for padding */ - overflow-y: auto; z-index: 2; + margin-top: 14px; } .topic-landing-search-dropdown:empty { padding: 0; @@ -4921,6 +4926,49 @@ body .ui-autocomplete.dictionary-toc-autocomplete .ui-menu-item a.ui-state-focus top: 6px; padding-inline-start: 11px; } +.topic-landing-upper-rainbow{ + margin-top: 88px; + margin-bottom: 43px; +} +.topic-landing-lower-rainbow{ + margin-top: 43px; +} +/*'Dummy' font, a hack to prevent the ellipsis char from being displayed at the end of a webkit line-clamped element*/ +/*This font addresses only the ellipsis char, rendering its size 0% */ +@font-face { + font-family: "hide-ellipsis-char-font"; + src: local("Courier"); + unicode-range: U+2026; + size-adjust: 0%; +} + + +.salad-container{ + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: var(--num-lines); + text-overflow: clip; + font-family: hide-ellipsis-char-font; +} + +.topic-salad{ + width: 843px; + font-size: 22px; + font-weight: 400; + line-height: 32px; + text-align: center; + text-underline-position: from-font; + text-decoration-skip-ink: none; +} +.topic-salad-item{ + margin: 11px; + --english-font: var(--english-sans-serif-font-family); + --hebrew-font: var(--hebrew-sans-serif-font-family); +} +.no-wrapping-salad-item-container{ + white-space: nowrap; +} .readerNavMenu .sheet { display: flex; diff --git a/static/css/static.css b/static/css/static.css index 4b1e6608c1..57dce0bcf7 100644 --- a/static/css/static.css +++ b/static/css/static.css @@ -1747,15 +1747,6 @@ body.interface-hebrew #visualGardenPage .filter-title .reset { #koschitzky.static { margin-top: 60px; } -.static .categoryColorLineRainbow { - position: fixed; - top: 60px; - left: 0; - width: 100%; - height: 4px; - z-index: 101; - background: linear-gradient(90deg, #00505E 0% 10%, #5698B4 10% 20%, #CCB37C 20% 30%, #5B9370 30% 40%, #823241 40% 50%, #5A4474 50% 60%, #AD4F66 60% 70%, #7285A6 70% 80%, #00807E 80% 90%, #4872B3 90% 100%) -} /******* mobile landing page ****/ #mobilePage{ diff --git a/static/js/RainbowLine.jsx b/static/js/RainbowLine.jsx new file mode 100644 index 0000000000..292620d283 --- /dev/null +++ b/static/js/RainbowLine.jsx @@ -0,0 +1,7 @@ +import React from "react"; + +export const RainbowLine = ({rainbowClassname}) => { + return ( +
+ ); +}; \ No newline at end of file diff --git a/static/js/TopicLandingPage/TopicLandingSearch.jsx b/static/js/TopicLandingPage/TopicLandingSearch.jsx index 0ddb9c9a23..b3b7a61d1a 100644 --- a/static/js/TopicLandingPage/TopicLandingSearch.jsx +++ b/static/js/TopicLandingPage/TopicLandingSearch.jsx @@ -109,7 +109,8 @@ export const TopicLandingSearch = ({openTopic, numOfTopics}) => { renderItems={renderItems.bind(null, openTopic)} containerClassString="topic-landing-search-container" dropdownMenuClassString="topic-landing-search-dropdown" - renderInput={renderInput.bind(null, openTopic, numOfTopics)}/> + renderInput={renderInput.bind(null, openTopic, numOfTopics)} + />
); }; \ No newline at end of file diff --git a/static/js/TopicLandingPage/TopicSalad.jsx b/static/js/TopicLandingPage/TopicSalad.jsx new file mode 100644 index 0000000000..ee72e7bffc --- /dev/null +++ b/static/js/TopicLandingPage/TopicSalad.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {useEffect, useState} from "react"; +import {WordSalad} from "../WordSalad"; +import Sefaria from "../sefaria/sefaria"; +import {InterfaceText} from "../Misc"; +import {RainbowLine} from "../RainbowLine"; + + +export const TopicSalad = () => { + + const [salad, setSalad] = useState([]); + + const renderSaladItem = (item) => { + return( + + ) + } + + const fetchRandomSaladItems = async () => { + const poolName = Sefaria.getLangSpecificTopicPoolName('general'); + const topics = await Sefaria.getTopicsByPool(poolName, 50); + const saladItems = topics.map(topic=>({slug: topic.slug, text: topic.primaryTitle})); + return saladItems; + } + + const loadSalad = async () => { + const saladItems = await fetchRandomSaladItems(); + setSalad(saladItems); + }; + + useEffect(() => { + loadSalad(); + }, []); + + return ( + <> + +
+ +
+ + + + ); +}; \ No newline at end of file diff --git a/static/js/TopicLandingPage/TopicsLandingPage.jsx b/static/js/TopicLandingPage/TopicsLandingPage.jsx index a5dfa14104..f235e22cfc 100644 --- a/static/js/TopicLandingPage/TopicsLandingPage.jsx +++ b/static/js/TopicLandingPage/TopicsLandingPage.jsx @@ -2,6 +2,8 @@ import React from 'react'; import {TopicLandingSearch} from "./TopicLandingSearch"; import {NavSidebar} from "../NavSidebar"; import Footer from "../Footer"; +import {TopicSalad} from "./TopicSalad"; +import {RainbowLine} from "../RainbowLine"; export const TopicsLandingPage = ({openTopic}) => { @@ -12,8 +14,9 @@ export const TopicsLandingPage = ({openTopic}) => {
-
+
+
diff --git a/static/js/WordSalad.jsx b/static/js/WordSalad.jsx new file mode 100644 index 0000000000..a3dabc9e8a --- /dev/null +++ b/static/js/WordSalad.jsx @@ -0,0 +1,29 @@ +import React from 'react'; + + +export const WordSalad = ({ numLines, salad, renderItem }) => { +/** + * This component renders a collection of items, styled to fit within a specified + * number of lines. Each item can be rendered using a custom `renderItem` function, and + * spaces within the items are replaced with non-breaking spaces to ensure consistent + * line breaking behavior in CSS. + * + * @param {number} props.numLines - The number of lines the container should display. + * @param {Array} props.salad - An array of objects representing the items to display. + * @param {Function} props.renderItem - A function that receives an item from the `salad` array + * and returns a React element to render it. + */ + + const renderItemWithSpacesForBreaks = (item)=>{ + // inner span to prevent wrapping on spaces mid-item, outer span with trailing space to allow wrapping between items + const trailingSpacedElement = {renderItem(item)} + return trailingSpacedElement; + } + + + return ( +
+ {salad.map(renderItemWithSpacesForBreaks)} +
+ ); +}; \ No newline at end of file diff --git a/static/js/sefaria/sefaria.js b/static/js/sefaria/sefaria.js index 494ab58c09..3cc2fe3881 100644 --- a/static/js/sefaria/sefaria.js +++ b/static/js/sefaria/sefaria.js @@ -1964,6 +1964,10 @@ _media: {}, store: this._TopicsByPool }); }, + getLangSpecificTopicPoolName: function(poolName){ + const lang = this.interfaceLang == 'hebrew' ? 'he' : 'en'; + return `${poolName}_${lang}` + }, _related: {}, related: function(ref, callback) { // Single API to bundle public links, sheets, and notes by ref. diff --git a/templates/static/henry-and-julia-koschitzky-apps.html b/templates/static/henry-and-julia-koschitzky-apps.html index 45f3f15d42..29a0bcb9a0 100644 --- a/templates/static/henry-and-julia-koschitzky-apps.html +++ b/templates/static/henry-and-julia-koschitzky-apps.html @@ -13,7 +13,7 @@ {% block content %}
-
+

Sefaria App for iOS and Android