@@ -185,6 +185,137 @@ export const LabelTogglingTest: Story = {
185185 } ,
186186} ;
187187
188+ // ──────────────────────────────────────────────────────────────
189+ // TEST: RTL mirroring
190+ // ──────────────────────────────────────────────────────────────
191+
192+ export const DirectionalIconMirrorsInRtlTest : Story = {
193+ render : ( ) => html `
194+ < swc-ui-icon
195+ icon ="chevron "
196+ dir ="rtl "
197+ accessible-label ="Expand "
198+ > </ swc-ui-icon >
199+ ` ,
200+ play : async ( { canvasElement, step } ) => {
201+ const icon = await getComponent < UiIcon > ( canvasElement , 'swc-ui-icon' ) ;
202+
203+ await step ( 'mirrors a curated directional icon under RTL' , async ( ) => {
204+ expect (
205+ getComputedStyle ( icon ) . scale ,
206+ 'chevron is horizontally mirrored in RTL'
207+ ) . toBe ( '-1 1' ) ;
208+ } ) ;
209+ } ,
210+ } ;
211+
212+ // chevron and arrow are two independent :host() selector clauses in
213+ // ui-icon-direction.css, not one dynamically-generated rule, so each is
214+ // tested explicitly; a typo in one clause wouldn't be caught by testing
215+ // only the other.
216+ export const SecondDirectionalIconMirrorsInRtlTest : Story = {
217+ render : ( ) => html `
218+ < swc-ui-icon icon ="arrow " dir ="rtl " accessible-label ="Go "> </ swc-ui-icon >
219+ ` ,
220+ play : async ( { canvasElement, step } ) => {
221+ const icon = await getComponent < UiIcon > ( canvasElement , 'swc-ui-icon' ) ;
222+
223+ await step (
224+ 'mirrors the other curated directional icon under RTL' ,
225+ async ( ) => {
226+ expect (
227+ getComputedStyle ( icon ) . scale ,
228+ 'arrow is horizontally mirrored in RTL'
229+ ) . toBe ( '-1 1' ) ;
230+ }
231+ ) ;
232+ } ,
233+ } ;
234+
235+ // Mirrors tabs.test.ts's SelectionIndicatorDirectionChangeTest pattern: real
236+ // consumers (AccordionItem, MessageSources, ResponseStatus) never set `dir`
237+ // directly on their <swc-ui-icon>; they rely on it inheriting from an
238+ // ancestor. Verified separately from the direct-attribute tests above since
239+ // :host(:dir(rtl)[icon="..."])'s selector-matching quirk (see
240+ // ui-icon-direction.css) makes it worth confirming inherited directionality
241+ // resolves the same way, not assuming it from spec compliance alone.
242+ export const DirectionalIconMirrorsWithInheritedRtlTest : Story = {
243+ render : ( ) => html `
244+ < div id ="direction-wrapper " dir ="ltr ">
245+ < swc-ui-icon icon ="chevron " accessible-label ="Expand "> </ swc-ui-icon >
246+ </ div >
247+ ` ,
248+ play : async ( { canvasElement, step } ) => {
249+ const icon = await getComponent < UiIcon > ( canvasElement , 'swc-ui-icon' ) ;
250+ const wrapper = canvasElement . querySelector (
251+ '#direction-wrapper'
252+ ) as HTMLElement ;
253+
254+ await step ( 'does not mirror while the ancestor is LTR' , async ( ) => {
255+ expect (
256+ getComputedStyle ( icon ) . scale ,
257+ 'chevron is unmirrored while the ancestor is LTR'
258+ ) . toBe ( 'none' ) ;
259+ } ) ;
260+
261+ await step (
262+ 'mirrors once an ancestor dir attribute flips to RTL at runtime' ,
263+ async ( ) => {
264+ wrapper . setAttribute ( 'dir' , 'rtl' ) ;
265+ await icon . updateComplete ;
266+ expect (
267+ getComputedStyle ( icon ) . scale ,
268+ 'chevron mirrors once the ancestor is RTL, with no dir attribute of its own'
269+ ) . toBe ( '-1 1' ) ;
270+ }
271+ ) ;
272+
273+ wrapper . setAttribute ( 'dir' , 'ltr' ) ;
274+ } ,
275+ } ;
276+
277+ export const DirectionalIconUnmirroredInLtrTest : Story = {
278+ render : ( ) => html `
279+ < swc-ui-icon
280+ icon ="chevron "
281+ dir ="ltr "
282+ accessible-label ="Expand "
283+ > </ swc-ui-icon >
284+ ` ,
285+ play : async ( { canvasElement, step } ) => {
286+ const icon = await getComponent < UiIcon > ( canvasElement , 'swc-ui-icon' ) ;
287+
288+ await step ( 'does not mirror under LTR' , async ( ) => {
289+ expect ( getComputedStyle ( icon ) . scale , 'chevron is unmirrored in LTR' ) . toBe (
290+ 'none'
291+ ) ;
292+ } ) ;
293+ } ,
294+ } ;
295+
296+ export const NonDirectionalIconUnaffectedInRtlTest : Story = {
297+ render : ( ) => html `
298+ < swc-ui-icon
299+ icon ="checkmark "
300+ dir ="rtl "
301+ accessible-label ="Done "
302+ > </ swc-ui-icon >
303+ ` ,
304+ play : async ( { canvasElement, step } ) => {
305+ const icon = await getComponent < UiIcon > ( canvasElement , 'swc-ui-icon' ) ;
306+
307+ await step (
308+ 'leaves a non-directional icon unmirrored under RTL' ,
309+ async ( ) => {
310+ expect (
311+ getComputedStyle ( icon ) . scale ,
312+ 'checkmark is not in the curated directional list, so it never flips'
313+ ) . toBe ( 'none' ) ;
314+ }
315+ ) ;
316+ } ,
317+ } ;
318+
188319// ──────────────────────────────────────────────────────────────
189320// TEST: Edge cases
190321// ──────────────────────────────────────────────────────────────
0 commit comments