-
Notifications
You must be signed in to change notification settings - Fork 856
Forms: Display star rating icons in response inspector #46874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f9bb851
7ba52ce
9bf16ea
113a28d
620335c
69474c0
d1f48e2
d196e48
d514a15
2f8a3ae
36cba3f
7d8c0bb
b6d1cd8
d47c24c
d0d117a
0d6e2e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| Significance: patch | ||
| Type: added | ||
|
|
||
| Response inspector: display star rating icons for rating field submissions. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { SVG, Path } from '@wordpress/components'; | ||
| import { RATING_ICONS } from './rating-icons.js'; | ||
|
|
||
| /** | ||
| * Rating icon React component for use in the block editor and dashboard. | ||
| * | ||
| * @param {object} props - Component props. | ||
| * @param {string} props.iconStyle - The icon style ('stars' or 'hearts'). | ||
| * @param {string} props.strokeColor - SVG stroke color. | ||
| * @param {string} props.fillColor - SVG fill color. | ||
| * @param {number} props.strokeWidth - SVG stroke width. | ||
| * @return {import('react').JSX.Element} SVG icon element. | ||
| */ | ||
| export const RatingIcon = ( { | ||
| iconStyle, | ||
| strokeColor = 'currentColor', | ||
| fillColor = 'none', | ||
| strokeWidth = 2, | ||
| } ) => { | ||
| const iconPath = RATING_ICONS[ iconStyle ] || RATING_ICONS.stars; | ||
| return ( | ||
| <SVG className="jetpack-field-rating__icon" viewBox="0 0 24 24" aria-hidden="true"> | ||
| <Path | ||
| d={ iconPath } | ||
| fill={ fillColor } | ||
| stroke={ strokeColor } | ||
| strokeWidth={ strokeWidth } | ||
| strokeLinejoin="round" | ||
| /> | ||
| </SVG> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||
| * External dependencies | ||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||
| __experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis | ||||||||||||||||||||||||||||
| VisuallyHidden, | ||||||||||||||||||||||||||||
| } from '@wordpress/components'; | ||||||||||||||||||||||||||||
| import { __, sprintf } from '@wordpress/i18n'; | ||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||
| * Internal dependencies | ||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||
| import { RatingIcon } from '../../../../../blocks/field-rating/rating-icon.js'; | ||||||||||||||||||||||||||||
| import { MAX_RATING_ICONS } from '../../../../../blocks/field-rating/rating-icons.js'; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| type FieldRatingProps = { | ||||||||||||||||||||||||||||
| value?: string | null; | ||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const FieldRating = ( { value }: FieldRatingProps ) => { | ||||||||||||||||||||||||||||
| const stringValue = value != null ? String( value ) : ''; | ||||||||||||||||||||||||||||
| if ( stringValue.trim() === '' ) { | ||||||||||||||||||||||||||||
| return '-'; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| const [ rateValue, outOf ] = stringValue.split( '/' ) ?? []; | ||||||||||||||||||||||||||||
| if ( ! rateValue || rateValue.trim() === '' ) { | ||||||||||||||||||||||||||||
| return '-'; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| if ( ! outOf || outOf.trim() === '' ) { | ||||||||||||||||||||||||||||
| return '-'; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const rateValueTrimmed = rateValue.trim(); | ||||||||||||||||||||||||||||
| const outOfTrimmed = outOf.trim(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Require strictly numeric values to reject partial matches like "4abc" | ||||||||||||||||||||||||||||
| if ( ! /^[0-9]+$/.test( rateValueTrimmed ) || ! /^[0-9]+$/.test( outOfTrimmed ) ) { | ||||||||||||||||||||||||||||
| return '-'; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const parsedRating = Number.parseInt( rateValueTrimmed, 10 ); | ||||||||||||||||||||||||||||
| const parsedMax = Number.parseInt( outOfTrimmed, 10 ); | ||||||||||||||||||||||||||||
| if ( | ||||||||||||||||||||||||||||
| ! Number.isFinite( parsedRating ) || | ||||||||||||||||||||||||||||
| parsedRating < 0 || | ||||||||||||||||||||||||||||
| ! Number.isFinite( parsedMax ) || | ||||||||||||||||||||||||||||
| parsedMax < 0 | ||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||
| return '-'; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Clamp max to prevent DOM bloat from large values | ||||||||||||||||||||||||||||
| const clampedMax = Math.min( parsedMax, MAX_RATING_ICONS ); | ||||||||||||||||||||||||||||
| const displayRating = Math.min( Math.max( 0, parsedRating ), clampedMax ); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
Comment on lines
42
to
54
|
||||||||||||||||||||||||||||
| const ratingLabel = sprintf( | ||||||||||||||||||||||||||||
| /* translators: 1: rating value, 2: maximum rating (e.g. "4" and "5" for "4 out of 5") */ | ||||||||||||||||||||||||||||
| __( 'Rating %1$s out of %2$s', 'jetpack-forms' ), | ||||||||||||||||||||||||||||
| String( displayRating ), | ||||||||||||||||||||||||||||
| String( clampedMax ) | ||||||||||||||||||||||||||||
|
Comment on lines
+55
to
+59
|
||||||||||||||||||||||||||||
| const ratingLabel = sprintf( | |
| /* translators: 1: rating value, 2: maximum rating (e.g. "4" and "5" for "4 out of 5") */ | |
| __( 'Rating %1$s out of %2$s', 'jetpack-forms' ), | |
| String( displayRating ), | |
| String( clampedMax ) | |
| // Use the original scale in the accessible label so screen readers get the real rating. | |
| const accessibleRating = Math.min( Math.max( 0, parsedRating ), parsedMax ); | |
| const ratingLabel = sprintf( | |
| /* translators: 1: rating value, 2: maximum rating (e.g. "4" and "5" for "4 out of 5") */ | |
| __( 'Rating %1$s out of %2$s', 'jetpack-forms' ), | |
| String( accessibleRating ), | |
| String( parsedMax ) |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alignment value "topLeft" should be "left" for HStack. The WordPress HStack component accepts alignment values like "left", "center", "right", "top", "bottom" but not "topLeft". This may cause unexpected behavior or styling issues.
| <HStack spacing="1" alignment="topLeft"> | |
| <HStack spacing="1" alignment="left"> |
Uh oh!
There was an error while loading. Please reload this page.