Consolidate some list styling

This commit is contained in:
Jackson Harper 2023-03-08 16:48:36 +08:00
parent fc81c59e32
commit 61c44c807b
6 changed files with 207 additions and 342 deletions

View file

@ -1,3 +1,8 @@
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
dayjs.extend(relativeTime)
export const MetaStyle = {
width: '100%',
color: '$thTextSubtle3',
@ -64,3 +69,39 @@ export const AuthorInfoStyle = {
fontWeight: '400',
fontFamily: '$display',
}
export const timeAgo = (date: string | undefined): string => {
if (!date) {
return ''
}
return dayjs(date).fromNow()
}
const shouldHideUrl = (url: string): boolean => {
try {
const origin = new URL(url).origin
const hideHosts = ['https://storage.googleapis.com', 'https://omnivore.app']
if (hideHosts.indexOf(origin) != -1) {
return true
}
} catch {
console.log('invalid url item', url)
}
return false
}
export const siteName = (
originalArticleUrl: string,
itemUrl: string
): string => {
if (shouldHideUrl(originalArticleUrl)) {
return ''
}
try {
return new URL(originalArticleUrl).hostname.replace(/^www\./, '')
} catch {}
try {
return new URL(itemUrl).hostname.replace(/^www\./, '')
} catch {}
return ''
}

View file

@ -13,6 +13,8 @@ import {
DescriptionStyle,
MenuStyle,
MetaStyle,
siteName,
timeAgo,
TitleStyle,
} from './LibraryCardStyles'
@ -48,39 +50,6 @@ export function ProgressBar(props: ProgressBarProps): JSX.Element {
)
}
const timeAgo = (date: string | undefined): string => {
if (!date) {
return ''
}
return dayjs(date).fromNow()
}
const shouldHideUrl = (url: string): boolean => {
try {
const origin = new URL(url).origin
const hideHosts = ['https://storage.googleapis.com', 'https://omnivore.app']
if (hideHosts.indexOf(origin) != -1) {
return true
}
} catch {
console.log('invalid url item', url)
}
return false
}
const siteName = (originalArticleUrl: string, itemUrl: string): string => {
if (shouldHideUrl(originalArticleUrl)) {
return ''
}
try {
return new URL(originalArticleUrl).hostname.replace(/^www\./, '')
} catch {}
try {
return new URL(itemUrl).hostname.replace(/^www\./, '')
} catch {}
return ''
}
// Component
export function LibraryGridCard(props: LinkedItemCardProps): JSX.Element {
const [isHovered, setIsHovered] = useState(false)

View file

@ -6,17 +6,8 @@ import {
Blockquote,
} from '../../elements/LayoutPrimitives'
import { LabelChip } from '../../elements/LabelChip'
import type { LinkedItemCardProps } from './CardTypes'
import { CoverImage } from '../../elements/CoverImage'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { Fragment, useMemo, useState } from 'react'
import {
CaretCircleDown,
CaretDown,
CaretUp,
DotsThreeVertical,
} from 'phosphor-react'
import { CaretDown, CaretUp, DotsThreeVertical } from 'phosphor-react'
import Link from 'next/link'
import { CardMenu } from '../CardMenu'
import {
@ -24,6 +15,7 @@ import {
DescriptionStyle,
MenuStyle,
MetaStyle,
timeAgo,
TitleStyle,
} from './LibraryCardStyles'
import { Separator } from '../../elements/Separator'
@ -41,15 +33,6 @@ import { Label } from '../../../lib/networking/fragments/labelFragment'
import { Button } from '../../elements/Button'
import { theme } from '../../tokens/stitches.config'
dayjs.extend(relativeTime)
const timeAgo = (date: string | undefined): string => {
if (!date) {
return ''
}
return dayjs(date).fromNow()
}
export const GridSeparator = styled(Box, {
height: '1px',
marginTop: '15px',
@ -211,6 +194,7 @@ const StyledQuote = styled(Blockquote, {
margin: '0px',
fontSize: '16px',
fontFamily: '$inter',
fontWeight: '500',
lineHeight: '1.50',
color: '$thHighContrast',
paddingLeft: '15px',
@ -281,11 +265,11 @@ function HighlightItemCard(props: HighlightItemCardProps): JSX.Element {
<StyledText
css={{
borderRadius: '6px',
bg: '$thBackground4',
bg: '#EBEBEB',
p: '10px',
width: '100%',
marginTop: '5px',
color: '$grayText',
color: '#3D3D3D',
}}
onClick={() => setIsEditing(true)}
>

View file

@ -1,55 +1,19 @@
import { Box, VStack, HStack, SpanBox } from '../../elements/LayoutPrimitives'
import { LabelChip } from '../../elements/LabelChip'
import type { LinkedItemCardProps } from './CardTypes'
import { CoverImage } from '../../elements/CoverImage'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { useState } from 'react'
import { DotsThree, DotsThreeVertical } from 'phosphor-react'
import { DotsThree } from 'phosphor-react'
import Link from 'next/link'
import { CardMenu } from '../CardMenu'
import {
AuthorInfoStyle,
MenuStyle,
MetaStyle,
siteName,
timeAgo,
TitleStyle,
} from './LibraryCardStyles'
dayjs.extend(relativeTime)
const timeAgo = (date: string | undefined): string => {
if (!date) {
return ''
}
return dayjs(date).fromNow()
}
const shouldHideUrl = (url: string): boolean => {
try {
const origin = new URL(url).origin
const hideHosts = ['https://storage.googleapis.com', 'https://omnivore.app']
if (hideHosts.indexOf(origin) != -1) {
return true
}
} catch {
console.log('invalid url item', url)
}
return false
}
const siteName = (originalArticleUrl: string, itemUrl: string): string => {
if (shouldHideUrl(originalArticleUrl)) {
return ''
}
try {
return new URL(originalArticleUrl).hostname.replace(/^www\./, '')
} catch {}
try {
return new URL(itemUrl).hostname.replace(/^www\./, '')
} catch {}
return ''
}
// Component
export function LibraryListCard(props: LinkedItemCardProps): JSX.Element {
const [isHovered, setIsHovered] = useState(false)

View file

@ -1,31 +1,16 @@
import dayjs from 'dayjs'
import { useRouter } from 'next/router'
import { DotsThreeVertical, HighlighterCircle } from 'phosphor-react'
import { Fragment, useEffect, useMemo, useState } from 'react'
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { useEffect, useState } from 'react'
import { LibraryItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
import { SideBarIcon } from '../../elements/images/SideBarIcon'
import { LabelChip } from '../../elements/LabelChip'
import {
Blockquote,
Box,
HStack,
SpanBox,
VStack,
} from '../../elements/LayoutPrimitives'
import {
ModalContent,
ModalOverlay,
ModalRoot,
ModalTitleBar,
} from '../../elements/ModalPrimitives'
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
import { StyledText } from '../../elements/StyledText'
import { MetaStyle } from '../../patterns/LibraryCards/LibraryCardStyles'
import {
MetaStyle,
timeAgo,
} from '../../patterns/LibraryCards/LibraryCardStyles'
import { LibraryHighlightGridCard } from '../../patterns/LibraryCards/LibraryHighlightGridCard'
import { styled, theme } from '../../tokens/stitches.config'
import { HighlightItem } from './HighlightItem'
type HighlightItemsLayoutProps = {
items: LibraryItem[]
@ -83,8 +68,6 @@ export function HighlightItemsLayout(
alignment="center"
distribution="start"
>
{/* <SideBarIcon strokeColor={theme.colors.thTextContrast.toString()} />
<DotsThreeVertical color={theme.colors.thTextContrast.toString()} /> */}
<Box
css={{
display: 'flex',
@ -142,7 +125,7 @@ export function HighlightItemsLayout(
},
}}
>
<HighlightItemsCard item={currentItem} viewer={props.viewer} />
<HighlightList item={currentItem} viewer={props.viewer} />
</SpanBox>
</>
)}
@ -157,13 +140,6 @@ type HighlightTitleCardProps = {
selected: boolean
}
const timeAgo = (date: string | undefined): string => {
if (!date) {
return ''
}
return dayjs(date).fromNow()
}
function LibraryItemCard(props: HighlightTitleCardProps): JSX.Element {
return (
<>
@ -254,12 +230,12 @@ function HighlightTitleCard(props: HighlightTitleCardProps): JSX.Element {
)
}
type HighlightItemsCardProps = {
type HighlightListProps = {
item: LibraryItem
viewer: UserBasicData | undefined
}
function HighlightItemsCard(props: HighlightItemsCardProps): JSX.Element {
function HighlightList(props: HighlightListProps): JSX.Element {
return (
<HStack
css={{
@ -302,7 +278,7 @@ function HighlightItemsCard(props: HighlightItemsCardProps): JSX.Element {
</HStack>
<VStack css={{ height: '100%', width: '100%' }} distribution="start">
{(props.item.node.highlights ?? []).map((highlight) => (
<HighlightItemCard
<HighlightItem
key={highlight.id}
viewer={props.viewer}
item={props.item}
@ -315,112 +291,114 @@ function HighlightItemsCard(props: HighlightItemsCardProps): JSX.Element {
)
}
const StyledQuote = styled(Blockquote, {
margin: '0px 0px 0px 0px',
fontSize: '16px',
lineHeight: '1.50',
color: '$thHighContrast',
paddingLeft: '15px',
borderLeft: '2px solid $omnivoreCtaYellow',
})
// const StyledQuote = styled(Blockquote, {
// margin: '0px',
// fontSize: '16px',
// fontFamily: '$inter',
// fontWeight: '500',
// lineHeight: '1.50',
// color: '$thHighContrast',
// paddingLeft: '15px',
// borderLeft: '2px solid $omnivoreCtaYellow',
// })
type HighlightItemCardProps = {
highlight: Highlight
viewer: UserBasicData | undefined
item: LibraryItem
}
// type HighlightItemCardProps = {
// highlight: Highlight
// viewer: UserBasicData | undefined
// item: LibraryItem
// }
function HighlightItemCard(props: HighlightItemCardProps): JSX.Element {
const router = useRouter()
const [hover, setHover] = useState(false)
const [isEditing, setIsEditing] = useState(false)
// function HighlightItemCard(props: HighlightItemCardProps): JSX.Element {
// const router = useRouter()
// const [hover, setHover] = useState(false)
// const [isEditing, setIsEditing] = useState(false)
const lines = useMemo(
() => props.highlight.quote.split('\n'),
[props.highlight.quote]
)
// const lines = useMemo(
// () => props.highlight.quote.split('\n'),
// [props.highlight.quote]
// )
return (
<HStack
css={{ width: '100%', py: '20px', cursor: 'pointer' }}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
<VStack
css={{
gap: '10px',
height: '100%',
width: '100%',
// return (
// <HStack
// css={{ width: '100%', py: '20px', cursor: 'pointer' }}
// onMouseEnter={() => setHover(true)}
// onMouseLeave={() => setHover(false)}
// >
// <VStack
// css={{
// gap: '10px',
// height: '100%',
// width: '100%',
wordBreak: 'break-word',
overflow: 'clip',
}}
alignment="start"
distribution="start"
onClick={(event) => {
if (router && props.viewer) {
const dest = `/${props.viewer}/${props.item.node.slug}#${props.highlight.id}`
router.push(dest)
}
event.preventDefault()
}}
>
<StyledQuote>
<SpanBox css={{ p: '1px', borderRadius: '2px' }}>
{lines.map((line: string, index: number) => (
<Fragment key={index}>
{line}
{index !== lines.length - 1 && (
<>
<br />
<br />
</>
)}
</Fragment>
))}
</SpanBox>
<Box css={{ display: 'block', pt: '16px' }}>
{props.highlight.labels?.map((label: Label, index: number) => (
<LabelChip
key={index}
text={label.name || ''}
color={label.color}
/>
))}
</Box>
</StyledQuote>
// wordBreak: 'break-word',
// overflow: 'clip',
// }}
// alignment="start"
// distribution="start"
// onClick={(event) => {
// if (router && props.viewer) {
// const dest = `/${props.viewer}/${props.item.node.slug}#${props.highlight.id}`
// router.push(dest)
// }
// event.preventDefault()
// }}
// >
// <StyledQuote>
// <SpanBox css={{ p: '1px', borderRadius: '2px' }}>
// {lines.map((line: string, index: number) => (
// <Fragment key={index}>
// {line}
// {index !== lines.length - 1 && (
// <>
// <br />
// <br />
// </>
// )}
// </Fragment>
// ))}
// </SpanBox>
// <Box css={{ display: 'block', pt: '16px' }}>
// {props.highlight.labels?.map((label: Label, index: number) => (
// <LabelChip
// key={index}
// text={label.name || ''}
// color={label.color}
// />
// ))}
// </Box>
// </StyledQuote>
<StyledText
css={{
borderRadius: '6px',
bg: '$thBackground4',
p: '10px',
width: '100%',
marginTop: '5px',
color: '$thTextSubtle',
}}
onClick={() => setIsEditing(true)}
>
{props.highlight.annotation
? props.highlight.annotation
: 'Add your notes...'}
</StyledText>
</VStack>
<SpanBox
css={{
marginLeft: 'auto',
width: '20px',
visibility: hover ? 'unset' : 'hidden',
'@media (hover: none)': {
visibility: 'unset',
},
}}
>
<HighlightsMenu />
</SpanBox>
</HStack>
)
}
// <StyledText
// css={{
// borderRadius: '6px',
// bg: '#EBEBEB',
// p: '10px',
// width: '100%',
// marginTop: '5px',
// color: '#3D3D3D',
// }}
// onClick={() => setIsEditing(true)}
// >
// {props.highlight.annotation
// ? props.highlight.annotation
// : 'Add your notes...'}
// </StyledText>
// </VStack>
// <SpanBox
// css={{
// marginLeft: 'auto',
// width: '20px',
// visibility: hover ? 'unset' : 'hidden',
// '@media (hover: none)': {
// visibility: 'unset',
// },
// }}
// >
// <HighlightsMenu />
// </SpanBox>
// </HStack>
// )
// }
type HighlightCountChipProps = {
count: number
@ -456,45 +434,45 @@ function HighlightCountChip(props: HighlightCountChipProps): JSX.Element {
)
}
function HighlightsMenu(): JSX.Element {
return (
<Dropdown
triggerElement={
<Box
css={{
display: 'flex',
height: '20px',
width: '20px',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '1000px',
'&:hover': {
bg: '#898989',
},
}}
>
<DotsThreeVertical size={20} color="#EBEBEB" weight="bold" />
</Box>
}
>
<DropdownOption
onSelect={() => {
console.log('copy')
}}
title="Copy"
/>
<DropdownOption
onSelect={() => {
console.log('labels')
}}
title="Labels"
/>
<DropdownOption
onSelect={() => {
console.log('delete')
}}
title="Delete"
/>
</Dropdown>
)
}
// function HighlightsMenu(): JSX.Element {
// return (
// <Dropdown
// triggerElement={
// <Box
// css={{
// display: 'flex',
// height: '20px',
// width: '20px',
// alignItems: 'center',
// justifyContent: 'center',
// borderRadius: '1000px',
// '&:hover': {
// bg: '#898989',
// },
// }}
// >
// <DotsThreeVertical size={20} color="#EBEBEB" weight="bold" />
// </Box>
// }
// >
// <DropdownOption
// onSelect={() => {
// console.log('copy')
// }}
// title="Copy"
// />
// <DropdownOption
// onSelect={() => {
// console.log('labels')
// }}
// title="Labels"
// />
// <DropdownOption
// onSelect={() => {
// console.log('delete')
// }}
// title="Delete"
// />
// </Dropdown>
// )
// }

View file

@ -1,71 +0,0 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'
import { HighlightItemCard, HighlightItemCardProps } from '../components/patterns/LibraryCards/HighlightItemCard'
import { updateThemeLocally } from '../lib/themeUpdater'
import { ThemeId } from '../components/tokens/stitches.config'
import { PageType, State } from '../lib/networking/fragments/articleFragment'
export default {
title: 'Components/HighlightItemCard',
component: HighlightItemCard,
argTypes: {
item: {
description: 'The highlight.',
},
handleAction: {
description: 'Action that fires on click.'
}
}
} as ComponentMeta<typeof HighlightItemCard>
const highlight: HighlightItemCardProps = {
handleAction: () => console.log('Handling Action'),
item:{
id: "nnnnn",
shortId: "shortId",
quote: "children not only participate in herding work, but are also encouraged to act independently in most other areas of life. They have a say in deciding when to eat, when to sleep, and what to wear, even at temperatures of -30C (-22F).",
annotation: "Okay… this is wild! I love this independence. Wondering how I can reponsibly instill this type of indepence in my own kids…",
createdAt: '',
description: '',
isArchived: false,
originalArticleUrl: 'https://example.com',
ownedByViewer: true,
pageId: '1',
readingProgressAnchorIndex: 12,
readingProgressPercent: 50,
slug: 'slug',
title: "This is a title",
uploadFileId: '1',
url: 'https://example.com',
author: 'Author',
image: 'https://logos-world.net/wp-content/uploads/2021/11/Unity-New-Logo.png',
state: State.SUCCEEDED,
pageType: PageType.HIGHLIGHTS,
},
}
const Template = (props: HighlightItemCardProps) => <HighlightItemCard {...props} />
export const LightHighlightItemCard: ComponentStory<
typeof HighlightItemCard
> = (args: any) => {
updateThemeLocally(ThemeId.Light)
return (
<Template {...args}/>
)
}
export const DarkHighlightItemCard: ComponentStory<
typeof HighlightItemCard
> = (args: any) => {
updateThemeLocally(ThemeId.Dark)
return (
<Template {...args}/>
)
}
LightHighlightItemCard.args = {
...highlight
}
DarkHighlightItemCard.args = {
...highlight
}