From 4acfb2a1cfdc76db31b175fbed1a3f3d3054ced1 Mon Sep 17 00:00:00 2001
From: Lim Chee Aun <cheeaun@gmail.com>
Date: Tue, 19 Sep 2023 21:53:59 +0800
Subject: [PATCH] Use useTruncated for notification items

---
 src/components/notification.jsx | 14 ++++++++++----
 src/pages/notifications.css     | 30 ++++++++++++++++++++++++++++--
 2 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/src/components/notification.jsx b/src/components/notification.jsx
index 958f18cb..079317d2 100644
--- a/src/components/notification.jsx
+++ b/src/components/notification.jsx
@@ -1,6 +1,7 @@
 import shortenNumber from '../utils/shorten-number';
 import states from '../utils/states';
 import store from '../utils/store';
+import useTruncated from '../utils/useTruncated';
 
 import Avatar from './avatar';
 import FollowRequestButtons from './follow-request-buttons';
@@ -266,20 +267,20 @@ function Notification({ notification, instance, reload, isStatic }) {
           <ul class="notification-group-statuses">
             {_statuses.map((status) => (
               <li key={status.id}>
-                <Link
+                <TruncatedLink
                   class={`status-link status-type-${type}`}
                   to={
                     instance ? `/${instance}/s/${status.id}` : `/s/${status.id}`
                   }
                 >
                   <Status status={status} size="s" />
-                </Link>
+                </TruncatedLink>
               </li>
             ))}
           </ul>
         )}
         {status && (!_statuses?.length || _statuses?.length <= 1) && (
-          <Link
+          <TruncatedLink
             class={`status-link status-type-${type}`}
             to={
               instance
@@ -306,11 +307,16 @@ function Notification({ notification, instance, reload, isStatic }) {
             ) : (
               <Status statusID={actualStatusID} size="s" />
             )}
-          </Link>
+          </TruncatedLink>
         )}
       </div>
     </div>
   );
 }
 
+function TruncatedLink(props) {
+  const ref = useTruncated();
+  return <Link {...props} data-read-more="Read more →" ref={ref} />;
+}
+
 export default Notification;
diff --git a/src/pages/notifications.css b/src/pages/notifications.css
index 9a91833c..468051cf 100644
--- a/src/pages/notifications.css
+++ b/src/pages/notifications.css
@@ -98,8 +98,8 @@
 }
 .notification .status-link:not(.status-type-mention) > .status {
   font-size: calc(var(--text-size) * 0.9);
-  max-height: 160px;
-  overflow: hidden;
+}
+.notification .status-link.truncated:not(.status-type-mention) > .status {
   /* fade out mask gradient bottom */
   mask-image: linear-gradient(
     rgba(0, 0, 0, 1) 130px,
@@ -107,6 +107,32 @@
     transparent 159px
   );
 }
+.notification .status-link.truncated {
+  position: relative;
+}
+.notification .status-link.truncated:after {
+  content: attr(data-read-more);
+  line-height: 1;
+  display: inline-block;
+  position: absolute;
+  --inset-offset: 16px;
+  inset-block-end: var(--inset-offset);
+  inset-inline-end: var(--inset-offset);
+  color: var(--link-color);
+  background-color: var(--bg-faded-blur-color);
+  backdrop-filter: blur(8px);
+  border: 1px solid var(--outline-color);
+  padding: 0.5em 0.75em;
+  border-radius: 10em;
+  font-size: 90%;
+  white-space: nowrap;
+  transition: all 0.2s ease-out;
+}
+.notification .status-link:is(:hover, :focus).truncated:after {
+  border-color: var(--link-color);
+  background-color: var(--bg-color);
+  transform: translate(2px, 0);
+}
 .notification .status-link.status-type-mention {
   max-height: 320px;
   filter: none;