From 1b98c96eb94f56042e69d08531fc8331d0ed98af Mon Sep 17 00:00:00 2001 From: Zakaria Boualaid Date: Mon, 6 Mar 2023 12:55:22 +0100 Subject: [PATCH 1/6] fix disappearing arrow when using drag/drop feature --- src/components/Layout/ScrollCardsNavigator.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Layout/ScrollCardsNavigator.tsx b/src/components/Layout/ScrollCardsNavigator.tsx index dfc059ee..d478ce56 100644 --- a/src/components/Layout/ScrollCardsNavigator.tsx +++ b/src/components/Layout/ScrollCardsNavigator.tsx @@ -34,6 +34,7 @@ export const ScrollCardsNavigator = () => { }, []) useLayoutEffect(() => { + setLeftButtonVisible(false) scrollBarContainer.current = document.querySelector('.Cards') }, []) @@ -48,7 +49,6 @@ export const ScrollCardsNavigator = () => { }, [handleKeyboardKeys]) useEffect(() => { - setLeftButtonVisible(false) setRightButtonVisible(cards.length > maxCardsPerRow) }, [cards]) From ad39ea0fea779cabd1e1a24ae061e07282b69b31 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 12 Mar 2023 13:28:25 +0100 Subject: [PATCH 2/6] implement: customizing the number of visible cards --- src/App.js | 7 ++- src/assets/App.css | 20 +++++--- src/assets/variables.css | 9 ++-- src/components/Elements/ChipsSet/ChipsSet.tsx | 6 ++- .../settings/components/SettingsModal.tsx | 48 ++++++++++++++++++- src/stores/preferences.ts | 4 ++ 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/App.js b/src/App.js index 43fb1fc1..22f9f4e0 100644 --- a/src/App.js +++ b/src/App.js @@ -19,7 +19,8 @@ function App() { const [showSideBar, setShowSideBar] = useState(false) const [showSettings, setShowSettings] = useState(false) const [showOnboarding, setShowOnboarding] = useState(true) - const { onboardingCompleted, firstSeenDate, markOnboardingAsCompleted } = useUserPreferences() + const { onboardingCompleted, firstSeenDate, markOnboardingAsCompleted, maxVisibleCards } = + useUserPreferences() useLayoutEffect(() => { if (!onboardingCompleted && getAppVersion() <= '1.15.9') { @@ -31,6 +32,10 @@ function App() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [onboardingCompleted, firstSeenDate]) + useEffect(() => { + document.documentElement.style.setProperty('--max-visible-cards', maxVisibleCards) + }, [maxVisibleCards]) + useEffect(() => { setupAnalytics() setupIdentification() diff --git a/src/assets/App.css b/src/assets/App.css index ae2276ce..902c5e53 100644 --- a/src/assets/App.css +++ b/src/assets/App.css @@ -1043,18 +1043,21 @@ Producthunt item .floatingFilter { display: block; } + .block { + width: 100vw; + } } /* Small devices (portrait tablets and large phones, 600px and up) */ @media only screen and (min-width: 600px) { .block { - width: calc(96vw / 2); + width: calc(96vw / min(2, var(--max-visible-cards))); } } /* Medium devices (landscape tablets, 768px and up) */ @media only screen and (min-width: 768px) { .block { - width: calc(96vw / 3); + width: calc(96vw / min(3, var(--max-visible-cards))); } .searchBarInput { width: 200px; @@ -1064,7 +1067,7 @@ Producthunt item /* Large devices (desktops, 992px and up)*/ @media only screen and (min-width: 992px) { .block { - width: calc(96vw / 3); + width: calc(96vw / min(3, var(--max-visible-cards))); } .searchBarInput { @@ -1075,14 +1078,14 @@ Producthunt item /* X-Large devices (large desktops, 1200px and up)*/ @media only screen and (min-width: 1200px) { .block { - width: calc(96vw / 4); + width: calc(96vw / min(4, var(--max-visible-cards))); } } /* XX-Large devices (larger desktops, 1400px and up)*/ @media only screen and (min-width: 1400px) { .block { - width: calc(96vw / 4); + width: calc(96vw / min(4, var(--max-visible-cards))); } } @@ -1093,7 +1096,9 @@ Producthunt item padding: 0; } .block { - width: calc((1800px - 12px * 4) / 4); + width: calc( + (1800px - 12px * min(5, var(--max-visible-cards))) / min(5, var(--max-visible-cards)) + ); } } @@ -1120,3 +1125,6 @@ Producthunt item position: relative; vertical-align: middle; } +.noMargin { + margin: 0 !important; +} diff --git a/src/assets/variables.css b/src/assets/variables.css index eae2e948..f2558e65 100644 --- a/src/assets/variables.css +++ b/src/assets/variables.css @@ -10,6 +10,10 @@ src: url('fonts/nunito/nunito-semibold.woff2') format('woff2'); } +html { + --max-visible-cards: 4; +} + html.dark { --app-name-text-color: #fff; --background-color: #0d1116; @@ -89,7 +93,7 @@ html.dark { --settings-input-border-color: #3a4553; --settings-input-border-focus-color: #6b7b90; --settings-input-placeholder-color: #42474e; - --settings-input-text-color: #fff + --settings-input-text-color: #fff; } html.light { @@ -171,6 +175,5 @@ html.light { --settings-input-border-color: #e9ebec; --settings-input-border-focus-color: #c4d6df; --settings-input-placeholder-color: #97a6ad; - --settings-input-text-color: #253b53 - + --settings-input-text-color: #253b53; } diff --git a/src/components/Elements/ChipsSet/ChipsSet.tsx b/src/components/Elements/ChipsSet/ChipsSet.tsx index 0e5e9d12..8e973870 100644 --- a/src/components/Elements/ChipsSet/ChipsSet.tsx +++ b/src/components/Elements/ChipsSet/ChipsSet.tsx @@ -1,7 +1,7 @@ +import clsx from 'clsx' import { useState } from 'react' import { Option } from 'src/types' import './chipset.css' - type ChipProps = { option: Option onSelect: (option: Option) => void @@ -19,12 +19,14 @@ const Chip = ({ option, onSelect, active = false }: ChipProps) => { type ChangeAction = 'ADD' | 'REMOVE' type ChipsSetProps = { options: Option[] + className?: string defaultValues?: string[] canSelectMultiple?: boolean onChange?: (action: ChangeAction, options: Option[]) => void } export const ChipsSet = ({ + className, options, canSelectMultiple = false, onChange, @@ -62,7 +64,7 @@ export const ChipsSet = ({ } return ( -
+
{options.map((option) => { return ( { + if (selectedChips.length) { + setMaxVisibleCards(parseInt(selectedChips[0].value)) + } + } + return ( +
+

Max number of cards to display

+
+ { + onCardsCountChange(selectedChips) + }} + /> + +

+ To ensure a seamless experience, we may adjust the selected number to align with the + resolution of your screen. +

+
+
+

Dark Mode

diff --git a/src/stores/preferences.ts b/src/stores/preferences.ts index 7c09f852..0743b85f 100644 --- a/src/stores/preferences.ts +++ b/src/stores/preferences.ts @@ -14,6 +14,7 @@ export type UserPreferencesState = { onboardingResult: Omit | null listingMode: ListingMode searchEngine: string + maxVisibleCards: number cards: SelectedCard[] cardsSettings: Record firstSeenDate: number @@ -28,6 +29,7 @@ type UserPreferencesStoreActions = { setListingMode: (listingMode: ListingMode) => void setCards: (selectedCards: SelectedCard[]) => void setTags: (selectedTags: Tag[]) => void + setMaxVisibleCards: (maxVisibleCards: number) => void setCardSettings: (card: string, settings: CardSettingsType) => void markOnboardingAsCompleted: (occupation: Omit | null) => void setUserCustomCards: (cards: SupportedCardType[]) => void @@ -39,6 +41,7 @@ export const useUserPreferences = create( (set) => ({ userSelectedTags: [], cardsSettings: {}, + maxVisibleCards: 4, theme: 'dark', onboardingCompleted: false, onboardingResult: null, @@ -59,6 +62,7 @@ export const useUserPreferences = create( setOpenLinksNewTab: (openLinksNewTab: boolean) => set({ openLinksNewTab: openLinksNewTab }), setCards: (selectedCards: SelectedCard[]) => set({ cards: selectedCards }), setTags: (selectedTags: Tag[]) => set({ userSelectedTags: selectedTags }), + setMaxVisibleCards: (maxVisibleCards: number) => set({ maxVisibleCards: maxVisibleCards }), initState: (newState: UserPreferencesState) => set(() => { return { ...newState } From 8cdd366bf6312d73961d54087bd632992429c9a1 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 15 Mar 2023 21:21:11 +0100 Subject: [PATCH 3/6] fix a minor padding issue on large screens --- src/assets/App.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/App.css b/src/assets/App.css index 902c5e53..a7bdaf94 100644 --- a/src/assets/App.css +++ b/src/assets/App.css @@ -1085,7 +1085,7 @@ Producthunt item /* XX-Large devices (larger desktops, 1400px and up)*/ @media only screen and (min-width: 1400px) { .block { - width: calc(96vw / min(4, var(--max-visible-cards))); + width: calc(95vw / min(4, var(--max-visible-cards))); } } @@ -1097,7 +1097,7 @@ Producthunt item } .block { width: calc( - (1800px - 12px * min(5, var(--max-visible-cards))) / min(5, var(--max-visible-cards)) + (1800px - 14px * min(5, var(--max-visible-cards))) / min(5, var(--max-visible-cards)) ); } } From 1e89a0700a7090bf77b328021ed196a43604b85c Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 15 Mar 2023 21:28:42 +0100 Subject: [PATCH 4/6] make the chipset match the settings color --- src/components/Elements/ChipsSet/chipset.css | 7 +++++++ src/features/settings/components/SettingsModal.tsx | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/Elements/ChipsSet/chipset.css b/src/components/Elements/ChipsSet/chipset.css index 9989c756..0dd9ab78 100644 --- a/src/components/Elements/ChipsSet/chipset.css +++ b/src/components/Elements/ChipsSet/chipset.css @@ -40,3 +40,10 @@ background-color: var(--chip-active-background); color: var(--chip-active-text); } + +.chipsSet.alternative-color .chip { + background-color: var(--card-action-button-background); +} +.chipsSet.alternative-color .chip.active { + background-color: var(--card-active-action-button-background); +} diff --git a/src/features/settings/components/SettingsModal.tsx b/src/features/settings/components/SettingsModal.tsx index 5c5ca891..2990e391 100644 --- a/src/features/settings/components/SettingsModal.tsx +++ b/src/features/settings/components/SettingsModal.tsx @@ -228,7 +228,7 @@ export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalPr

Max number of cards to display

Date: Wed, 15 Mar 2023 21:36:05 +0100 Subject: [PATCH 5/6] track max visible cards feature --- .../settings/components/SettingsModal.tsx | 11 +++++++--- src/lib/analytics.ts | 20 ++++++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/features/settings/components/SettingsModal.tsx b/src/features/settings/components/SettingsModal.tsx index 2990e391..2ab59724 100644 --- a/src/features/settings/components/SettingsModal.tsx +++ b/src/features/settings/components/SettingsModal.tsx @@ -13,11 +13,13 @@ import { identifyUserLanguages, identifyUserLinksInNewTab, identifyUserListingMode, + identifyUserMaxVisibleCards, identifyUserSearchEngine, identifyUserTheme, trackLanguageAdd, trackLanguageRemove, trackListingModeSelect, + trackMaxVisibleCardsChange, trackSearchEngineSelect, trackSourceAdd, trackSourceRemove, @@ -147,9 +149,12 @@ export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalPr identifyUserTheme(newTheme) } - const onCardsCountChange = (selectedChips: Option[]) => { + const onMaxVisibleCardsChange = (selectedChips: Option[]) => { if (selectedChips.length) { - setMaxVisibleCards(parseInt(selectedChips[0].value)) + const maxVisibleCards = parseInt(selectedChips[0].value) + setMaxVisibleCards(maxVisibleCards) + identifyUserMaxVisibleCards(maxVisibleCards) + trackMaxVisibleCardsChange(maxVisibleCards) } } @@ -250,7 +255,7 @@ export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalPr ]} defaultValues={[maxVisibleCards.toString()]} onChange={(_, selectedChips) => { - onCardsCountChange(selectedChips) + onMaxVisibleCardsChange(selectedChips) }} /> diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts index 5e7907dd..ed14183d 100644 --- a/src/lib/analytics.ts +++ b/src/lib/analytics.ts @@ -38,6 +38,7 @@ enum Verbs { FINISH = 'Finish', SKIP = 'Skip', DRAG = 'Drag', + Change = 'Change', } export enum Attributes { @@ -60,6 +61,7 @@ export enum Attributes { SOURCE_TAGS = 'Source Tags', CAMPAIGN_ID = 'Campaign Id', OCCUPATION = 'Occupation', + MAX_VISIBLE_CARDS = 'Max Visible Cards', } const _SEP_ = ' ' @@ -82,6 +84,7 @@ export const setupIdentification = () => { listingMode, openLinksNewTab, searchEngine, + maxVisibleCards } = useUserPreferences.getState() identifyUserProperty(Attributes.RESOLUTION, getScreenResolution()) @@ -91,6 +94,7 @@ export const setupIdentification = () => { identifyUserListingMode(listingMode) identifyUserSearchEngine(searchEngine) identifyUserLinksInNewTab(openLinksNewTab) + identifyUserMaxVisibleCards(maxVisibleCards) if (onboardingResult?.title) { identifyUserOccupation(onboardingResult.title) } @@ -291,6 +295,14 @@ export const trackPageDrag = () => { }) } +export const trackMaxVisibleCardsChange = (maxVisibleCards: number) => { + trackEvent({ + object: Objects.CARD, + verb: Verbs.Change, + attributes: {[Attributes.MAX_VISIBLE_CARDS]: maxVisibleCards} + }) +} + // Identification export const identifyUserLanguages = (languages: string[]) => { @@ -317,7 +329,9 @@ export const identifyUserLinksInNewTab = (enabled: boolean) => { export const identifyUserOccupation = (occupation: string) => { identifyUserProperty(Attributes.OCCUPATION, occupation) } - +export const identifyUserMaxVisibleCards = (maxVisibleCards: number) => { + identifyUserProperty(Attributes.MAX_VISIBLE_CARDS, maxVisibleCards) +} // Private functions type trackEventProps = { @@ -365,13 +379,13 @@ const trackEvent = ({ object, verb, attributes }: trackEventProps) => { } } -const identifyUserProperty = (attributes: Attributes, value: string | string[]) => { +const identifyUserProperty = (attributes: Attributes, value: string | number | string[]) => { try { let formatedValue if (Array.isArray(value)) { formatedValue = value.filter(Boolean).map((item) => item.toLowerCase()) } else { - formatedValue = value.toLowerCase() + formatedValue = typeof value === "string" ? value.toLowerCase() : value.toString() } if (isDevelopment()) { From 25e1ec4ca822bc7c7b013518ab0a4796aba84483 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 15 Mar 2023 21:53:08 +0100 Subject: [PATCH 6/6] fix active chip color on dark mode --- src/components/Elements/ChipsSet/chipset.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Elements/ChipsSet/chipset.css b/src/components/Elements/ChipsSet/chipset.css index 0dd9ab78..8b4b0cfd 100644 --- a/src/components/Elements/ChipsSet/chipset.css +++ b/src/components/Elements/ChipsSet/chipset.css @@ -46,4 +46,5 @@ } .chipsSet.alternative-color .chip.active { background-color: var(--card-active-action-button-background); + color: var(--card-active-action-button-color); }