Add information about alt text to alt text modal in web UI (#33702)
This commit is contained in:
		
					parent
					
						
							
								db146046c4
							
						
					
				
			
			
				commit
				
					
						0885c31633
					
				
			
		
					 7 changed files with 142 additions and 6 deletions
				
			
		|  | @ -0,0 +1,81 @@ | |||
| import { useState, useRef, useCallback, useId } from 'react'; | ||||
| 
 | ||||
| import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; | ||||
| 
 | ||||
| import classNames from 'classnames'; | ||||
| 
 | ||||
| import Overlay from 'react-overlays/Overlay'; | ||||
| 
 | ||||
| import QuestionMarkIcon from '@/material-icons/400-24px/question_mark.svg?react'; | ||||
| import { Icon } from 'mastodon/components/icon'; | ||||
| 
 | ||||
| const messages = defineMessages({ | ||||
|   help: { id: 'info_button.label', defaultMessage: 'Help' }, | ||||
| }); | ||||
| 
 | ||||
| export const InfoButton: React.FC = () => { | ||||
|   const intl = useIntl(); | ||||
|   const [open, setOpen] = useState(false); | ||||
|   const triggerRef = useRef<HTMLButtonElement>(null); | ||||
|   const accessibilityId = useId(); | ||||
| 
 | ||||
|   const handleClick = useCallback(() => { | ||||
|     setOpen(!open); | ||||
|   }, [open, setOpen]); | ||||
| 
 | ||||
|   return ( | ||||
|     <> | ||||
|       <button | ||||
|         type='button' | ||||
|         className={classNames('help-button', { active: open })} | ||||
|         ref={triggerRef} | ||||
|         onClick={handleClick} | ||||
|         aria-expanded={open} | ||||
|         aria-controls={accessibilityId} | ||||
|         aria-label={intl.formatMessage(messages.help)} | ||||
|       > | ||||
|         <Icon id='' icon={QuestionMarkIcon} /> | ||||
|       </button> | ||||
| 
 | ||||
|       <Overlay | ||||
|         show={open} | ||||
|         rootClose | ||||
|         placement='top' | ||||
|         onHide={handleClick} | ||||
|         offset={[5, 5]} | ||||
|         target={triggerRef} | ||||
|       > | ||||
|         {({ props }) => ( | ||||
|           <div | ||||
|             {...props} | ||||
|             className='dialog-modal__popout prose dropdown-animation' | ||||
|             id={accessibilityId} | ||||
|           > | ||||
|             <FormattedMessage | ||||
|               id='info_button.what_is_alt_text' | ||||
|               defaultMessage='<h1>What is alt text?</h1> | ||||
| 
 | ||||
|             <p>Alt text provides image descriptions for people with vision impairments, low-bandwidth connections, or those seeking extra context.</p> | ||||
| 
 | ||||
|             <p>You can improve accessibility and understanding for everyone by writing clear, concise, and objective alt text.</p> | ||||
| 
 | ||||
|             <ul> | ||||
|               <li>Capture important elements</li> | ||||
|               <li>Summarize text in images</li> | ||||
|               <li>Use regular sentence structure</li> | ||||
|               <li>Avoid redundant information</li> | ||||
|               <li>Focus on trends and key findings in complex visuals (like diagrams or maps)</li> | ||||
|             </ul>' | ||||
|               values={{ | ||||
|                 h1: (node) => <h1>{node}</h1>, | ||||
|                 p: (node) => <p>{node}</p>, | ||||
|                 ul: (node) => <ul>{node}</ul>, | ||||
|                 li: (node) => <li>{node}</li>, | ||||
|               }} | ||||
|             /> | ||||
|           </div> | ||||
|         )} | ||||
|       </Overlay> | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
|  | @ -36,6 +36,8 @@ import type { MediaAttachment } from 'mastodon/models/media_attachment'; | |||
| import { useAppSelector, useAppDispatch } from 'mastodon/store'; | ||||
| import { assetHost } from 'mastodon/utils/config'; | ||||
| 
 | ||||
| import { InfoButton } from './components/info_button'; | ||||
| 
 | ||||
| const messages = defineMessages({ | ||||
|   placeholderVisual: { | ||||
|     id: 'alt_text_modal.describe_for_people_with_visual_impairments', | ||||
|  | @ -504,6 +506,13 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>( | |||
|               </div> | ||||
| 
 | ||||
|               <div className='input__toolbar'> | ||||
|                 <CharacterCounter | ||||
|                   max={MAX_LENGTH} | ||||
|                   text={isDetecting ? '' : description} | ||||
|                 /> | ||||
| 
 | ||||
|                 <div className='spacer' /> | ||||
| 
 | ||||
|                 <button | ||||
|                   className='link-button' | ||||
|                   onClick={handleDetectClick} | ||||
|  | @ -515,10 +524,7 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>( | |||
|                   /> | ||||
|                 </button> | ||||
| 
 | ||||
|                 <CharacterCounter | ||||
|                   max={MAX_LENGTH} | ||||
|                   text={isDetecting ? '' : description} | ||||
|                 /> | ||||
|                 <InfoButton /> | ||||
|               </div> | ||||
|             </div> | ||||
|           </form> | ||||
|  |  | |||
|  | @ -414,6 +414,8 @@ | |||
|   "ignore_notifications_modal.not_followers_title": "Ignore notifications from people not following you?", | ||||
|   "ignore_notifications_modal.not_following_title": "Ignore notifications from people you don't follow?", | ||||
|   "ignore_notifications_modal.private_mentions_title": "Ignore notifications from unsolicited Private Mentions?", | ||||
|   "info_button.label": "Help", | ||||
|   "info_button.what_is_alt_text": "<h1>What is alt text?</h1> <p>Alt text provides image descriptions for people with vision impairments, low-bandwidth connections, or those seeking extra context.</p> <p>You can improve accessibility and understanding for everyone by writing clear, concise, and objective alt text.</p> <ul> <li>Capture important elements</li> <li>Summarize text in images</li> <li>Use regular sentence structure</li> <li>Avoid redundant information</li> <li>Focus on trends and key findings in complex visuals (like diagrams or maps)</li> </ul>", | ||||
|   "interaction_modal.action.favourite": "To continue, you need to favorite from your account.", | ||||
|   "interaction_modal.action.follow": "To continue, you need to follow from your account.", | ||||
|   "interaction_modal.action.reblog": "To continue, you need to reblog from your account.", | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M424-320q0-81 14.5-116.5T500-514q41-36 62.5-62.5T584-637q0-41-27.5-68T480-732q-51 0-77.5 31T365-638l-103-44q21-64 77-111t141-47q105 0 161.5 58.5T698-641q0 50-21.5 85.5T609-475q-49 47-59.5 71.5T539-320H424Zm56 240q-33 0-56.5-23.5T400-160q0-33 23.5-56.5T480-240q33 0 56.5 23.5T560-160q0 33-23.5 56.5T480-80Z"/></svg> | ||||
| After Width: | Height: | Size: 411 B | 
							
								
								
									
										1
									
								
								app/javascript/material-icons/400-24px/question_mark.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								app/javascript/material-icons/400-24px/question_mark.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M424-320q0-81 14.5-116.5T500-514q41-36 62.5-62.5T584-637q0-41-27.5-68T480-732q-51 0-77.5 31T365-638l-103-44q21-64 77-111t141-47q105 0 161.5 58.5T698-641q0 50-21.5 85.5T609-475q-49 47-59.5 71.5T539-320H424Zm56 240q-33 0-56.5-23.5T400-160q0-33 23.5-56.5T480-240q33 0 56.5 23.5T560-160q0 33-23.5 56.5T480-80Z"/></svg> | ||||
| After Width: | Height: | Size: 411 B | 
|  | @ -50,6 +50,34 @@ | |||
|   } | ||||
| } | ||||
| 
 | ||||
| .help-button { | ||||
|   background: $ui-button-background-color; | ||||
|   border: 0; | ||||
|   color: $ui-button-color; | ||||
|   border-radius: 20px; | ||||
|   cursor: pointer; | ||||
|   width: 24px; | ||||
|   height: 24px; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
| 
 | ||||
|   &:active, | ||||
|   &:focus, | ||||
|   &:hover { | ||||
|     background-color: $ui-button-focus-background-color; | ||||
|   } | ||||
| 
 | ||||
|   &:focus-visible { | ||||
|     outline: $ui-button-icon-focus-outline; | ||||
|   } | ||||
| 
 | ||||
|   .icon { | ||||
|     width: 14px; | ||||
|     height: 14px; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .button { | ||||
|   background-color: $ui-button-background-color; | ||||
|   border: 10px none; | ||||
|  | @ -6091,6 +6119,20 @@ a.status-card { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &__popout { | ||||
|     background: var(--dropdown-background-color); | ||||
|     backdrop-filter: var(--background-filter); | ||||
|     border: 1px solid var(--dropdown-border-color); | ||||
|     box-shadow: var(--dropdown-shadow); | ||||
|     max-width: 320px; | ||||
|     padding: 16px; | ||||
|     border-radius: 8px; | ||||
|     z-index: 9999 !important; | ||||
|     font-size: 14px; | ||||
|     line-height: 20px; | ||||
|     color: $darker-text-color; | ||||
|   } | ||||
| 
 | ||||
|   .copy-paste-text { | ||||
|     margin-bottom: 0; | ||||
|   } | ||||
|  |  | |||
|  | @ -83,9 +83,12 @@ code { | |||
|     &__toolbar { | ||||
|       margin-top: 16px; | ||||
|       display: flex; | ||||
|       justify-content: space-between; | ||||
|       align-items: center; | ||||
|       gap: 16px; | ||||
| 
 | ||||
|       .character-counter { | ||||
|         flex: 0 0 auto; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &.hidden { | ||||
|  | @ -565,7 +568,7 @@ code { | |||
|     margin-bottom: 15px; | ||||
|   } | ||||
| 
 | ||||
|   button:not(.button, .link-button) { | ||||
|   button:not(.button, .link-button, .help-button) { | ||||
|     display: block; | ||||
|     width: 100%; | ||||
|     border: 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue