@furystack/shades-common-components 10.0.27 → 10.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/esm/components/avatar.d.ts.map +1 -1
  2. package/esm/components/avatar.js +40 -6
  3. package/esm/components/avatar.js.map +1 -1
  4. package/esm/components/button.d.ts.map +1 -1
  5. package/esm/components/button.js +45 -32
  6. package/esm/components/button.js.map +1 -1
  7. package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
  8. package/esm/components/command-palette/command-palette-input.js +6 -3
  9. package/esm/components/command-palette/command-palette-input.js.map +1 -1
  10. package/esm/components/command-palette/command-palette-suggestion-list.d.ts.map +1 -1
  11. package/esm/components/command-palette/command-palette-suggestion-list.js +29 -10
  12. package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
  13. package/esm/components/command-palette/index.d.ts.map +1 -1
  14. package/esm/components/command-palette/index.js +35 -8
  15. package/esm/components/command-palette/index.js.map +1 -1
  16. package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
  17. package/esm/components/data-grid/data-grid-row.js +37 -9
  18. package/esm/components/data-grid/data-grid-row.js.map +1 -1
  19. package/esm/components/data-grid/data-grid.d.ts +2 -2
  20. package/esm/components/data-grid/data-grid.d.ts.map +1 -1
  21. package/esm/components/data-grid/data-grid.js +12 -5
  22. package/esm/components/data-grid/data-grid.js.map +1 -1
  23. package/esm/components/data-grid/header.js +3 -3
  24. package/esm/components/data-grid/header.js.map +1 -1
  25. package/esm/components/data-grid/selection-cell.d.ts.map +1 -1
  26. package/esm/components/data-grid/selection-cell.js +6 -1
  27. package/esm/components/data-grid/selection-cell.js.map +1 -1
  28. package/esm/components/grid.d.ts.map +1 -1
  29. package/esm/components/grid.js +25 -3
  30. package/esm/components/grid.js.map +1 -1
  31. package/esm/components/inputs/input.d.ts.map +1 -1
  32. package/esm/components/inputs/input.js +72 -22
  33. package/esm/components/inputs/input.js.map +1 -1
  34. package/esm/components/noty-list.d.ts.map +1 -1
  35. package/esm/components/noty-list.js +30 -8
  36. package/esm/components/noty-list.js.map +1 -1
  37. package/esm/components/suggest/index.d.ts.map +1 -1
  38. package/esm/components/suggest/index.js +35 -9
  39. package/esm/components/suggest/index.js.map +1 -1
  40. package/esm/components/suggest/suggest-input.d.ts.map +1 -1
  41. package/esm/components/suggest/suggest-input.js +6 -3
  42. package/esm/components/suggest/suggest-input.js.map +1 -1
  43. package/esm/components/suggest/suggestion-list.d.ts.map +1 -1
  44. package/esm/components/suggest/suggestion-list.js +30 -12
  45. package/esm/components/suggest/suggestion-list.js.map +1 -1
  46. package/esm/services/theme-provider-service.d.ts +1 -1
  47. package/esm/services/theme-provider-service.js +1 -1
  48. package/package.json +5 -5
  49. package/src/components/avatar.tsx +41 -6
  50. package/src/components/button.tsx +53 -40
  51. package/src/components/command-palette/command-palette-input.tsx +6 -2
  52. package/src/components/command-palette/command-palette-suggestion-list.tsx +29 -10
  53. package/src/components/command-palette/index.tsx +34 -7
  54. package/src/components/data-grid/data-grid-row.tsx +39 -10
  55. package/src/components/data-grid/data-grid.tsx +16 -7
  56. package/src/components/data-grid/header.tsx +3 -3
  57. package/src/components/data-grid/selection-cell.tsx +6 -0
  58. package/src/components/grid.tsx +32 -4
  59. package/src/components/inputs/input.tsx +99 -33
  60. package/src/components/noty-list.tsx +34 -8
  61. package/src/components/suggest/index.tsx +34 -8
  62. package/src/components/suggest/suggest-input.tsx +6 -2
  63. package/src/components/suggest/suggestion-list.tsx +30 -12
  64. package/src/services/theme-provider-service.ts +1 -1
