Skip to content

Commit 67e31ba

Browse files
authored
Merge pull request #664 from kilianc/master
feat: add support for space separated cssClasses in settings
2 parents 1ad2ec9 + 420f451 commit 67e31ba

File tree

5 files changed

+187
-128
lines changed

5 files changed

+187
-128
lines changed

src/docs/pages/settings/classes.vue

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ export default defineComponent({
4949
<div id="cssClasses" class="content">
5050
<h2 class="header">cssClasses</h2>
5151
<p>
52-
The cssClasses setting allows you to override SlimSelect's default CSS classes with your own custom classes. This
53-
gives you complete control over the styling of different parts of the dropdown, enabling you to match your
54-
application's design system perfectly.
52+
The cssClasses setting allows you to add custom CSS classes to SlimSelect's default classes. Your custom classes
53+
are appended to the default SlimSelect classes (like 'ss-main', 'ss-option', etc.), giving you the ability to add
54+
additional styling without breaking SlimSelect's core functionality.
5555
</p>
5656
<p>
57-
You can customize classes for various elements like options, the main container, search input, and more. This is
58-
particularly useful when you need to apply specific styling that integrates seamlessly with your existing CSS
59-
framework or design requirements.
57+
You can add classes to various elements like options, the main container, search input, and more. The default
58+
classes are always preserved to ensure proper functionality, while your custom classes provide additional styling
59+
hooks. This allows you to integrate seamlessly with CSS frameworks like Tailwind CSS or your own design system.
6060
</p>
6161

6262
<div class="row">
@@ -87,7 +87,8 @@ export default defineComponent({
8787
new SlimSelect({
8888
select: '#primary-select',
8989
cssClasses: {
90-
option: "primary-option"
90+
option: "primary-option" // Appended to 'ss-option', resulting in class="ss-option primary-option"
91+
}
9192
})
9293
</pre>
9394
</ShikiStyle>

src/slim-select/classes.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ describe('CssClasses module', () => {
5959
})
6060
})
6161

62-
test('classes can be overwritten via the constructor', () => {
62+
test('classes can be added via the constructor', () => {
6363
const classesWithOverride = JSON.parse(JSON.stringify(defaultClasses))
64-
classesWithOverride['main'] = 'new-main'
65-
classesWithOverride['mainOpen'] = 'new-open'
64+
classesWithOverride['main'] = 'ss-main new-main'
65+
classesWithOverride['mainOpen'] = 'ss-open new-open'
6666

6767
// Convert to unknown and then to custom object to prevent TS from throwing errors
6868
const classes = new CssClasses({ main: 'new-main', mainOpen: 'new-open' }) as unknown as { [key: string]: string }

src/slim-select/classes.ts

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -65,47 +65,53 @@ export default class CssClasses {
6565
classes = {}
6666
}
6767

68-
this.main = classes.main || 'ss-main'
69-
this.placeholder = classes.placeholder || 'ss-placeholder'
70-
this.values = classes.values || 'ss-values'
71-
this.single = classes.single || 'ss-single'
72-
this.max = classes.max || 'ss-max'
73-
this.value = classes.value || 'ss-value'
74-
this.valueText = classes.valueText || 'ss-value-text'
75-
this.valueDelete = classes.valueDelete || 'ss-value-delete'
76-
this.valueOut = classes.valueOut || 'ss-value-out'
68+
let join = (a = '', b = '') => `${a} ${b}`.trim()
7769

78-
this.deselect = classes.deselect || 'ss-deselect'
70+
this.main = join('ss-main', classes.main)
71+
this.placeholder = join('ss-placeholder', classes.placeholder)
72+
this.values = join('ss-values', classes.values)
73+
this.single = join('ss-single', classes.single)
74+
this.max = join('ss-max', classes.max)
75+
this.value = join('ss-value', classes.value)
76+
this.valueText = join('ss-value-text', classes.valueText)
77+
this.valueDelete = join('ss-value-delete', classes.valueDelete)
78+
this.valueOut = join('ss-value-out', classes.valueOut)
79+
80+
this.deselect = join('ss-deselect', classes.deselect)
7981
this.deselectPath = classes.deselectPath || 'M10,10 L90,90 M10,90 L90,10'
80-
this.arrow = classes.arrow || 'ss-arrow'
82+
this.arrow = join('ss-arrow', classes.arrow)
8183
this.arrowClose = classes.arrowClose || 'M10,30 L50,70 L90,30'
8284
this.arrowOpen = classes.arrowOpen || 'M10,70 L50,30 L90,70'
83-
this.content = classes.content || 'ss-content'
84-
this.contentOpen = classes.contentOpen || 'ss-open'
85-
this.dirAbove = classes.dirAbove || 'ss-dir-above'
86-
this.dirBelow = classes.dirBelow || 'ss-dir-below'
87-
this.search = classes.search || 'ss-search'
88-
this.searchHighlighter = classes.searchHighlighter || 'ss-search-highlight'
89-
this.searching = classes.searching || 'ss-searching'
90-
this.addable = classes.addable || 'ss-addable'
85+
this.content = join('ss-content', classes.content)
86+
this.contentOpen = join('ss-open', classes.contentOpen)
87+
this.dirAbove = join('ss-dir-above', classes.dirAbove)
88+
this.dirBelow = join('ss-dir-below', classes.dirBelow)
89+
this.search = join('ss-search', classes.search)
90+
this.searchHighlighter = join('ss-search-highlight', classes.searchHighlighter)
91+
this.searching = join('ss-searching', classes.searching)
92+
this.addable = join('ss-addable', classes.addable)
9193
this.addablePath = classes.addablePath || 'M50,10 L50,90 M10,50 L90,50'
92-
this.list = classes.list || 'ss-list'
93-
this.optgroup = classes.optgroup || 'ss-optgroup'
94-
this.optgroupLabel = classes.optgroupLabel || 'ss-optgroup-label'
95-
this.optgroupLabelText = classes.optgroupLabelText || 'ss-optgroup-label-text'
96-
this.optgroupActions = classes.optgroupActions || 'ss-optgroup-actions'
97-
this.optgroupSelectAll = classes.optgroupSelectAll || 'ss-selectall'
94+
this.list = join('ss-list', classes.list)
95+
this.optgroup = join('ss-optgroup', classes.optgroup)
96+
this.optgroupLabel = join('ss-optgroup-label', classes.optgroupLabel)
97+
this.optgroupLabelText = join('ss-optgroup-label-text', classes.optgroupLabelText)
98+
this.optgroupActions = join('ss-optgroup-actions', classes.optgroupActions)
99+
this.optgroupSelectAll = join('ss-selectall', classes.optgroupSelectAll)
98100
this.optgroupSelectAllBox = classes.optgroupSelectAllBox || 'M60,10 L10,10 L10,90 L90,90 L90,50'
99101
this.optgroupSelectAllCheck = classes.optgroupSelectAllCheck || 'M30,45 L50,70 L90,10'
100-
this.optgroupClosable = classes.optgroupClosable || 'ss-closable'
101-
this.option = classes.option || 'ss-option'
102+
this.optgroupClosable = join('ss-closable', classes.optgroupClosable)
103+
this.option = join('ss-option', classes.option)
102104
this.optionDelete = classes.optionDelete || 'M10,10 L90,90 M10,90 L90,10'
103-
this.highlighted = classes.highlighted || 'ss-highlighted'
104-
this.mainOpen = classes.mainOpen || 'ss-open'
105-
this.close = classes.close || 'ss-close'
106-
this.selected = classes.selected || 'ss-selected'
107-
this.error = classes.error || 'ss-error'
108-
this.disabled = classes.disabled || 'ss-disabled'
109-
this.hide = classes.hide || 'ss-hide'
105+
this.highlighted = join('ss-highlighted', classes.highlighted)
106+
this.mainOpen = join('ss-open', classes.mainOpen)
107+
this.close = join('ss-close', classes.close)
108+
this.selected = join('ss-selected', classes.selected)
109+
this.error = join('ss-error', classes.error)
110+
this.disabled = join('ss-disabled', classes.disabled)
111+
this.hide = join('ss-hide', classes.hide)
112+
}
113+
114+
public getFirst(name: keyof Omit<CssClasses, 'getFirst'>): string {
115+
return this[name].split(' ')[0]
110116
}
111117
}

src/slim-select/index.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,4 +1300,23 @@ describe('SlimSelect Module', () => {
13001300
slim.destroy()
13011301
})
13021302
})
1303+
1304+
describe('cssClasses with space-separated strings', () => {
1305+
test('space-separated cssClasses are applied as individual classes', () => {
1306+
document.body.innerHTML = '<select id="test"><option>Test</option></select>'
1307+
1308+
const slim = new SlimSelect({
1309+
select: '#test',
1310+
cssClasses: {
1311+
main: 'class1 class2'
1312+
}
1313+
})
1314+
1315+
expect(slim.render.main.main.classList.contains('ss-main')).toBe(true)
1316+
expect(slim.render.main.main.classList.contains('class1')).toBe(true)
1317+
expect(slim.render.main.main.classList.contains('class2')).toBe(true)
1318+
1319+
slim.destroy()
1320+
})
1321+
})
13031322
})

0 commit comments

Comments
 (0)