diff --git a/src/state/models/ui/shell.ts b/src/state/models/ui/shell.ts
index dea220c5..4a55c23a 100644
--- a/src/state/models/ui/shell.ts
+++ b/src/state/models/ui/shell.ts
@@ -48,11 +48,6 @@ export interface AltTextImageModal {
   image: ImageModel
 }
 
-export interface AltTextImageReadModal {
-  name: 'alt-text-image-read'
-  altText: string
-}
-
 export interface DeleteAccountModal {
   name: 'delete-account'
 }
@@ -106,7 +101,6 @@ export type Modal =
 
   // Posts
   | AltTextImageModal
-  | AltTextImageReadModal
   | CropImageModal
   | ServerInputModal
   | RepostModal
@@ -127,9 +121,14 @@ export class ProfileImageLightbox implements LightboxModel {
   }
 }
 
+interface ImagesLightboxItem {
+  uri: string
+  alt?: string
+}
+
 export class ImagesLightbox implements LightboxModel {
   name = 'images'
-  constructor(public uris: string[], public index: number) {
+  constructor(public images: ImagesLightboxItem[], public index: number) {
     makeAutoObservable(this)
   }
   setIndex(index: number) {
@@ -173,7 +172,7 @@ export class ShellUiModel {
   isModalActive = false
   activeModals: Modal[] = []
   isLightboxActive = false
-  activeLightbox: ProfileImageLightbox | ImagesLightbox | undefined
+  activeLightbox: ProfileImageLightbox | ImagesLightbox | null = null
   isComposerActive = false
   composerOpts: ComposerOpts | undefined
 
@@ -262,7 +261,7 @@ export class ShellUiModel {
 
   closeLightbox() {
     this.isLightboxActive = false
-    this.activeLightbox = undefined
+    this.activeLightbox = null
   }
 
   openComposer(opts: ComposerOpts) {
diff --git a/src/view/com/lightbox/Lightbox.tsx b/src/view/com/lightbox/Lightbox.tsx
index 06b48143..c4bc88cf 100644
--- a/src/view/com/lightbox/Lightbox.tsx
+++ b/src/view/com/lightbox/Lightbox.tsx
@@ -1,31 +1,75 @@
 import React from 'react'
+import {Pressable, StyleSheet, View} from 'react-native'
 import {observer} from 'mobx-react-lite'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import ImageView from './ImageViewing'
 import {useStores} from 'state/index'
 import * as models from 'state/models/ui/shell'
 import {saveImageModal} from 'lib/media/manip'
-import {ImageSource} from './ImageViewing/@types'
+import {Text} from '../util/text/Text'
+import {s, colors} from 'lib/styles'
+import {Button} from '../util/forms/Button'
+import {isIOS} from 'platform/detection'
 
 export const Lightbox = observer(function Lightbox() {
   const store = useStores()
-  if (!store.shell.isLightboxActive) {
-    return null
-  }
+  const [isAltExpanded, setAltExpanded] = React.useState(false)
 
-  const onClose = () => {
+  const onClose = React.useCallback(() => {
     store.shell.closeLightbox()
-  }
-  const onLongPress = (image: ImageSource) => {
-    if (
-      typeof image === 'object' &&
-      'uri' in image &&
-      typeof image.uri === 'string'
-    ) {
-      saveImageModal({uri: image.uri})
-    }
-  }
+  }, [store])
 
-  if (store.shell.activeLightbox?.name === 'profile-image') {
+  const LightboxFooter = React.useCallback(
+    ({imageIndex}: {imageIndex: number}) => {
+      const lightbox = store.shell.activeLightbox
+      if (!lightbox) {
+        return null
+      }
+
+      let altText = ''
+      let uri
+      if (lightbox.name === 'images') {
+        const opts = store.shell.activeLightbox as models.ImagesLightbox
+        uri = opts.images[imageIndex].uri
+        altText = opts.images[imageIndex].alt
+      } else if (store.shell.activeLightbox.name === 'profile-image') {
+        const opts = store.shell.activeLightbox as models.ProfileImageLightbox
+        uri = opts.profileView.avatar
+      }
+
+      return (
+        <View style={[styles.footer]}>
+          {altText ? (
+            <Pressable
+              onPress={() => setAltExpanded(!isAltExpanded)}
+              accessibilityRole="button">
+              <Text
+                style={[s.gray3, styles.footerText]}
+                numberOfLines={isAltExpanded ? undefined : 3}>
+                {altText}
+              </Text>
+            </Pressable>
+          ) : null}
+          <View style={styles.footerBtns}>
+            <Button
+              type="primary-outline"
+              style={styles.footerBtn}
+              onPress={() => saveImageModal({uri})}>
+              <FontAwesomeIcon icon="arrow-up-from-bracket" style={s.white} />
+              <Text type="xl" style={s.white}>
+                Share
+              </Text>
+            </Button>
+          </View>
+        </View>
+      )
+    },
+    [store.shell.activeLightbox, isAltExpanded, setAltExpanded],
+  )
+
+  if (!store.shell.activeLightbox) {
+    return null
+  } else if (store.shell.activeLightbox.name === 'profile-image') {
     const opts = store.shell.activeLightbox as models.ProfileImageLightbox
     return (
       <ImageView
@@ -33,20 +77,44 @@ export const Lightbox = observer(function Lightbox() {
         imageIndex={0}
         visible
         onRequestClose={onClose}
+        FooterComponent={LightboxFooter}
       />
     )
-  } else if (store.shell.activeLightbox?.name === 'images') {
+  } else if (store.shell.activeLightbox.name === 'images') {
     const opts = store.shell.activeLightbox as models.ImagesLightbox
     return (
       <ImageView
-        images={opts.uris.map(uri => ({uri}))}
+        images={opts.images.map(({uri}) => ({uri}))}
         imageIndex={opts.index}
         visible
         onRequestClose={onClose}
-        onLongPress={onLongPress}
+        FooterComponent={LightboxFooter}
       />
     )
   } else {
     return null
   }
 })
+
+const styles = StyleSheet.create({
+  footer: {
+    paddingTop: 16,
+    paddingBottom: isIOS ? 40 : 24,
+    paddingHorizontal: 24,
+    backgroundColor: '#000d',
+  },
+  footerText: {
+    paddingBottom: isIOS ? 20 : 16,
+  },
+  footerBtns: {
+    flexDirection: 'row',
+    justifyContent: 'center',
+  },
+  footerBtn: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    gap: 8,
+    backgroundColor: 'transparent',
+    borderColor: colors.white,
+  },
+})
diff --git a/src/view/com/lightbox/Lightbox.web.tsx b/src/view/com/lightbox/Lightbox.web.tsx
index 3388b54b..eff9af2d 100644
--- a/src/view/com/lightbox/Lightbox.web.tsx
+++ b/src/view/com/lightbox/Lightbox.web.tsx
@@ -10,11 +10,13 @@ import {observer} from 'mobx-react-lite'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {useStores} from 'state/index'
 import * as models from 'state/models/ui/shell'
-import {colors} from 'lib/styles'
+import {colors, s} from 'lib/styles'
 import ImageDefaultHeader from './ImageViewing/components/ImageDefaultHeader'
+import {Text} from '../util/text/Text'
 
 interface Img {
   uri: string
+  alt?: string
 }
 
 export const Lightbox = observer(function Lightbox() {
@@ -37,7 +39,7 @@ export const Lightbox = observer(function Lightbox() {
     }
   } else if (activeLightbox instanceof models.ImagesLightbox) {
     const opts = activeLightbox
-    imgs = opts.uris.map(uri => ({uri}))
+    imgs = opts.images
   }
 
   if (!imgs) {
@@ -131,6 +133,11 @@ function LightboxInner({
           )}
         </View>
       </TouchableWithoutFeedback>
+      {imgs[index].alt ? (
+        <View style={styles.footer}>
+          <Text style={s.white}>{imgs[index].alt}</Text>
+        </View>
+      ) : null}
       <View style={styles.closeBtn}>
         <ImageDefaultHeader onRequestClose={onClose} />
       </View>
@@ -183,4 +190,9 @@ const styles = StyleSheet.create({
     right: 30,
     top: '50%',
   },
+  footer: {
+    paddingHorizontal: 32,
+    paddingVertical: 24,
+    backgroundColor: colors.black,
+  },
 })
diff --git a/src/view/com/modals/AltImageRead.tsx b/src/view/com/modals/AltImageRead.tsx
deleted file mode 100644
index 98547728..00000000
--- a/src/view/com/modals/AltImageRead.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import React, {useCallback} from 'react'
-import {StyleSheet, View} from 'react-native'
-import {usePalette} from 'lib/hooks/usePalette'
-import {gradients, s} from 'lib/styles'
-import {Text} from '../util/text/Text'
-import {TouchableOpacity} from 'react-native-gesture-handler'
-import LinearGradient from 'react-native-linear-gradient'
-import {useStores} from 'state/index'
-import {isDesktopWeb} from 'platform/detection'
-
-export const snapPoints = ['70%']
-
-interface Props {
-  altText: string
-}
-
-export function Component({altText}: Props) {
-  const pal = usePalette('default')
-  const store = useStores()
-
-  const onPress = useCallback(() => {
-    store.shell.closeModal()
-  }, [store])
-
-  return (
-    <View
-      testID="altTextImageModal"
-      style={[pal.view, styles.container, s.flex1]}>
-      <Text style={[styles.title, pal.text]}>Image description</Text>
-      <View style={[styles.text, pal.viewLight]}>
-        <Text style={pal.text}>{altText}</Text>
-      </View>
-      <TouchableOpacity
-        testID="altTextImageSaveBtn"
-        onPress={onPress}
-        accessibilityRole="button"
-        accessibilityLabel="Done"
-        accessibilityHint="Closes alt text modal">
-        <LinearGradient
-          colors={[gradients.blueLight.start, gradients.blueLight.end]}
-          start={{x: 0, y: 0}}
-          end={{x: 1, y: 1}}
-          style={[styles.button]}>
-          <Text type="button-lg" style={[s.white, s.bold]}>
-            Done
-          </Text>
-        </LinearGradient>
-      </TouchableOpacity>
-    </View>
-  )
-}
-
-const styles = StyleSheet.create({
-  container: {
-    gap: 18,
-    paddingVertical: isDesktopWeb ? 0 : 18,
-    paddingHorizontal: isDesktopWeb ? 0 : 12,
-    height: '100%',
-    width: '100%',
-  },
-  title: {
-    textAlign: 'center',
-    fontWeight: 'bold',
-    fontSize: 24,
-  },
-  text: {
-    borderRadius: 5,
-    marginVertical: 18,
-    paddingHorizontal: 18,
-    paddingVertical: 16,
-  },
-  button: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    justifyContent: 'center',
-    width: '100%',
-    borderRadius: 32,
-    padding: 10,
-  },
-})
diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx
index b5d71a11..18b7ae4c 100644
--- a/src/view/com/modals/Modal.tsx
+++ b/src/view/com/modals/Modal.tsx
@@ -13,7 +13,6 @@ import * as ServerInputModal from './ServerInput'
 import * as ReportPostModal from './ReportPost'
 import * as RepostModal from './Repost'
 import * as AltImageModal from './AltImage'
-import * as AltImageReadModal from './AltImageRead'
 import * as ReportAccountModal from './ReportAccount'
 import * as DeleteAccountModal from './DeleteAccount'
 import * as ChangeHandleModal from './ChangeHandle'
@@ -76,9 +75,6 @@ export const ModalsContainer = observer(function ModalsContainer() {
   } else if (activeModal?.name === 'alt-text-image') {
     snapPoints = AltImageModal.snapPoints
     element = <AltImageModal.Component {...activeModal} />
-  } else if (activeModal?.name === 'alt-text-image-read') {
-    snapPoints = AltImageReadModal.snapPoints
-    element = <AltImageReadModal.Component {...activeModal} />
   } else if (activeModal?.name === 'change-handle') {
     snapPoints = ChangeHandleModal.snapPoints
     element = <ChangeHandleModal.Component {...activeModal} />
diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx
index 50487e3e..9dcc8fa7 100644
--- a/src/view/com/modals/Modal.web.tsx
+++ b/src/view/com/modals/Modal.web.tsx
@@ -15,7 +15,6 @@ import * as DeleteAccountModal from './DeleteAccount'
 import * as RepostModal from './Repost'
 import * as CropImageModal from './crop-image/CropImage.web'
 import * as AltTextImageModal from './AltImage'
-import * as AltTextImageReadModal from './AltImageRead'
 import * as ChangeHandleModal from './ChangeHandle'
 import * as WaitlistModal from './Waitlist'
 import * as InviteCodesModal from './InviteCodes'
@@ -89,8 +88,6 @@ function Modal({modal}: {modal: ModalIface}) {
     element = <ContentLanguagesSettingsModal.Component />
   } else if (modal.name === 'alt-text-image') {
     element = <AltTextImageModal.Component {...modal} />
-  } else if (modal.name === 'alt-text-image-read') {
-    element = <AltTextImageReadModal.Component {...modal} />
   } else {
     return null
   }
diff --git a/src/view/com/util/images/Gallery.tsx b/src/view/com/util/images/Gallery.tsx
index 5b6c3384..1a29b453 100644
--- a/src/view/com/util/images/Gallery.tsx
+++ b/src/view/com/util/images/Gallery.tsx
@@ -1,8 +1,7 @@
 import {AppBskyEmbedImages} from '@atproto/api'
-import React, {ComponentProps, FC, useCallback} from 'react'
-import {Pressable, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
+import React, {ComponentProps, FC} from 'react'
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
 import {Image} from 'expo-image'
-import {useStores} from 'state/index'
 
 type EventFunction = (index: number) => void
 
@@ -26,22 +25,14 @@ export const GalleryItem: FC<GalleryItemProps> = ({
   onLongPress,
 }) => {
   const image = images[index]
-  const store = useStores()
-
-  const onPressAltText = useCallback(() => {
-    store.shell.openModal({
-      name: 'alt-text-image-read',
-      altText: image.alt,
-    })
-  }, [image.alt, store.shell])
 
   return (
     <View>
       <TouchableOpacity
         delayPressIn={DELAY_PRESS_IN}
-        onPress={() => onPress?.(index)}
-        onPressIn={() => onPressIn?.(index)}
-        onLongPress={() => onLongPress?.(index)}
+        onPress={onPress ? () => onPress(index) : undefined}
+        onPressIn={onPressIn ? () => onPressIn(index) : undefined}
+        onLongPress={onLongPress ? () => onLongPress(index) : undefined}
         accessibilityRole="button"
         accessibilityLabel="View image"
         accessibilityHint="">
@@ -54,15 +45,7 @@ export const GalleryItem: FC<GalleryItemProps> = ({
           accessibilityIgnoresInvertColors
         />
       </TouchableOpacity>
-      {image.alt === '' ? null : (
-        <Pressable
-          onPress={onPressAltText}
-          accessibilityRole="button"
-          accessibilityLabel="View alt text"
-          accessibilityHint="Opens modal with alt text">
-          <Text style={styles.alt}>ALT</Text>
-        </Pressable>
-      )}
+      {image.alt === '' ? null : <Text style={styles.alt}>ALT</Text>}
     </View>
   )
 }
@@ -78,8 +61,8 @@ const styles = StyleSheet.create({
     paddingHorizontal: 10,
     paddingVertical: 3,
     position: 'absolute',
-    left: 10,
-    top: -26,
+    left: 6,
+    bottom: 6,
     width: 46,
   },
 })
diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx
index 929c85ad..2dda9069 100644
--- a/src/view/com/util/post-embeds/index.tsx
+++ b/src/view/com/util/post-embeds/index.tsx
@@ -1,11 +1,10 @@
-import React, {useCallback} from 'react'
+import React from 'react'
 import {
   StyleSheet,
   StyleProp,
   View,
   ViewStyle,
   Image as RNImage,
-  Pressable,
   Text,
 } from 'react-native'
 import {
@@ -20,7 +19,6 @@ import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
 import {ImagesLightbox} from 'state/models/ui/shell'
 import {useStores} from 'state/index'
 import {usePalette} from 'lib/hooks/usePalette'
-import {saveImageModal} from 'lib/media/manip'
 import {YoutubeEmbed} from './YoutubeEmbed'
 import {ExternalLinkEmbed} from './ExternalLinkEmbed'
 import {getYoutubeVideoId} from 'lib/strings/url-helpers'
@@ -44,16 +42,6 @@ export function PostEmbeds({
   const pal = usePalette('default')
   const store = useStores()
 
-  const onPressAltText = useCallback(
-    (alt: string) => {
-      store.shell.openModal({
-        name: 'alt-text-image-read',
-        altText: alt,
-      })
-    },
-    [store.shell],
-  )
-
   if (
     AppBskyEmbedRecordWithMedia.isView(embed) &&
     AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
@@ -103,20 +91,17 @@ export function PostEmbeds({
     const {images} = embed
 
     if (images.length > 0) {
-      const uris = embed.images.map(img => img.fullsize)
+      const items = embed.images.map(img => ({uri: img.fullsize, alt: img.alt}))
       const openLightbox = (index: number) => {
-        store.shell.openLightbox(new ImagesLightbox(uris, index))
-      }
-      const onLongPress = (index: number) => {
-        saveImageModal({uri: uris[index]})
+        store.shell.openLightbox(new ImagesLightbox(items, index))
       }
       const onPressIn = (index: number) => {
-        const firstImageToShow = uris[index]
+        const firstImageToShow = items[index].uri
         RNImage.prefetch(firstImageToShow)
-        uris.forEach(uri => {
-          if (firstImageToShow !== uri) {
+        items.forEach(item => {
+          if (firstImageToShow !== item.uri) {
             // First image already prefeched above
-            RNImage.prefetch(uri)
+            RNImage.prefetch(item.uri)
           }
         })
       }
@@ -129,20 +114,9 @@ export function PostEmbeds({
               alt={alt}
               uri={thumb}
               onPress={() => openLightbox(0)}
-              onLongPress={() => onLongPress(0)}
               onPressIn={() => onPressIn(0)}
               style={styles.singleImage}>
-              {alt === '' ? null : (
-                <Pressable
-                  onPress={() => {
-                    onPressAltText(alt)
-                  }}
-                  accessibilityRole="button"
-                  accessibilityLabel="View alt text"
-                  accessibilityHint="Opens modal with alt text">
-                  <Text style={styles.alt}>ALT</Text>
-                </Pressable>
-              )}
+              {alt === '' ? null : <Text style={styles.alt}>ALT</Text>}
             </AutoSizedImage>
           </View>
         )
@@ -153,7 +127,6 @@ export function PostEmbeds({
           <ImageLayoutGrid
             images={embed.images}
             onPress={openLightbox}
-            onLongPress={onLongPress}
             onPressIn={onPressIn}
             style={embed.images.length === 1 ? styles.singleImage : undefined}
           />
@@ -209,8 +182,8 @@ const styles = StyleSheet.create({
     paddingHorizontal: 10,
     paddingVertical: 3,
     position: 'absolute',
-    left: 10,
-    top: -26,
+    left: 6,
+    bottom: 6,
     width: 46,
   },
 })