@@ -1,6 +1,5 @@
1
1
  import type { ChildrenList } from '@furystack/shades'
2
2
  import { attachStyles, createComponent, Shade } from '@furystack/shades'
3
- import { ThemeProviderService } from '../../services/theme-provider-service.js'
4
3
  import type { CollectionService } from '../../services/collection-service.js'
5
4
  import type { DataRowCells } from './data-grid.js'
6
5
 
@@ -23,19 +22,27 @@ export const DataGridRow: <T, Column extends string>(
23
22
  ) => JSX.Element<any> = Shade({
24
23
  shadowDomName: 'shades-data-grid-row',
25
24
 
26
- render: ({ props, element, useObservable, injector }) => {
25
+ render: ({ props, element, useObservable }) => {
27
26
  const { entry, rowComponents, columns, service } = props
28
27
 
29
- const { theme } = injector.getInstance(ThemeProviderService)
30
-
31
28
  const attachSelectedStyles = (selection: any[]) => {
32
29
  if (selection.includes(entry)) {
33
30
  element.classList.add('selected')
34
- attachStyles(element, { style: props.selectedRowStyle || { backgroundColor: theme.background.default } })
31
+ attachStyles(element, {
32
+ style: props.selectedRowStyle || {
33
+ backgroundColor: 'rgba(128, 128, 128, 0.15)',
34
+ borderLeft: `3px solid var(--shades-theme-palette-primary-main)`,
35
+ },
36
+ })
35
37
  element.setAttribute('aria-selected', 'true')
36
38
  } else {
37
39
  element.classList.remove('selected')
38
- attachStyles(element, { style: props.unselectedRowStyle || { backgroundColor: 'transparent' } })
40
+ attachStyles(element, {
41
+ style: props.unselectedRowStyle || {
42
+ backgroundColor: 'transparent',
43
+ borderLeft: '3px solid transparent',
44
+ },
45
+ })
39
46
  element.setAttribute('aria-selected', 'false')
40
47
  }
41
48
  }
@@ -44,9 +51,10 @@ export const DataGridRow: <T, Column extends string>(
44
51
  if (newEntry === props.entry) {
45
52
  attachStyles(element, {
46
53
  style: props.focusedRowStyle || {
47
- boxShadow: `0 0 50px 1px rgba(255,255,255,0.2) inset, 0 0 35px 1px var(--shades-theme-palette-primary-main) inset, 2px 0px 5px 0px rgba(0,0,0,0.3)`,
48
- transition: 'box-shadow 0.1s ease-in-out',
49
- fontWeight: 'bolder',
54
+ boxShadow: `0 0 0 2px var(--shades-theme-palette-primary-main) inset, 0 2px 8px 0px rgba(0,0,0,0.15)`,
55
+ transition: 'box-shadow 0.15s ease-in-out, transform 0.15s ease-in-out',
56
+ fontWeight: '500',
57
+ transform: 'scale(1.002)',
50
58
  },
51
59
  })
52
60
 
@@ -75,6 +83,7 @@ export const DataGridRow: <T, Column extends string>(
75
83
  style: props.unfocusedRowStyle || {
76
84
  boxShadow: 'none',
77
85
  fontWeight: 'inherit',
86
+ transform: 'scale(1)',
78
87
  },
79
88
  })
80
89
  }
@@ -93,6 +102,8 @@ export const DataGridRow: <T, Column extends string>(
93
102
  element.style.display = 'table-row'
94
103
  element.style.cursor = 'default'
95
104
  element.style.userSelect = 'none'
105
+ element.style.transition = 'background-color 0.15s ease'
106
+
96
107
  if (selection?.includes(entry)) {
97
108
  element.setAttribute('aria-selected', 'true')
98
109
  element.classList.add('selected')
@@ -103,11 +114,29 @@ export const DataGridRow: <T, Column extends string>(
103
114
  }
104
115
  element.setAttribute('aria-selected', selection?.includes(entry).toString() || 'false')
105
116
 
117
+ // Add hover effect
118
+ element.onmouseenter = () => {
119
+ if (!selection?.includes(entry)) {
120
+ element.style.backgroundColor = 'rgba(128, 128, 128, 0.08)'
121
+ }
122
+ }
123
+ element.onmouseleave = () => {
124
+ if (!selection?.includes(entry)) {
125
+ element.style.backgroundColor = 'transparent'
126
+ }
127
+ }
128
+
106
129
  return (
107
130
  <>
108
131
  {columns.map((column) => (
109
132
  <td
110
- style={{ padding: '0.5em' }}
133
+ style={{
134
+ padding: '0.75em 1.2em',
135
+ borderBottom: '1px solid rgba(128, 128, 128, 0.1)',
136
+ verticalAlign: 'middle',
137
+ fontSize: '0.875rem',
138
+ lineHeight: '1.5',
139
+ }}
111
140
  onclick={(ev) => props.onRowClick?.(entry, ev)}
112
141
  ondblclick={(ev) => props.onRowDoubleClick?.(entry, ev)}
113
142
  >
@@ -1,14 +1,14 @@
1
+ import type { FindOptions } from '@furystack/core'
1
2
  import type { ChildrenList } from '@furystack/shades'
2
3
  import { createComponent, Shade } from '@furystack/shades'
4
+ import type { ObservableValue } from '@furystack/utils'
5
+ import { ClickAwayService } from '../../services/click-away-service.js'
3
6
  import type { CollectionService } from '../../services/collection-service.js'
7
+ import { ThemeProviderService } from '../../services/theme-provider-service.js'
4
8
  import type { GridProps } from '../grid.js'
5
- import { DataGridHeader } from './header.js'
6
9
  import { DataGridBody } from './body.js'
7
10
  import { DataGridFooter } from './footer.js'
8
- import { ThemeProviderService } from '../../services/theme-provider-service.js'
9
- import { ClickAwayService } from '../../services/click-away-service.js'
10
- import type { FindOptions } from '@furystack/core'
11
- import type { ObservableValue } from '@furystack/utils'
11
+ import { DataGridHeader } from './header.js'
12
12
 
13
13
  export type DataHeaderCells<Column extends string> = {
14
14
  [TKey in Column | 'default']?: (name: Column) => JSX.Element
@@ -101,14 +101,21 @@ export const DataGrid: <T, Column extends string>(
101
101
  backdropFilter: 'blur(12px) saturate(180%)',
102
102
  background: 'rgba(128,128,128,0.3)',
103
103
  color: theme.text.secondary,
104
- height: '38px',
104
+ height: '48px',
105
+ padding: '0 1.2em',
105
106
  alignItems: 'center',
106
107
  borderRadius: '2px',
107
108
  top: '2px',
108
109
  position: 'sticky',
109
110
  fontVariant: 'all-petite-caps',
111
+ fontSize: '0.875rem',
112
+ fontWeight: '600',
113
+ letterSpacing: '0.05em',
114
+ textAlign: 'left',
110
115
  zIndex: '1',
111
116
  boxShadow: 'rgba(0, 0, 0, 0.2) 1px 1px 1px 2px',
117
+ borderBottom: `2px solid rgba(128, 128, 128, 0.2)`,
118
+ borderRight: `1px solid rgba(128, 128, 128, 0.2)`,
112
119
  ...props.styles?.header,
113
120
  }
114
121
 
@@ -127,7 +134,9 @@ export const DataGrid: <T, Column extends string>(
127
134
  }}
128
135
  ariaMultiSelectable="true"
129
136
  >
130
- <table style={{ width: '100%', maxHeight: 'calc(100% - 4em)', position: 'relative' }}>
137
+ <table
138
+ style={{ width: '100%', maxHeight: 'calc(100% - 4em)', position: 'relative', borderCollapse: 'collapse' }}
139
+ >
131
140
  <thead>
132
141
  <tr>
133
142
  {props.columns.map((column) => {
@@ -222,14 +222,14 @@ export const DataGridHeader: <T, Column extends string>(
222
222
  height: '48px',
223
223
  justifyContent: 'space-between',
224
224
  alignItems: 'center',
225
- gap: '8px',
225
+ gap: '12px',
226
226
  overflow: 'hide',
227
227
  }}
228
228
  >
229
- <div style={{ paddingLeft: '0.5em' }}>{props.field}</div>
229
+ <div style={{ paddingLeft: '0', fontWeight: '600' }}>{props.field}</div>
230
230
  <div
231
231
  className="header-controls"
232
- style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', paddingRight: '0.5em' }}
232
+ style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', paddingRight: '0', gap: '4px' }}
233
233
  >
234
234
  <SearchButton
235
235
  onclick={() => {
@@ -18,6 +18,12 @@ export const SelectionCell = Shade<{ entry: any; service: CollectionService<any>
18
18
  }}
19
19
  type="checkbox"
20
20
  checked={isSelected}
21
+ style={{
22
+ cursor: 'pointer',
23
+ width: '18px',
24
+ height: '18px',
25
+ accentColor: 'var(--shades-theme-palette-primary-main)',
26
+ }}
21
27
  />
22
28
  )
23
29
  },
@@ -29,7 +29,7 @@ export const Grid: <T, Column extends string>(props: GridProps<T, Column>, child
29
29
  render: ({ props, injector }) => {
30
30
  const { theme } = injector.getInstance(ThemeProviderService)
31
31
  const headerStyle: Partial<CSSStyleDeclaration> = {
32
- padding: '0 0.51em',
32
+ padding: '1em 1.2em',
33
33
  backgroundColor: theme.background.paper,
34
34
  color: theme.text.secondary,
35
35
  borderRadius: '2px',
@@ -37,8 +37,24 @@ export const Grid: <T, Column extends string>(props: GridProps<T, Column>, child
37
37
  position: 'sticky',
38
38
  cursor: 'pointer',
39
39
  fontVariant: 'all-petite-caps',
40
+ fontSize: '0.875rem',
41
+ fontWeight: '600',
42
+ letterSpacing: '0.05em',
43
+ textAlign: 'left',
44
+ borderBottom: `2px solid ${theme.background.default}`,
45
+ borderRight: `1px solid rgba(128, 128, 128, 0.2)`,
40
46
  ...props.styles?.header,
41
47
  }
48
+
49
+ const cellStyle: Partial<CSSStyleDeclaration> = {
50
+ padding: '0.75em 1.2em',
51
+ borderBottom: `1px solid rgba(128, 128, 128, 0.15)`,
52
+ transition: 'background-color 0.2s ease',
53
+ fontSize: '0.875rem',
54
+ lineHeight: '1.5',
55
+ ...props.styles?.cell,
56
+ }
57
+
42
58
  return (
43
59
  <div
44
60
  className="shade-grid-wrapper"
@@ -49,7 +65,7 @@ export const Grid: <T, Column extends string>(props: GridProps<T, Column>, child
49
65
  overflow: 'auto',
50
66
  }}
51
67
  >
52
- <table style={{ width: '100%', position: 'relative' }}>
68
+ <table style={{ width: '100%', position: 'relative', borderCollapse: 'collapse' }}>
53
69
  <thead>
54
70
  <tr>
55
71
  {props.columns.map((column) => {
@@ -65,9 +81,21 @@ export const Grid: <T, Column extends string>(props: GridProps<T, Column>, child
65
81
  </thead>
66
82
  <tbody>
67
83
  {props.entries.map((entry) => (
68
- <tr>
84
+ <tr
85
+ style={{
86
+ transition: 'background-color 0.2s ease',
87
+ }}
88
+ onmouseenter={(e) => {
89
+ const target = e.currentTarget as HTMLElement
90
+ target.style.backgroundColor = `rgba(128, 128, 128, 0.08)`
91
+ }}
92
+ onmouseleave={(e) => {
93
+ const target = e.currentTarget as HTMLElement
94
+ target.style.backgroundColor = 'transparent'
95
+ }}
96
+ >
69
97
  {props.columns.map((column) => (
70
- <td style={props.styles?.cell}>
98
+ <td style={cellStyle}>
71
99
  {props.rowComponents?.[column]?.(entry, column) ||
72
100
  props.rowComponents?.default?.(entry, column) ||
73
101
  null}
@@ -85,47 +85,63 @@ const getLabelStyle = ({
85
85
  state: TextInputState
86
86
  validationResult?: InputValidationResult
87
87
  }): Partial<CSSStyleDeclaration> => {
88
+ const isError = state.validity?.valid === false || validationResult?.isValid === false
89
+ const isOutlined = props.variant === 'outlined'
90
+ const isContained = props.variant === 'contained'
91
+
88
92
  return {
89
93
  display: 'flex',
90
94
  flexDirection: 'column',
91
95
  alignItems: 'flex-start',
92
96
  justifyContent: 'space-between',
93
- fontSize: '10px',
97
+ fontSize: '11px',
98
+ fontWeight: '500',
99
+ letterSpacing: '0.01em',
94
100
  color: props.disabled
95
101
  ? themeProvider.theme.text.disabled
96
- : state.validity?.valid === false || validationResult?.isValid === false
102
+ : isError
97
103
  ? themeProvider.theme.palette.error.main
98
104
  : state.focused
99
- ? themeProvider.theme.text.primary
105
+ ? themeProvider.theme.palette[props.defaultColor || 'primary'].main
100
106
  : themeProvider.theme.text.secondary,
101
- marginBottom: '1em',
102
- padding: '1em',
103
- borderRadius: '5px',
104
- background:
105
- props.variant === 'contained'
106
- ? themeProvider
107
- .getRgbFromColorString(
108
- state.validity?.valid === false || validationResult?.isValid === false
109
- ? themeProvider.theme.palette.error.main
110
- : themeProvider.theme.palette[props.defaultColor || 'primary'].main,
111
- )
112
- .update('a', state.focused ? 0.1 : 0.2)
113
- .toString()
114
- : 'transparent',
115
- boxShadow:
116
- props.variant === 'outlined' || props.variant === 'contained'
117
- ? `0 0 0 1px ${
118
- state.validity?.valid === false || validationResult?.isValid === false
107
+ marginBottom: '1.25em',
108
+ padding: '12px 14px',
109
+ borderRadius: '8px',
110
+ background: isContained
111
+ ? themeProvider
112
+ .getRgbFromColorString(
113
+ isError
114
+ ? themeProvider.theme.palette.error.main
115
+ : themeProvider.theme.palette[props.defaultColor || 'primary'].main,
116
+ )
117
+ .update('a', state.focused ? 0.12 : 0.08)
118
+ .toString()
119
+ : 'transparent',
120
+ border:
121
+ isOutlined || isContained
122
+ ? `2px solid ${
123
+ isError
119
124
  ? themeProvider.theme.palette.error.main
120
125
  : state.focused
121
126
  ? themeProvider.theme.palette[props.defaultColor || 'primary'].main
122
- : themeProvider.theme.text.primary
127
+ : themeProvider.getRgbFromColorString(themeProvider.theme.text.secondary).update('a', 0.3).toString()
123
128
  }`
129
+ : `2px solid transparent`,
130
+ boxShadow:
131
+ state.focused && !props.disabled
132
+ ? `0 0 0 3px ${themeProvider
133
+ .getRgbFromColorString(
134
+ isError
135
+ ? themeProvider.theme.palette.error.main
136
+ : themeProvider.theme.palette[props.defaultColor || 'primary'].main,
137
+ )
138
+ .update('a', 0.15)
139
+ .toString()}`
124
140
  : 'none',
125
141
  filter: props.disabled ? 'grayscale(100%)' : 'none',
126
142
  opacity: props.disabled ? '0.5' : '1',
127
- transition:
128
- 'color 0.2s ease-in-out, filter 0.2s ease-in-out, opacity 0.2s ease-in-out, border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out',
143
+ transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
144
+ cursor: props.disabled ? 'not-allowed' : 'text',
129
145
  ...props.labelProps?.style,
130
146
  }
131
147
  }
@@ -212,12 +228,41 @@ export const Input = Shade<TextInputProps>({
212
228
  props.getHelperText?.({ state: newState, validationResult }) ||
213
229
  getDefaultMessagesForValidityState(newState.validity) ||
214
230
  ''
215
- helper?.replaceChildren(helperNode)
231
+ if (helper) {
232
+ helper.replaceChildren(helperNode)
233
+ attachStyles(helper, {
234
+ style: {
235
+ fontSize: '11px',
236
+ marginTop: '6px',
237
+ opacity: '0.85',
238
+ lineHeight: '1.4',
239
+ },
240
+ })
241
+ }
216
242
 
217
243
  const startIcon = element.querySelector<HTMLSpanElement>('span.startIcon')
218
- startIcon?.replaceChildren(props.getStartIcon?.({ state: newState, validationResult }) || '')
244
+ if (startIcon) {
245
+ startIcon.replaceChildren(props.getStartIcon?.({ state: newState, validationResult }) || '')
246
+ attachStyles(startIcon, {
247
+ style: {
248
+ display: 'flex',
249
+ alignItems: 'center',
250
+ fontSize: '16px',
251
+ },
252
+ })
253
+ }
254
+
219
255
  const endIcon = element.querySelector<HTMLSpanElement>('span.endIcon')
220
- endIcon?.replaceChildren(props.getEndIcon?.({ state: newState, validationResult }) || '')
256
+ if (endIcon) {
257
+ endIcon.replaceChildren(props.getEndIcon?.({ state: newState, validationResult }) || '')
258
+ attachStyles(endIcon, {
259
+ style: {
260
+ display: 'flex',
261
+ alignItems: 'center',
262
+ fontSize: '16px',
263
+ },
264
+ })
265
+ }
221
266
 
222
267
  if (injector.cachedSingletons.has(FormService)) {
223
268
  const formService = injector.getInstance(FormService)
@@ -245,9 +290,14 @@ export const Input = Shade<TextInputProps>({
245
290
  display: 'flex',
246
291
  alignItems: 'center',
247
292
  width: '100%',
293
+ gap: '8px',
248
294
  }}
249
295
  >
250
- {props.getStartIcon ? <span className="startIcon">{props.getStartIcon?.({ state })}</span> : null}
296
+ {props.getStartIcon ? (
297
+ <span className="startIcon" style={{ display: 'flex', alignItems: 'center', fontSize: '16px' }}>
298
+ {props.getStartIcon?.({ state })}
299
+ </span>
300
+ ) : null}
251
301
  <input
252
302
  oninvalid={(ev) => {
253
303
  ev.preventDefault()
@@ -275,20 +325,36 @@ export const Input = Shade<TextInputProps>({
275
325
  border: 'none',
276
326
  backgroundColor: 'transparent',
277
327
  outline: 'none',
278
- fontSize: '12px',
328
+ fontSize: '13px',
329
+ fontWeight: '400',
279
330
  width: '100%',
280
331
  textOverflow: 'ellipsis',
281
332
  padding: '0',
282
- marginTop: '0.6em',
283
- marginBottom: '0.4em',
333
+ marginTop: '8px',
334
+ marginBottom: '2px',
284
335
  flexGrow: '1',
336
+ lineHeight: '1.5',
285
337
  ...props.style,
286
338
  }}
287
339
  value={state.value}
288
340
  />
289
- {props.getEndIcon ? <span className="endIcon">{props.getEndIcon({ state })}</span> : null}
341
+ {props.getEndIcon ? (
342
+ <span className="endIcon" style={{ display: 'flex', alignItems: 'center', fontSize: '16px' }}>
343
+ {props.getEndIcon({ state })}
344
+ </span>
345
+ ) : null}
290
346
  </div>
291
- <span className="helperText">{props.getHelperText?.({ state })}</span>
347
+ <span
348
+ className="helperText"
349
+ style={{
350
+ fontSize: '11px',
351
+ marginTop: '6px',
352
+ opacity: '0.85',
353
+ lineHeight: '1.4',
354
+ }}
355
+ >
356
+ {props.getHelperText?.({ state })}
357
+ </span>
292
358
  </label>
293
359
  )
294
360
  },
@@ -42,12 +42,14 @@ export const NotyComponent = Shade<{ model: NotyModel; onDismiss: () => void }>(
42
42
  style: {
43
43
  margin: '8px',
44
44
  overflow: 'hidden',
45
- borderRadius: '6px',
46
- boxShadow: '1px 3px 6px rgba(0,0,0,0.3)',
47
- width: '300px',
45
+ borderRadius: '12px',
46
+ boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.08)',
47
+ width: '340px',
48
48
  display: 'flex',
49
49
  flexDirection: 'column',
50
50
  height: '0px',
51
+ border: '1px solid rgba(0, 0, 0, 0.1)',
52
+ backdropFilter: 'blur(10px)',
51
53
  },
52
54
  render: ({ props, injector, element }) => {
53
55
  const themeProvider = injector.getInstance(ThemeProviderService)
@@ -87,10 +89,10 @@ export const NotyComponent = Shade<{ model: NotyModel; onDismiss: () => void }>(
87
89
  display: 'flex',
88
90
  justifyContent: 'space-between',
89
91
  alignItems: 'center',
90
- padding: '0px 6px 0px 16px',
92
+ padding: '12px 12px 12px 20px',
91
93
  backgroundColor: colors.dark,
92
94
  color: headerTextColor,
93
- fontSize: '1.3em',
95
+ borderBottom: '1px solid rgba(0, 0, 0, 0.1)',
94
96
  }}
95
97
  >
96
98
  <h5
@@ -99,15 +101,30 @@ export const NotyComponent = Shade<{ model: NotyModel; onDismiss: () => void }>(
99
101
  overflow: 'hidden',
100
102
  textOverflow: 'ellipsis',
101
103
  margin: '0',
102
- fontSize: '.7em',
104
+ fontSize: '0.95em',
105
+ fontWeight: '600',
106
+ letterSpacing: '0.01em',
103
107
  }}
104
108
  title={props.model.title}
105
109
  >
106
110
  {props.model.title}
107
111
  </h5>
108
112
  <Button
109
- style={{ margin: '4px 0', padding: '0 4px', fontSize: '12px' }}
113
+ style={{
114
+ margin: '0',
115
+ padding: '4px 8px',
116
+ fontSize: '16px',
117
+ minWidth: '28px',
118
+ opacity: '0.8',
119
+ transition: 'opacity 0.2s ease',
120
+ }}
110
121
  className="dismissNoty"
122
+ onmouseenter={(e: MouseEvent) => {
123
+ ;(e.currentTarget as HTMLElement).style.opacity = '1'
124
+ }}
125
+ onmouseleave={(e: MouseEvent) => {
126
+ ;(e.currentTarget as HTMLElement).style.opacity = '0.8'
127
+ }}
111
128
  onclick={removeSelf}
112
129
  title="Close Notification"
113
130
  variant="contained"
@@ -116,7 +133,16 @@ export const NotyComponent = Shade<{ model: NotyModel; onDismiss: () => void }>(
116
133
 
117
134
  </Button>
118
135
  </div>
119
- <div style={{ padding: '16px 16px' }}>{props.model.body}</div>
136
+ <div
137
+ style={{
138
+ padding: '16px 20px 18px 20px',
139
+ fontSize: '0.9em',
140
+ lineHeight: '1.5',
141
+ fontWeight: '400',
142
+ }}
143
+ >
144
+ {props.model.body}
145
+ </div>
120
146
  </>
121
147
  )
122
148
  },
@@ -124,10 +124,15 @@ export const Suggest: <T>(props: SuggestProps<T>, children: ChildrenList) => JSX
124
124
  display: 'flex',
125
125
  alignItems: 'center',
126
126
  justifyContent: 'flex-end',
127
- padding: '0 1em',
128
- borderRadius: '5px',
127
+ padding: '0 1.25em',
128
+ borderRadius: '12px',
129
129
  position: 'relative',
130
- background: 'rgba(128,128,128,0.1)',
130
+ background: 'rgba(128,128,128,0.08)',
131
+ border: `1px solid ${manager.isOpened.getValue() ? 'rgba(128,128,128,0.3)' : 'rgba(128,128,128,0.15)'}`,
132
+ boxShadow: manager.isOpened.getValue()
133
+ ? '0 4px 12px rgba(0,0,0,0.15), 0 0 0 3px rgba(128,128,128,0.05)'
134
+ : '0 2px 4px rgba(0,0,0,0.05)',
135
+ transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
131
136
  ...props.style,
132
137
  }}
133
138
  >
@@ -135,9 +140,18 @@ export const Suggest: <T>(props: SuggestProps<T>, children: ChildrenList) => JSX
135
140
  className="term-icon"
136
141
  style={{
137
142
  cursor: 'pointer',
138
- color: '#aaa',
139
- fontWeight: 'bolder',
140
- textShadow: '0 0 1px #aaa',
143
+ color: theme.text.secondary,
144
+ fontWeight: '600',
145
+ fontSize: '0.95em',
146
+ transition: 'color 0.2s ease',
147
+ padding: '0.5em 0.75em 0.5em 0',
148
+ userSelect: 'none',
149
+ }}
150
+ onmouseenter={(ev) => {
151
+ ;(ev.target as HTMLElement).style.color = theme.text.primary
152
+ }}
153
+ onmouseleave={(ev) => {
154
+ ;(ev.target as HTMLElement).style.color = theme.text.secondary
141
155
  }}
142
156
  onclick={() => manager.isOpened.setValue(true)}
143
157
  >
@@ -162,14 +176,26 @@ export const Suggest: <T>(props: SuggestProps<T>, children: ChildrenList) => JSX
162
176
  <div
163
177
  className="close-suggestions"
164
178
  onclick={() => manager.isOpened.setValue(false)}
179
+ onmouseenter={(ev) => {
180
+ ;(ev.target as HTMLElement).style.background = 'rgba(255,255,255,0.15)'
181
+ ;(ev.target as HTMLElement).style.transform = 'scale(1.1)'
182
+ }}
183
+ onmouseleave={(ev) => {
184
+ ;(ev.target as HTMLElement).style.background = 'transparent'
185
+ ;(ev.target as HTMLElement).style.transform = 'scale(1)'
186
+ }}
165
187
  style={{
166
- width: '20px',
167
- height: '20px',
188
+ width: '24px',
189
+ height: '24px',
168
190
  opacity: manager.isOpened.getValue() ? '1' : '0',
169
191
  display: 'flex',
170
192
  alignItems: 'center',
171
193
  justifyContent: 'center',
172
194
  cursor: 'pointer',
195
+ borderRadius: '6px',
196
+ transition: 'all 0.2s ease',
197
+ fontSize: '14px',
198
+ color: theme.text.secondary,
173
199
  }}
174
200
  >
175
201
 
@@ -26,14 +26,18 @@ export const SuggestInput = Shade<{ manager: SuggestManager<any> }>({
26
26
  return (
27
27
  <input
28
28
  autofocus
29
+ placeholder="Type to search..."
29
30
  style={{
30
31
  color: theme.text.primary,
31
32
  outline: 'none',
32
- padding: '1em',
33
+ padding: '0.875em 0.5em',
33
34
  background: 'transparent',
34
35
  border: 'none',
35
36
  display: 'inline-flex',
36
- width: 'calc(100% - 2em)',
37
+ width: 'calc(100% - 1em)',
38
+ fontSize: '0.95em',
39
+ fontWeight: '400',
40
+ letterSpacing: '0.01em',
37
41
  }}
38
42
  />
39
43
  )