Rating.svelte
1 <script lang="ts"> 2 import type { RatingCountsList } from './types'; 3 import { calculatePercentages } from './utils'; 4 import FilledStarIcon from '@amp/web-app-components/assets/icons/star-filled.svg'; 5 6 /** 7 * @name Rating 8 * 9 * @description 10 * This implements the standard rating lockup showing aggregate ratings 11 * 12 * Design: 13 * https://pd-hi.apple.com/viewvc/Common/Modules/macOS/Podcasts/Lockups/Review%20Lockup.png?revision=57299 14 * 15 * Aria Discussions: 16 * https://quip-apple.com/yvZaAbJMnAK0#JeB9CAOHPMd 17 * 18 * POTW difference: 19 * No write a review on the web 20 */ 21 22 export let averageRating: number | string; 23 export let ratingCount: number; 24 export let ratingCountText: string; 25 export let ratingCountsList: RatingCountsList; 26 export let totalText: string; 27 28 $: ratingPercentList = calculatePercentages(ratingCountsList, ratingCount); 29 </script> 30 31 <div class="amp-rating" data-testid="rating-component"> 32 <div class="stats" aria-label={`${averageRating} ${totalText}`}> 33 <div class="stats__main" data-testid="amp-rating__average-rating"> 34 {averageRating} 35 </div> 36 <div class="stats__total" data-testid="amp-rating__total-text"> 37 {totalText} 38 </div> 39 </div> 40 <div class="numbers"> 41 <div class="numbers__star-graph"> 42 {#each ratingPercentList as value, i} 43 <div 44 class={`numbers__star-graph__row row-${i}`} 45 aria-label={`${5 - i} star, ${value}%`} 46 > 47 <!-- TODO: rdar://79873131 (Localize Aria Label in Rating Shared Component) --> 48 <div class="numbers__star-graph__row__stars"> 49 <!-- In order to display the 5 stars to 1 stars we use the 5 - index as 0 index means 1 star and so on --> 50 {#each { length: 5 - i } as _} 51 <div class="star"><FilledStarIcon /></div> 52 {/each} 53 </div> 54 <div class="numbers__star-graph__row__bar"> 55 <div 56 class="numbers__star-graph__row__bar__foreground" 57 style={`width: ${value}%`} 58 data-testid={`star-row-${5 - i}`} 59 /> 60 </div> 61 </div> 62 {/each} 63 </div> 64 <div class="numbers__count" data-testid="amp-rating__rating-count-text"> 65 {ratingCountText} 66 </div> 67 </div> 68 </div> 69 70 <style lang="scss"> 71 .amp-rating { 72 display: flex; 73 } 74 75 .stats { 76 margin-right: 10px; 77 flex: 0 80px; 78 } 79 80 .stats__main { 81 font-size: 50px; 82 font-weight: bold; 83 display: flex; 84 justify-content: center; 85 } 86 87 .stats__total { 88 display: flex; 89 justify-content: center; 90 color: var(--systemSecondary-text); 91 font: var(--body-emphasized); 92 } 93 94 .numbers { 95 width: 100%; 96 } 97 98 .numbers__count { 99 display: flex; 100 align-items: flex-end; 101 justify-content: flex-end; 102 color: var(--systemSecondary-text); 103 } 104 105 .numbers__star-graph { 106 margin-top: 12px; 107 line-height: 9px; 108 } 109 110 .numbers__star-graph__row { 111 display: flex; 112 width: 100%; 113 } 114 115 .numbers__star-graph__row__stars { 116 display: flex; 117 min-width: 45px; 118 font-size: 8px; 119 justify-content: flex-end; 120 margin-right: 6px; 121 122 & :global(.star) { 123 fill: var(--systemSecondary); 124 width: 8px; 125 height: 8px; 126 } 127 } 128 129 .numbers__star-graph__row__bar { 130 height: 2px; 131 width: 100%; 132 background: var(--systemQuaternary); 133 margin-top: 3px; 134 } 135 136 .numbers__star-graph__row__bar__foreground { 137 height: 2px; 138 background: var(--ratingBarColor, --systemSecondary); 139 max-width: 100%; 140 } 141 </style>