mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 17:42:24 -05:00 
			
		
		
		
	[bugfix] Fixes to tablist, fileinput, checkbox
This commit is contained in:
		
					parent
					
						
							
								ca04512689
							
						
					
				
			
			
				commit
				
					
						d0c3bd80e6
					
				
			
		
					 4 changed files with 85 additions and 45 deletions
				
			
		|  | @ -493,9 +493,8 @@ section.with-form { | |||
| 			gap: 0.4rem; | ||||
| 
 | ||||
| 			& > input { | ||||
| 				height: 100%; | ||||
| 				width: 5%; | ||||
| 				min-width: 1.2rem; | ||||
| 				height: 1rem; | ||||
| 				width: 1rem; | ||||
| 				align-self: center; | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -122,10 +122,6 @@ export function FileInput({ label, field, ...props }: FileInputProps) { | |||
| 	const ref = useRef<HTMLInputElement>(null); | ||||
| 	const { onChange, infoComponent } = field; | ||||
| 	const id = nanoid(); | ||||
| 	const onClick = (e) => { | ||||
| 		e.preventDefault(); | ||||
| 		ref.current?.click(); | ||||
| 	}; | ||||
| 
 | ||||
| 	return ( | ||||
| 		<div className="form-field file"> | ||||
|  | @ -133,11 +129,9 @@ export function FileInput({ label, field, ...props }: FileInputProps) { | |||
| 				className="label-wrapper" | ||||
| 				htmlFor={id} | ||||
| 				tabIndex={0} | ||||
| 				onClick={onClick} | ||||
| 				onKeyDown={(e) => { | ||||
| 					if (e.key === "Enter") { | ||||
| 						e.preventDefault(); | ||||
| 						onClick(e); | ||||
| 						ref.current?.click(); | ||||
| 					} | ||||
| 				}} | ||||
| 				role="button" | ||||
|  |  | |||
|  | @ -71,9 +71,6 @@ export default function ImportExportForm({ form, submitParse, parseResult }: Imp | |||
| 	}, [exportResult]); | ||||
| 
 | ||||
| 	const importFileRef = useRef<HTMLInputElement>(null); | ||||
| 	const importFileOnClick = () => { | ||||
| 		importFileRef.current?.click(); | ||||
| 	}; | ||||
| 
 | ||||
| 	return ( | ||||
| 		<> | ||||
|  | @ -109,11 +106,9 @@ export default function ImportExportForm({ form, submitParse, parseResult }: Imp | |||
| 					<label | ||||
| 						className={`button with-icon${form.permType.value === undefined || form.permType.value.length === 0 ? " disabled" : ""}`} | ||||
| 						tabIndex={0} | ||||
| 						onClick={importFileOnClick} | ||||
| 						onKeyDown={(e) => { | ||||
| 							if (e.key === "Enter") { | ||||
| 								e.preventDefault(); | ||||
| 								importFileOnClick(); | ||||
| 								importFileRef.current?.click(); | ||||
| 							} | ||||
| 						}} | ||||
| 						role="button" | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| import React, { useCallback, useMemo } from "react"; | ||||
| import React, { forwardRef, useCallback, useMemo, useRef } from "react"; | ||||
| import { | ||||
| 	useDefaultInteractionPoliciesQuery, | ||||
| 	useResetDefaultInteractionPoliciesMutation, | ||||
|  | @ -191,57 +191,109 @@ function InteractionPoliciesForm({ defaultPolicies }: InteractionPoliciesFormPro | |||
| 
 | ||||
| // A tablist of tab buttons, one for each visibility.
 | ||||
| function PolicyPanelsTablist({ selectedVis }: { selectedVis: TextFormInputHook}) { | ||||
| 	const publicRef = useRef<HTMLButtonElement>(null); | ||||
| 	const unlistedRef = useRef<HTMLButtonElement>(null); | ||||
| 	const privateRef = useRef<HTMLButtonElement>(null); | ||||
| 	 | ||||
| 	return ( | ||||
| 		<div className="tab-buttons" role="tablist"> | ||||
| 			<Tab | ||||
| 				thisVisibility="public" | ||||
| 				label="Public" | ||||
| 				selectedVis={selectedVis} | ||||
| 				prevVis="private" | ||||
| 				thisVis="public" | ||||
| 				nextVis="unlisted" | ||||
| 				prevRef={privateRef} | ||||
| 				thisRef={publicRef} | ||||
| 				nextRef={unlistedRef} | ||||
| 			/> | ||||
| 			<Tab | ||||
| 				thisVisibility="unlisted" | ||||
| 				label="Unlisted" | ||||
| 				selectedVis={selectedVis} | ||||
| 				prevVis="public" | ||||
| 				thisVis="unlisted" | ||||
| 				nextVis="private" | ||||
| 				prevRef={publicRef} | ||||
| 				thisRef={unlistedRef} | ||||
| 				nextRef={privateRef} | ||||
| 			/> | ||||
| 			<Tab | ||||
| 				thisVisibility="private" | ||||
| 				label="Followers-only" | ||||
| 				selectedVis={selectedVis} | ||||
| 				prevVis="unlisted" | ||||
| 				thisVis="private" | ||||
| 				nextVis="public" | ||||
| 				prevRef={unlistedRef} | ||||
| 				thisRef={privateRef} | ||||
| 				nextRef={publicRef} | ||||
| 			/> | ||||
| 		</div> | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| interface TabProps { | ||||
| 	thisVisibility: string; | ||||
| 	label: string, | ||||
| 	selectedVis: TextFormInputHook | ||||
| 	label: string; | ||||
| 	selectedVis: TextFormInputHook; | ||||
| 	prevVis: string; | ||||
| 	thisVis: string; | ||||
| 	nextVis: string; | ||||
| 	prevRef: React.RefObject<HTMLButtonElement>; | ||||
| 	thisRef: React.RefObject<HTMLButtonElement>; | ||||
| 	nextRef: React.RefObject<HTMLButtonElement>; | ||||
| } | ||||
| 
 | ||||
| // One tab in a tablist, corresponding to the given thisVisibility.
 | ||||
| function Tab({ thisVisibility, label, selectedVis }: TabProps) { | ||||
| 	const selected = useMemo(() => { | ||||
| 		return selectedVis.value === thisVisibility; | ||||
| 	}, [selectedVis, thisVisibility]); | ||||
| const Tab = forwardRef( | ||||
| 	function Tab({ | ||||
| 		label, | ||||
| 		selectedVis, | ||||
| 		prevVis, | ||||
| 		thisVis, | ||||
| 		nextVis, | ||||
| 		prevRef, | ||||
| 		thisRef, | ||||
| 		nextRef, | ||||
| 	}: TabProps) { | ||||
| 		const selected = useMemo(() => { | ||||
| 			return selectedVis.value === thisVis; | ||||
| 		}, [selectedVis, thisVis]); | ||||
| 
 | ||||
| 	return ( | ||||
| 		<button | ||||
| 			id={`tab-${thisVisibility}`} | ||||
| 			title={label} | ||||
| 			role="tab" | ||||
| 			className={`tab-button ${selected && "active"}`} | ||||
| 			onClick={(e) => { | ||||
| 				e.preventDefault(); | ||||
| 				selectedVis.setter(thisVisibility); | ||||
| 			}} | ||||
| 			aria-selected={selected} | ||||
| 			aria-controls={`panel-${thisVisibility}`} | ||||
| 			tabIndex={selected ? 0 : -1} | ||||
| 		> | ||||
| 			{label} | ||||
| 		</button> | ||||
| 	); | ||||
| } | ||||
| 		return ( | ||||
| 			<button | ||||
| 				id={`tab-${thisVis}`} | ||||
| 				title={label} | ||||
| 				role="tab" | ||||
| 				ref={thisRef} | ||||
| 				className={`tab-button ${selected && "active"}`} | ||||
| 				onClick={(e) => { | ||||
| 					// Allow tab to be clicked.
 | ||||
| 					e.preventDefault(); | ||||
| 					selectedVis.setter(thisVis); | ||||
| 				}} | ||||
| 				onKeyDown={(e) => { | ||||
| 					// Allow cycling through
 | ||||
| 					// tabs with arrow keys.
 | ||||
| 					if (e.key === "ArrowLeft") { | ||||
| 						// Select and set
 | ||||
| 						// focus on previous tab.
 | ||||
| 						selectedVis.setter(prevVis); | ||||
| 						prevRef.current?.focus(); | ||||
| 					} else if (e.key === "ArrowRight") { | ||||
| 						// Select and set
 | ||||
| 						// focus on next tab.
 | ||||
| 						selectedVis.setter(nextVis); | ||||
| 						nextRef.current?.focus(); | ||||
| 					} | ||||
| 				}} | ||||
| 				aria-selected={selected} | ||||
| 				aria-controls={`panel-${thisVis}`} | ||||
| 				tabIndex={selected ? 0 : -1} | ||||
| 			> | ||||
| 				{label} | ||||
| 			</button> | ||||
| 		); | ||||
| 	} | ||||
| ); | ||||
| 
 | ||||
| interface PolicyPanelProps { | ||||
| 	policyForm: PolicyForm; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue