Skip to content

Commit 7270aa5

Browse files
committed
Add text alignment option to counter
Allow overriding the automatic centering of wide counters with explicit left, center, centerRagged, or right alignment. Auto (default) preserves the existing behavior based on element width and section layout. REDMINE-21218
1 parent 2fea27e commit 7270aa5

6 files changed

Lines changed: 209 additions & 9 deletions

File tree

entry_types/scrolled/config/locales/de.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,14 @@ de:
332332
values:
333333
leading: Vor dem Betrag ($100)
334334
trailing: Nach dem Betrag (100%)
335+
textAlign:
336+
label: Textausrichtung
337+
blank: "(Automatisch)"
338+
values:
339+
left: Links
340+
center: Mitte
341+
centerRagged: Zentriert
342+
right: Rechts
335343
thousandsSeparators:
336344
label: "Tausendertrennzeichen anzeigen"
337345
inline_help: "Zum Beispiel 1.000, wenn Deutsch als Sprache für den Beitrag eingestellt ist."

entry_types/scrolled/config/locales/en.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,14 @@ en:
325325
values:
326326
leading: Leading ($100)
327327
trailing: Trailing (100%)
328+
textAlign:
329+
label: Text alignment
330+
blank: "(Auto)"
331+
values:
332+
left: Left
333+
center: Center
334+
centerRagged: Center (ragged)
335+
right: Right
328336
thousandsSeparators:
329337
label: "Display thousands separators"
330338
inline_help: "For example, 1,000 in stories with English language setting."

entry_types/scrolled/package/spec/contentElements/counter/Counter-spec.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {Counter} from 'contentElements/counter/Counter';
55
import {renderInContentElement} from 'pageflow-scrolled/testHelpers';
66
import {contentElementWidths} from 'pageflow-scrolled/frontend';
77

8+
import styles from 'contentElements/counter/Counter.module.css';
9+
810
import '@testing-library/jest-dom/extend-expect';
911
import 'support/toHaveScaleCategory';
1012
import 'support/toHaveColor';
@@ -180,4 +182,140 @@ describe('Counter', () => {
180182

181183
expect(numberWrapper.className).toContain('animation-fadeIn-active');
182184
});
185+
186+
describe('textAlign', () => {
187+
function renderCounterWithOptions(configuration, {width, sectionProps} = {}) {
188+
const baseConfiguration = {
189+
targetValue: 10,
190+
startValue: 0,
191+
countingSpeed: 'none',
192+
entranceAnimation: 'fadeIn',
193+
...configuration
194+
};
195+
196+
return renderInContentElement(
197+
<Counter
198+
configuration={baseConfiguration}
199+
contentElementId={5}
200+
contentElementWidth={width || contentElementWidths.md}
201+
sectionProps={sectionProps || {}}
202+
/>, {
203+
editorState: {isEditable: false}
204+
}
205+
);
206+
}
207+
208+
it('centers wide elements by default', () => {
209+
const {container} = renderCounterWithOptions({}, {width: contentElementWidths.xl});
210+
211+
expect(container.firstChild).toHaveClass(styles.center);
212+
});
213+
214+
it('does not center narrow elements by default', () => {
215+
const {container} = renderCounterWithOptions({}, {width: contentElementWidths.md});
216+
217+
expect(container.firstChild).not.toHaveClass(styles.center);
218+
});
219+
220+
it('applies centerRagged alignment from sectionProps layout by default', () => {
221+
const {container} = renderCounterWithOptions({}, {sectionProps: {layout: 'centerRagged'}});
222+
const wrapper = container.querySelector('[class*="wrapper"]');
223+
const numberWrapper = container.querySelector('[class*="number"]');
224+
const descriptionDiv = wrapper.lastChild;
225+
226+
expect(container.firstChild).toHaveClass(styles.center);
227+
expect(numberWrapper).toHaveClass(styles.numberCenter);
228+
expect(descriptionDiv).toHaveClass(styles.textCenter);
229+
});
230+
231+
it('applies left alignment when textAlign is left', () => {
232+
const {container} = renderCounterWithOptions(
233+
{textAlign: 'left'},
234+
{width: contentElementWidths.xl}
235+
);
236+
237+
expect(container.firstChild).toHaveClass(styles.left);
238+
expect(container.firstChild).not.toHaveClass(styles.center);
239+
});
240+
241+
it('applies right alignment when textAlign is right', () => {
242+
const {container} = renderCounterWithOptions(
243+
{textAlign: 'right'},
244+
{width: contentElementWidths.xl}
245+
);
246+
247+
expect(container.firstChild).toHaveClass(styles.right);
248+
});
249+
250+
it('applies center alignment when textAlign is center', () => {
251+
const {container} = renderCounterWithOptions(
252+
{textAlign: 'center'},
253+
{width: contentElementWidths.md}
254+
);
255+
256+
expect(container.firstChild).toHaveClass(styles.center);
257+
});
258+
259+
it('centers description text when textAlign is centerRagged', () => {
260+
const {container} = renderCounterWithOptions(
261+
{textAlign: 'centerRagged'},
262+
{width: contentElementWidths.md}
263+
);
264+
const wrapper = container.querySelector('[class*="wrapper"]');
265+
const descriptionDiv = wrapper.lastChild;
266+
267+
expect(descriptionDiv).toHaveClass(styles.textCenter);
268+
});
269+
270+
it('centers the number when textAlign is center', () => {
271+
const {container} = renderCounterWithOptions(
272+
{textAlign: 'center'},
273+
{width: contentElementWidths.md}
274+
);
275+
const numberWrapper = container.querySelector('[class*="number"]');
276+
277+
expect(numberWrapper).toHaveClass(styles.numberCenter);
278+
});
279+
280+
it('centers the number when textAlign is centerRagged', () => {
281+
const {container} = renderCounterWithOptions(
282+
{textAlign: 'centerRagged'},
283+
{width: contentElementWidths.md}
284+
);
285+
const numberWrapper = container.querySelector('[class*="number"]');
286+
287+
expect(numberWrapper).toHaveClass(styles.numberCenter);
288+
});
289+
290+
it('does not center the number when textAlign is left', () => {
291+
const {container} = renderCounterWithOptions(
292+
{textAlign: 'left'},
293+
{width: contentElementWidths.xl}
294+
);
295+
const numberWrapper = container.querySelector('[class*="number"]');
296+
297+
expect(numberWrapper).not.toHaveClass(styles.numberCenter);
298+
});
299+
300+
it('right aligns the number when textAlign is right', () => {
301+
const {container} = renderCounterWithOptions(
302+
{textAlign: 'right'},
303+
{width: contentElementWidths.md}
304+
);
305+
const numberWrapper = container.querySelector('[class*="number"]');
306+
307+
expect(numberWrapper).toHaveClass(styles.numberRight);
308+
});
309+
310+
it('right aligns description text when textAlign is right', () => {
311+
const {container} = renderCounterWithOptions(
312+
{textAlign: 'right'},
313+
{width: contentElementWidths.md}
314+
);
315+
const wrapper = container.querySelector('[class*="wrapper"]');
316+
const descriptionDiv = wrapper.lastChild;
317+
318+
expect(descriptionDiv).toHaveClass(styles.textRight);
319+
});
320+
});
183321
});

entry_types/scrolled/package/src/contentElements/counter/Counter.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,36 @@ export function Counter({configuration, contentElementId, contentElementWidth, s
115115
);
116116
}
117117

118+
const textAlign = configuration.textAlign ||
119+
(sectionProps.layout === 'centerRagged' ? 'centerRagged' : 'auto');
120+
121+
const wrapperAlignment = {
122+
auto: contentElementWidth > contentElementWidths.md ? 'center' : null,
123+
center: 'center',
124+
centerRagged: 'center',
125+
left: 'left',
126+
right: 'right'
127+
}[textAlign];
128+
129+
const numberAlignment = {
130+
center: 'numberCenter',
131+
centerRagged: 'numberCenter',
132+
right: 'numberRight'
133+
}[textAlign];
134+
135+
const descriptionAlignment = {
136+
centerRagged: 'textCenter',
137+
right: 'textRight'
138+
}[textAlign];
139+
118140
return (
119-
<div className={classNames(
120-
{[styles.center]: contentElementWidth > contentElementWidths.md}
121-
)}>
122-
<div className={classNames(
123-
styles.wrapper,
124-
{[styles.centerRagged]: sectionProps.layout === 'centerRagged'}
125-
)}>
141+
<div className={styles[wrapperAlignment]}>
142+
<div className={styles.wrapper}>
126143
<div
127144
className={classNames(
128145
`typography-counter-${configuration.typographyVariant}`,
129146
styles.number,
147+
styles[numberAlignment],
130148
styles[`animation-${configuration.entranceAnimation}`],
131149
{[styles[`animation-${configuration.entranceAnimation}-active`]]: animated
132150
})}
@@ -142,7 +160,8 @@ export function Counter({configuration, contentElementId, contentElementWidth, s
142160
</span>
143161
</Text>
144162
</div>
145-
<div style={{color: paletteColor(configuration.descriptionColor)}}>
163+
<div className={styles[descriptionAlignment]}
164+
style={{color: paletteColor(configuration.descriptionColor)}}>
146165
<EditableText value={configuration.description}
147166
contentElementId={contentElementId}
148167
className={styles.description}

entry_types/scrolled/package/src/contentElements/counter/Counter.module.css

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,40 @@
77
word-break: break-word;
88
}
99

10-
.centerRagged {
10+
.numberCenter {
1111
text-align: center;
1212
}
1313

14+
.numberRight {
15+
text-align: right;
16+
}
17+
1418
.center,
1519
.center .wrapper {
1620
display: flex;
1721
flex-direction: column;
1822
align-items: center;
1923
}
2024

25+
.left {
26+
text-align: left;
27+
}
28+
29+
.right,
30+
.right .wrapper {
31+
display: flex;
32+
flex-direction: column;
33+
align-items: flex-end;
34+
}
35+
36+
.textCenter {
37+
text-align: center;
38+
}
39+
40+
.textRight {
41+
text-align: right;
42+
}
43+
2144
.animation-fadeIn {
2245
opacity: 0;
2346
}

entry_types/scrolled/package/src/contentElements/counter/editor.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ editor.contentElementTypes.register('counter', {
121121
position: 'inline'
122122
})
123123
});
124+
this.input('textAlign', SelectInputView, {
125+
values: ['left', 'right', 'center', 'centerRagged'],
126+
includeBlank: true
127+
});
124128
this.group('ContentElementPosition', {entry});
125129
});
126130
}

0 commit comments

Comments
 (0)