diff --git a/bun.lockb b/bun.lockb index 337f675..faccfb9 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 9cce6a9..7284ff7 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,9 @@ "@suid/icons-material": "^0.7.0", "@suid/material": "^0.16.0", "blurhash": "^2.0.5", + "colorjs.io": "^0.5.2", "date-fns": "^3.6.0", + "fast-average-color": "^9.4.0", "hammerjs": "^2.0.8", "masto": "^6.8.0", "nanostores": "^0.9.5", diff --git a/src/timelines/CompactToot.tsx b/src/timelines/CompactToot.tsx index 7042ad4..eb8a7b7 100644 --- a/src/timelines/CompactToot.tsx +++ b/src/timelines/CompactToot.tsx @@ -18,7 +18,7 @@ const CompactToot: Component = (props) => { const toot = () => props.status; return (
{ + if (!props.src.width) return; + const width = root.getBoundingClientRect().width; + if (width > props.src.width) { + root.classList.add(tootStyle.compact); + } else { + root.classList.remove(tootStyle.compact); + } + }); + + const onImgLoad = (event: Event & { currentTarget: HTMLImageElement }) => { + // TODO: better extraction algorithm + // I'd like to use a pattern panel and match one in the panel from the extracted color + const fac = new FastAverageColor(); + const result = fac.getColor(event.currentTarget); + if (result.error) { + console.error(result.error); + fac.destroy(); + return; + } + root.style.setProperty("--tutu-color-surface", result.hex); + const focusSurface = result.isDark + ? new Color(result.hex).darken(0.2) + : new Color(result.hex).lighten(0.2); + root.style.setProperty("--tutu-color-surface-d", focusSurface.toString()); + const textColor = result.isDark ? "white" : "black"; + const secondaryTextColor = new Color(textColor); + secondaryTextColor.alpha = 0.75; + root.style.setProperty("--tutu-color-on-surface", textColor); + root.style.setProperty( + "--tutu-color-secondary-text-on-surface", + secondaryTextColor.toString(), + ); + fac.destroy(); + }; + + return ( + + + + + {props.src.title} + {props.src.description} + + ); +} + const RegularToot: Component = (props) => { let rootRef: HTMLElement; const [managed, managedActionGroup, rest] = splitProps( @@ -241,6 +312,9 @@ const RegularToot: Component = (props) => { emojis={toot().emojis} class={tootStyle.tootContent} /> + + + 0}> diff --git a/src/timelines/toot.module.css b/src/timelines/toot.module.css index 108cedc..bc82522 100644 --- a/src/timelines/toot.module.css +++ b/src/timelines/toot.module.css @@ -13,7 +13,7 @@ border-radius: 0; } - & > .toot { + &>.toot { box-shadow: none; } @@ -47,7 +47,7 @@ display: grid; grid-template-columns: 1fr auto; - > * { + >* { color: var(--tutu-color-secondary-text-on-surface); } @@ -55,7 +55,7 @@ grid-column: 1 /3; } - > time { + >time { text-align: end; } @@ -104,7 +104,64 @@ } } -.compact { +.previewCard { + composes: cardGutSkip from "../material/cards.module.css"; + display: block; + border: 1px solid #eeeeee; + background-color: var(--tutu-color-surface); + text-decoration: none; + border-radius: 4px; + overflow: hidden; + margin-top: 1em; + margin-bottom: 1.5em; + color: var(--tutu-color-secondary-text-on-surface); + transition: color 220ms var(--tutu-anim-curve-std), background-color 220ms var(--tutu-anim-curve-std); + padding-bottom: 8px; + + >img { + max-width: 100%; + } + + &:hover, + &:focus-visible { + background-color: var(--tutu-color-surface-d); + color: var(--tutu-color-on-surface); + + >h1 { + text-decoration: underline; + } + } + + >h1 { + color: var(--tutu-color-on-surface); + } + + >h1, + >p { + margin-left: 16px; + margin-right: 16px; + } + + &.compact { + display: grid; + grid-template-columns: minmax(10%, 30%) 1fr; + padding-left: 16px; + padding-right: 16px; + + >img:first-child { + grid-row: 1 / 3; + height: 100%; + object-fit: contain; + } + + >h1, + >p { + margin-right: 0; + } + } +} + +.toot.compact { display: grid; grid-template-columns: auto 1fr; gap: 8px; @@ -127,12 +184,12 @@ align-items: center; margin-bottom: 8px; - > .compactAuthorUsername { + >.compactAuthorUsername { color: var(--tutu-color-secondary-text-on-surface); flex-grow: 1; } - > time { + >time { color: var(--tutu-color-secondary-text-on-surface); } } @@ -177,11 +234,11 @@ flex-flow: row wrap; justify-content: space-evenly; - > button { + >button { color: var(--tutu-color-on-surface); padding: 10px 8px; - > svg { + >svg { font-size: 20px; } } @@ -207,4 +264,4 @@ 100% { opacity: 1; } -} +} \ No newline at end of file