11import { Meta , StoryObj } from "@storybook/react-vite" ;
2- import Title from "../../.storybook/components/Title" ;
3- import ExampleContainer from "../../.storybook/components/ExampleContainer" ;
4- import DxcActionIcon from "./ActionIcon" ;
5- import DxcTooltip from "../tooltip/Tooltip" ;
6- import DxcInset from "../inset/Inset" ;
72import { userEvent , within } from "storybook/internal/test" ;
3+ import DxcActionIcon from "./ActionIcon" ;
4+ import DxcFlex from "../flex/Flex" ;
5+ import Title from "../../.storybook/components/Title" ;
6+ import ExampleContainer , { PseudoState } from "../../.storybook/components/ExampleContainer" ;
7+ import { ActionIconPropTypes , Status } from "./types" ;
88
99export default {
10- title : "Action Icon " ,
10+ title : "ActionIcon " ,
1111 component : DxcActionIcon ,
1212} satisfies Meta < typeof DxcActionIcon > ;
1313
14- const iconSVG = (
15- < svg width = "24px" height = "24px" viewBox = "0 0 24 24" fill = "currentColor" >
16- < path d = "M0 0h24v24H0z" fill = "none" />
17- < path d = "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
18- </ svg >
19- ) ;
14+ type Story = StoryObj < typeof DxcActionIcon > ;
2015
21- const ActionIcon = ( ) => (
22- < >
23- < Title title = "Default" theme = "light" level = { 2 } />
24- < ExampleContainer >
25- < DxcActionIcon icon = "favorite" title = "Favourite" />
26- </ ExampleContainer >
27- < Title title = "Disabled" theme = "light" level = { 2 } />
28- < ExampleContainer >
29- < DxcActionIcon icon = "favorite" title = "Favourite" disabled />
30- </ ExampleContainer >
31- < Title title = "Hover" theme = "light" level = { 2 } />
32- < ExampleContainer pseudoState = "pseudo-hover" >
33- < DxcActionIcon icon = "filled_favorite" title = "Favourite" />
34- </ ExampleContainer >
35- < Title title = "Focus" theme = "light" level = { 2 } />
36- < ExampleContainer pseudoState = "pseudo-focus" >
37- < DxcActionIcon icon = { iconSVG } title = "Favourite" />
38- </ ExampleContainer >
39- < Title title = "Active" theme = "light" level = { 2 } />
40- < ExampleContainer pseudoState = "pseudo-active" >
41- < DxcActionIcon icon = { iconSVG } title = "Favourite" />
42- </ ExampleContainer >
43- </ >
44- ) ;
16+ type GroupingKey = "size" | "shape" | "color" | "statusPosition" | "statusMode" | "pseudoState" ;
4517
46- const Tooltip = ( ) => (
47- < >
48- < Title title = "Default tooltip" theme = "light" level = { 2 } />
49- < ExampleContainer >
50- < DxcActionIcon icon = "favorite" title = "Favourite" />
51- </ ExampleContainer >
52- </ >
53- ) ;
18+ type ActionIconRowProps = {
19+ sizes ?: ActionIconPropTypes [ "size" ] [ ] ;
20+ shapes ?: ActionIconPropTypes [ "shape" ] [ ] ;
21+ colors ?: ActionIconPropTypes [ "color" ] [ ] ;
22+ icon ?: ActionIconPropTypes [ "icon" ] ;
23+ statusModes ?: Status [ "mode" ] [ ] ;
24+ statusPositions ?: ( Status [ "position" ] | undefined ) [ ] ;
25+ pseudoStates ?: ( PseudoState | "disabled" | undefined ) [ ] ;
26+ groupBy ?: GroupingKey [ ] ;
27+ } ;
28+
29+ const ActionIconRow = ( {
30+ sizes = [ "medium" ] ,
31+ shapes = [ "circle" ] ,
32+ colors = [ "neutral" ] ,
33+ statusModes,
34+ statusPositions = [ ] ,
35+ pseudoStates = [ ] ,
36+ groupBy = [ "size" ] ,
37+ } : ActionIconRowProps ) => {
38+ const getValuesForKey = ( key ?: GroupingKey ) => {
39+ switch ( key ) {
40+ case "size" :
41+ return sizes as string [ ] ;
42+ case "shape" :
43+ return shapes as string [ ] ;
44+ case "color" :
45+ return colors as string [ ] ;
46+ case "statusPosition" :
47+ return statusPositions as string [ ] ;
48+ case "statusMode" :
49+ return statusModes as string [ ] ;
50+ case "pseudoState" :
51+ return pseudoStates ;
52+ default :
53+ return [ ] ;
54+ }
55+ } ;
56+
57+ const renderGroup = (
58+ level : number ,
59+ filters : {
60+ size ?: ActionIconPropTypes [ "size" ] ;
61+ shape ?: ActionIconPropTypes [ "shape" ] ;
62+ color ?: ActionIconPropTypes [ "color" ] ;
63+ statusMode ?: Status [ "mode" ] ;
64+ statusPosition ?: Status [ "position" ] ;
65+ pseudoState ?: PseudoState | "disabled" ;
66+ }
67+ ) : JSX . Element | JSX . Element [ ] => {
68+ if ( level >= groupBy . length ) {
69+ const sizesToRender = filters . size ? [ filters . size ] : sizes ;
70+ const colorsToRender = filters . color ? [ filters . color ] : colors ;
71+ const shapesToRender = filters . shape ? [ filters . shape ] : shapes ;
72+ const positionsToRender = filters . statusPosition
73+ ? [ filters . statusPosition ]
74+ : statusPositions . length
75+ ? statusPositions
76+ : [ undefined ] ;
77+ const modesToRender = filters . statusMode ? [ filters . statusMode ] : statusModes ?. length ? statusModes : [ undefined ] ;
78+
79+ const pseudoStatesEnabled = ! ! filters . pseudoState ;
80+ const isDisabled = filters . pseudoState === "disabled" ;
81+ const validPseudoState = isDisabled ? undefined : ( filters . pseudoState as PseudoState | undefined ) ;
82+
83+ return shapesToRender . map ( ( shape ) => (
84+ < DxcFlex
85+ key = { `shape-${ shape } -${ String ( filters . size ?? "all" ) } -${ String ( filters . color ?? "all" ) } ` }
86+ gap = "var(--spacing-gap-l)"
87+ wrap = "wrap"
88+ >
89+ { sizesToRender . map ( ( size ) =>
90+ colorsToRender . map ( ( color ) =>
91+ positionsToRender . map ( ( position ) =>
92+ modesToRender . map ( ( mode ) => (
93+ < ExampleContainer
94+ key = { `${ size } -${ shape } -${ color } -${ mode } -${ position ?? "none" } ` }
95+ pseudoState = { validPseudoState }
96+ >
97+ < DxcActionIcon
98+ icon = "settings"
99+ size = { size }
100+ shape = { shape }
101+ color = { color }
102+ status = { position && mode ? { position, mode : mode } : undefined }
103+ onClick = { pseudoStatesEnabled ? ( ) => console . log ( "" ) : undefined }
104+ disabled = { isDisabled }
105+ />
106+ </ ExampleContainer >
107+ ) )
108+ )
109+ )
110+ ) }
111+ </ DxcFlex >
112+ ) ) ;
113+ }
54114
55- const NestedTooltip = ( ) => (
115+ const key = groupBy [ level ] ;
116+ const values = getValuesForKey ( key ) ;
117+
118+ return values . map ( ( value ) => {
119+ const newFilters = { ...filters } ;
120+ if ( key === "size" ) newFilters . size = value as ActionIconPropTypes [ "size" ] ;
121+ else if ( key === "shape" ) newFilters . shape = value as ActionIconPropTypes [ "shape" ] ;
122+ else if ( key === "color" ) newFilters . color = value as ActionIconPropTypes [ "color" ] ;
123+ else if ( key === "statusPosition" ) newFilters . statusPosition = value as Status [ "position" ] ;
124+ else if ( key === "statusMode" ) newFilters . statusMode = value as Status [ "mode" ] ;
125+ else if ( key === "pseudoState" ) newFilters . pseudoState = value as PseudoState | "disabled" ;
126+
127+ return (
128+ < div key = { `${ key } -${ String ( value ) } ` } >
129+ < Title title = { String ( value ) } theme = "light" level = { 3 + level } />
130+ { renderGroup ( level + 1 , newFilters ) }
131+ </ div >
132+ ) ;
133+ } ) ;
134+ } ;
135+
136+ return < > { renderGroup ( 0 , { } ) } </ > ;
137+ } ;
138+
139+ export const Shapes : Story = {
140+ render : ( ) => (
141+ < >
142+ < Title title = "Shapes" theme = "light" level = { 2 } />
143+ < ActionIconRow
144+ sizes = { [ "xsmall" , "small" , "medium" , "large" , "xlarge" , "xxlarge" ] }
145+ shapes = { [ "circle" , "square" ] }
146+ groupBy = { [ "shape" , "size" ] }
147+ />
148+ </ >
149+ ) ,
150+ } ;
151+
152+ export const Colors : Story = {
153+ render : ( ) => (
154+ < >
155+ < Title title = "Colors" theme = "light" level = { 2 } />
156+ < ActionIconRow
157+ sizes = { [ "medium" ] }
158+ shapes = { [ "circle" ] }
159+ colors = { [ "neutral" , "primary" , "secondary" , "tertiary" , "success" , "warning" , "error" , "info" , "transparent" ] }
160+ groupBy = { [ "color" ] }
161+ />
162+ </ >
163+ ) ,
164+ } ;
165+
166+ export const Statuses : Story = {
167+ render : ( ) => (
168+ < >
169+ < Title title = "Statuses" theme = "light" level = { 2 } />
170+ < ActionIconRow
171+ sizes = { [ "xsmall" , "small" , "medium" , "large" , "xlarge" , "xxlarge" ] }
172+ colors = { [ "neutral" , "primary" , "secondary" , "tertiary" , "success" , "warning" , "error" , "info" , "transparent" ] }
173+ shapes = { [ "circle" ] }
174+ statusModes = { [ "default" , "info" , "success" , "warning" , "error" ] }
175+ statusPositions = { [ "top" , "bottom" ] }
176+ groupBy = { [ "statusPosition" , "statusMode" , "color" ] }
177+ />
178+ </ >
179+ ) ,
180+ } ;
181+
182+ export const PseudoStates : Story = {
183+ render : ( ) => (
184+ < >
185+ < Title title = "Pseudo states" theme = "light" level = { 2 } />
186+ < ActionIconRow
187+ sizes = { [ "xsmall" , "small" , "medium" , "large" , "xlarge" , "xxlarge" ] }
188+ shapes = { [ "circle" ] }
189+ statusModes = { [ "success" ] }
190+ statusPositions = { [ undefined , "top" , "bottom" ] }
191+ pseudoStates = { [ undefined , "pseudo-hover" , "pseudo-focus" , "pseudo-active" , "disabled" ] }
192+ groupBy = { [ "pseudoState" , "size" ] }
193+ />
194+ </ >
195+ ) ,
196+ } ;
197+
198+ export const Types : Story = {
199+ render : ( ) => (
200+ < >
201+ < Title title = "Icon (custom)" theme = "light" level = { 2 } />
202+ < ActionIconRow
203+ sizes = { [ "xsmall" , "small" , "medium" , "large" , "xlarge" , "xxlarge" ] }
204+ shapes = { [ "circle" ] }
205+ groupBy = { [ "size" ] }
206+ />
207+ < Title title = "Icon (default)" theme = "light" level = { 2 } />
208+ < ActionIconRow
209+ sizes = { [ "xsmall" , "small" , "medium" , "large" , "xlarge" , "xxlarge" ] }
210+ shapes = { [ "circle" ] }
211+ groupBy = { [ "size" ] }
212+ />
213+ </ >
214+ ) ,
215+ } ;
216+
217+ const Tooltip = ( ) => (
56218 < >
57- < Title title = "Nested tooltip" theme = "light " level = { 2 } />
219+ < Title title = "Default tooltip" theme = "ligth " level = { 2 } />
58220 < ExampleContainer >
59- < DxcInset top = "var(--spacing-padding-xxl)" >
60- < DxcTooltip label = "Favourite" position = "top" >
61- < DxcActionIcon icon = "favorite" title = "Favourite" />
62- </ DxcTooltip >
63- </ DxcInset >
221+ < DxcActionIcon title = "Home" icon = "home" color = "neutral" onClick = { ( ) => console . log ( ) } />
64222 </ ExampleContainer >
65223 </ >
66224) ;
67225
68- type Story = StoryObj < typeof DxcActionIcon > ;
69-
70- export const Chromatic : Story = {
71- render : ActionIcon ,
72- } ;
73-
74226export const ActionIconTooltip : Story = {
75227 render : Tooltip ,
76228 play : async ( { canvasElement } ) => {
@@ -79,12 +231,3 @@ export const ActionIconTooltip: Story = {
79231 await userEvent . hover ( button ) ;
80232 } ,
81233} ;
82-
83- export const NestedActionIconTooltip : Story = {
84- render : NestedTooltip ,
85- play : async ( { canvasElement } ) => {
86- const canvas = within ( canvasElement ) ;
87- const button = await canvas . findByRole ( "button" ) ;
88- await userEvent . hover ( button ) ;
89- } ,
90- } ;
0 commit comments