Skip to content

Commit 831d223

Browse files
committed
feat: give typescale responsive capabilities
1 parent 883fb30 commit 831d223

File tree

3 files changed

+130
-50
lines changed

3 files changed

+130
-50
lines changed

src/plugins/global-settings/typography/index.js

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,26 @@ import { GlobalTypographyStyles } from './editor-loader'
55
import TypographyPicker from './typography-picker'
66
import { getThemeStyles } from './get-theme-styles'
77
import FREE_FONT_PAIRS from './font-pairs.json'
8-
import { getAppliedTypeScale, cleanTypographyStyle } from './utils'
8+
import {
9+
getDevicePropertyKey,
10+
getAppliedTypeScale,
11+
cleanTypographyStyle,
12+
getTypographyTypeScale,
13+
} from './utils'
914

1015
/**
1116
* External dependencies
1217
*/
1318
import {
14-
PanelAdvancedSettings, AdvancedSelectControl, ControlSeparator, FontPairPicker, ProControlButton, AdvancedToggleControl,
19+
PanelAdvancedSettings,
20+
AdvancedSelectControl,
21+
ControlSeparator,
22+
FontPairPicker,
23+
ProControlButton,
24+
AdvancedToggleControl,
1525
} from '~stackable/components'
1626
import { fetchSettings } from '~stackable/util'
27+
import { useDeviceType } from '~stackable/hooks'
1728
import {
1829
i18n, isPro, showProNotice,
1930
} from 'stackable'
@@ -148,6 +159,7 @@ addFilter( 'stackable.global-settings.inspector', 'stackable/global-typography',
148159
const _useTypographyAsPresets = select( 'stackable/global-preset-controls.custom' )?.getUseTypographyAsPresets() ?? false
149160
return { useTypographyAsPresets: _useTypographyAsPresets }
150161
}, [] )
162+
const deviceType = useDeviceType()?.toLowerCase() || 'desktop'
151163

152164
const FONT_PAIRS = applyFilters( 'stackable.global-settings.typography.font-pairs.premium-font-pairs', FREE_FONT_PAIRS )
153165

@@ -157,7 +169,11 @@ addFilter( 'stackable.global-settings.inspector', 'stackable/global-typography',
157169
const [ customFontPairs, setCustomFontPairs ] = useState( [] )
158170
const [ selectedFontPairName, setSelectedFontPairName ] = useState( '' )
159171
const [ isEditingFontPair, setIsEditingFontPair ] = useState( false )
160-
const [ selectedTypeScale, setSelectedTypeScale ] = useState( 'none' )
172+
const [ selectedTypeScale, setSelectedTypeScale ] = useState( {
173+
desktop: 'none',
174+
tablet: 'none',
175+
mobile: 'none',
176+
} )
161177
const [ isApplyBodyToHTML, setIsApplyBodyToHTML ] = useState( false )
162178

163179
const fontPairContainerRef = useRef( null )
@@ -172,22 +188,21 @@ addFilter( 'stackable.global-settings.inspector', 'stackable/global-typography',
172188
setSelectedFontPairName( response.stackable_selected_font_pair || 'theme-heading-default/theme-body-default' )
173189
setIsApplyBodyToHTML( response.stackable_is_apply_body_to_html || false )
174190

175-
// Reversely compute the type scale from the font sizes
176-
let typeScale = _typographySettings?.h6?.fontSize
177-
if ( typeScale ) {
178-
const computedApplied = getAppliedTypeScale( typeScale ) ?? {}
179-
const tags = Object.keys( _typographySettings )
180-
for ( const tag of tags ) {
181-
// If font size mismatch, set typography scale to Custom
182-
if ( _typographySettings[ tag ]?.fontSize !== computedApplied[ tag ]?.fontSize ) {
183-
typeScale = 'custom'
184-
}
185-
}
186-
setSelectedTypeScale( typeScale )
187-
}
191+
// Reversely compute initial typescale for highlighting
192+
const typeScaleDesktop = getTypographyTypeScale( _typographySettings, 'desktop' )
193+
const typeScaleTablet = getTypographyTypeScale( _typographySettings, 'tablet' )
194+
const typeScaleMobile = getTypographyTypeScale( _typographySettings, 'mobile' )
195+
setSelectedTypeScale( {
196+
desktop: typeScaleDesktop, tablet: typeScaleTablet, mobile: typeScaleMobile,
197+
} )
188198
} )
189199
}, [] )
190200

201+
useEffect( () => {
202+
const typeScale = getTypographyTypeScale( typographySettings, deviceType )
203+
setSelectedTypeScale( prev => ( { ...prev, [ deviceType ]: typeScale } ) )
204+
}, [ deviceType, typographySettings ] )
205+
191206
useEffect( () => {
192207
// When typography styles are changed, trigger our editor style generator to update.
193208
// This also triggers updating presets with typography, and applying body font size to html.
@@ -269,26 +284,25 @@ addFilter( 'stackable.global-settings.inspector', 'stackable/global-typography',
269284
}
270285

271286
const updateTypeScale = value => {
272-
setSelectedTypeScale( value )
273-
274-
// If value is custom, do not do anything
275-
if ( value === 'custom ' ) {
276-
return
277-
}
278-
279-
// If value is none, reset the font sizes and units
280287
if ( value === 'none' ) {
281288
const selectors = TYPOGRAPHY_TAGS.map( tag => tag.selector )
282-
const newSettings = selectors.reduce( ( acc, selector, ) => {
283-
acc[ selector ] = { fontSize: '', fontSizeUnit: '' }
289+
const fontSizeKey = getDevicePropertyKey( 'fontSize', deviceType )
290+
const fontSizeUnitKey = getDevicePropertyKey( 'fontSizeUnit', deviceType )
291+
292+
const newSettings = selectors.reduce( ( acc, selector ) => {
293+
acc[ selector ] = {
294+
[ fontSizeKey ]: '',
295+
[ fontSizeUnitKey ]: '',
296+
}
284297
return acc
285298
}, {} )
299+
286300
changeStyles( newSettings )
287301
return
288302
}
289303

290304
// If value is valid type scale, apply to the styles
291-
const newSettings = getAppliedTypeScale( value )
305+
const newSettings = getAppliedTypeScale( value, deviceType )
292306
changeStyles( newSettings )
293307
}
294308

@@ -513,9 +527,12 @@ addFilter( 'stackable.global-settings.inspector', 'stackable/global-typography',
513527
<AdvancedSelectControl
514528
label={ __( 'Type Scale', i18n ) }
515529
options={ TYPE_SCALE }
516-
value={ selectedTypeScale }
530+
value={ selectedTypeScale[ deviceType ] }
517531
onChange={ updateTypeScale }
532+
responsive="all"
518533
default="none"
534+
hasTabletValue={ selectedTypeScale.tablet !== 'none' }
535+
hasMobileValue={ selectedTypeScale.mobile !== 'none' }
519536
/>
520537
{ TYPOGRAPHY_TAGS.map( ( {
521538
label, selector, help,
@@ -531,18 +548,9 @@ addFilter( 'stackable.global-settings.inspector', 'stackable/global-typography',
531548
isAllowReset={ getIsAllowReset( selector ) }
532549
onChange={ styles => {
533550
changeStyles( { [ selector ]: styles } )
534-
// Set typeScale to custom when editing font size or units
535-
if ( 'fontSize' in styles || 'fontSizeUnit' in styles ) {
536-
setSelectedTypeScale( 'custom' )
537-
}
538551
} }
539552
onReset={ () => {
540553
resetStyles( selector )
541-
// Set typeScale to custom when editing font size or units
542-
const styles = typographySettings[ selector ]
543-
if ( 'fontSize' in styles || 'fontSizeUnit' in styles ) {
544-
setSelectedTypeScale( 'custom' )
545-
}
546554
} }
547555
/>
548556
)

src/plugins/global-settings/typography/utils.js

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,50 @@
1+
export const getTypographyTypeScale = ( typographySettings, deviceType ) => {
2+
const fontSizeKey = getDevicePropertyKey( 'fontSize', deviceType )
3+
const fontSizeUnitKey = getDevicePropertyKey( 'fontSizeUnit', deviceType )
4+
const tags = Object.keys( typographySettings )
5+
6+
// Reversely compute the type scale from the font sizes
7+
let typeScale = typographySettings?.h6?.[ fontSizeKey ]
8+
typeScale = typeScale && parseFloat( typeScale ).toString()
9+
10+
if ( typeScale ) {
11+
const computedApplied = getAppliedTypeScale( typeScale, deviceType ) ?? {}
12+
for ( const tag of tags ) {
13+
// console.log( typographySettings[ tag ]?.[ fontSizeKey ], computedApplied[ tag ]?.[ fontSizeKey ] )
14+
// If font size mismatch, set typography scale to Custom
15+
if ( typographySettings[ tag ]?.[ fontSizeKey ] !== computedApplied[ tag ]?.[ fontSizeKey ] ||
16+
typographySettings[ tag ]?.[ fontSizeUnitKey ] !== computedApplied[ tag ]?.[ fontSizeUnitKey ]
17+
) {
18+
typeScale = 'custom'
19+
}
20+
}
21+
} else {
22+
typeScale = 'none'
23+
for ( const tag of tags ) {
24+
if ( typographySettings[ tag ]?.[ fontSizeKey ] ) {
25+
typeScale = 'custom'
26+
}
27+
}
28+
}
29+
return typeScale
30+
}
31+
32+
/**
33+
* Returns the property key adjusted for the given device type.
34+
*
35+
* @param {string} baseProperty - The base property name
36+
* @param {string} deviceType - The device type
37+
* @return {string} The adjusted property key based on the device type.
38+
*
39+
*/
40+
export const getDevicePropertyKey = ( baseProperty, deviceType ) => {
41+
deviceType = deviceType.toLowerCase()
42+
if ( deviceType && deviceType !== 'desktop' ) {
43+
return `${ deviceType }${ baseProperty.charAt( 0 ).toUpperCase() }${ baseProperty.slice( 1 ) }`
44+
}
45+
return baseProperty
46+
}
47+
148
/**
249
* Generates a typographic scale based on the given value.
350
*
@@ -6,26 +53,51 @@
653
* calculated using an exponential scale.
754
*
855
* @param {string|number} value - The base number to use for the typographic scale.
56+
* @param {string} deviceType - The device type
957
* @return {Object|undefined} An object mapping CSS selectors to their corresponding
1058
* font size settings. Returns `undefined` if input is invalid.
1159
*/
1260

13-
export const getAppliedTypeScale = value => {
61+
export const getAppliedTypeScale = ( value, deviceType = '' ) => {
1462
const typeScale = Number( value )
1563
if ( Number.isNaN( typeScale ) ) {
1664
return
1765
}
18-
return {
19-
h1: { fontSize: String( Math.pow( typeScale, 6 ).toFixed( 3 ) ), fontSizeUnit: 'rem' },
20-
h2: { fontSize: String( Math.pow( typeScale, 5 ).toFixed( 3 ) ), fontSizeUnit: 'rem' },
21-
h3: { fontSize: String( Math.pow( typeScale, 4 ).toFixed( 3 ) ), fontSizeUnit: 'rem' },
22-
h4: { fontSize: String( Math.pow( typeScale, 3 ).toFixed( 3 ) ), fontSizeUnit: 'rem' },
23-
h5: { fontSize: String( Math.pow( typeScale, 2 ).toFixed( 3 ) ), fontSizeUnit: 'rem' },
24-
h6: { fontSize: String( typeScale.toFixed( 3 ) ), fontSizeUnit: 'rem' },
25-
p: { fontSize: '1', fontSizeUnit: 'rem' },
26-
'.stk-subtitle': { fontSize: String( ( 1 / typeScale ).toFixed( 3 ) ), fontSizeUnit: 'rem' },
27-
'.stk-button__inner-text': { fontSize: '1', fontSizeUnit: 'rem' },
66+
67+
const headings = {
68+
h1: 6,
69+
h2: 5,
70+
h3: 4,
71+
h4: 3,
72+
h5: 2,
73+
h6: 1,
74+
p: 0,
75+
'.stk-subtitle': -1,
76+
'.stk-button__inner-text': 0,
2877
}
78+
79+
const result = {}
80+
81+
Object.entries( headings ).forEach( ( [ key, power ] ) => {
82+
let fontSize
83+
if ( power > 0 ) {
84+
fontSize = String( Math.pow( typeScale, power ).toFixed( 3 ) )
85+
} else if ( power === 0 ) {
86+
fontSize = '1'
87+
} else {
88+
fontSize = String( ( 1 / typeScale ).toFixed( 3 ) )
89+
}
90+
91+
const fontSizeKey = getDevicePropertyKey( 'fontSize', deviceType )
92+
const fontSizeUnitKey = getDevicePropertyKey( 'fontSizeUnit', deviceType )
93+
94+
result[ key ] = {
95+
[ fontSizeKey ]: fontSize,
96+
[ fontSizeUnitKey ]: 'rem',
97+
}
98+
} )
99+
100+
return result
29101
}
30102

31103
/**

src/util/typography/styles.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ export const createTypographyStyles = ( attrNameTemplate = '%s', screen = 'deskt
3939
const mobileFontSize = getValue( 'MobileFontSize' )
4040

4141
const desktopFontSizeUnit = isCSSVarValue( desktopFontSize ) ? '' : getValue( 'FontSizeUnit' ) || 'px'
42-
const tabletFontSizeUnit = isCSSVarValue( tabletFontSize ) ? '' : getValue( 'FontSizeUnit' ) || 'px'
43-
const mobileFontSizeUnit = isCSSVarValue( mobileFontSize ) ? '' : getValue( 'FontSizeUnit' ) || 'px'
42+
const tabletFontSizeUnit = isCSSVarValue( tabletFontSize ) ? '' : getValue( 'TabletFontSizeUnit' ) || 'px'
43+
const mobileFontSizeUnit = isCSSVarValue( mobileFontSize ) ? '' : getValue( 'MobileFontSizeUnit' ) || 'px'
4444

4545
if ( screen !== 'tablet' && screen !== 'mobile' ) { // Desktop.
4646
styles = {

0 commit comments

Comments
 (0)