webcoreui 0.0.11 → 0.1.0

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 (141) hide show
  1. package/README.md +42 -11
  2. package/astro.d.ts +4 -0
  3. package/astro.js +4 -0
  4. package/components/Accordion/Accordion.astro +10 -8
  5. package/components/Accordion/Accordion.svelte +8 -8
  6. package/components/Accordion/Accordion.tsx +7 -6
  7. package/components/Accordion/accordion.module.scss +65 -0
  8. package/components/Alert/Alert.astro +11 -7
  9. package/components/Alert/Alert.svelte +9 -7
  10. package/components/Alert/Alert.tsx +11 -7
  11. package/components/Alert/alert.module.scss +51 -0
  12. package/components/Alert/alert.ts +3 -1
  13. package/components/Avatar/Avatar.astro +4 -4
  14. package/components/Avatar/Avatar.svelte +13 -7
  15. package/components/Avatar/Avatar.tsx +11 -9
  16. package/components/Avatar/{avatar.scss → avatar.module.scss} +11 -8
  17. package/components/Badge/Badge.astro +8 -8
  18. package/components/Badge/Badge.svelte +25 -13
  19. package/components/Badge/Badge.tsx +26 -8
  20. package/components/Badge/badge.module.scss +86 -0
  21. package/components/Badge/badge.ts +8 -1
  22. package/components/Button/Button.astro +9 -7
  23. package/components/Button/Button.svelte +13 -11
  24. package/components/Button/Button.tsx +10 -8
  25. package/components/Button/button.module.scss +87 -0
  26. package/components/Button/button.ts +6 -2
  27. package/components/Card/Card.astro +7 -15
  28. package/components/Card/Card.svelte +16 -13
  29. package/components/Card/Card.tsx +15 -11
  30. package/components/Card/card.module.scss +38 -0
  31. package/components/Checkbox/Checkbox.astro +10 -10
  32. package/components/Checkbox/Checkbox.svelte +19 -18
  33. package/components/Checkbox/Checkbox.tsx +12 -11
  34. package/components/Checkbox/checkbox.module.scss +70 -0
  35. package/components/Checkbox/checkbox.ts +5 -1
  36. package/components/ConditionalWrapper/ConditionalWrapper.svelte +1 -1
  37. package/components/Icon/Icon.astro +2 -2
  38. package/components/Icon/Icon.svelte +1 -8
  39. package/components/Icon/Icon.tsx +1 -8
  40. package/components/Icon/map.ts +23 -0
  41. package/components/Input/Input.astro +50 -52
  42. package/components/Input/Input.svelte +52 -52
  43. package/components/Input/Input.tsx +59 -59
  44. package/components/Input/input.module.scss +79 -0
  45. package/components/Input/input.ts +8 -2
  46. package/components/Menu/Menu.astro +107 -0
  47. package/components/Menu/Menu.svelte +88 -0
  48. package/components/Menu/Menu.tsx +107 -0
  49. package/components/Menu/menu.module.scss +141 -0
  50. package/components/Menu/menu.ts +21 -0
  51. package/components/Progress/Progress.astro +42 -40
  52. package/components/Progress/Progress.svelte +40 -38
  53. package/components/Progress/Progress.tsx +48 -47
  54. package/components/Progress/progress.module.scss +70 -0
  55. package/components/Radio/Radio.astro +57 -57
  56. package/components/Radio/Radio.svelte +58 -56
  57. package/components/Radio/Radio.tsx +69 -68
  58. package/components/Radio/radio.module.scss +84 -0
  59. package/components/Radio/radio.ts +4 -0
  60. package/components/Rating/Rating.astro +13 -10
  61. package/components/Rating/Rating.svelte +15 -15
  62. package/components/Rating/Rating.tsx +22 -11
  63. package/components/Rating/rating.module.scss +45 -0
  64. package/components/Rating/rating.ts +1 -1
  65. package/components/Spinner/Spinner.astro +44 -42
  66. package/components/Spinner/Spinner.svelte +40 -38
  67. package/components/Spinner/Spinner.tsx +45 -44
  68. package/components/Spinner/{spinner.scss → spinner.module.scss} +50 -41
  69. package/components/Switch/Switch.astro +13 -11
  70. package/components/Switch/Switch.svelte +26 -24
  71. package/components/Switch/Switch.tsx +14 -12
  72. package/components/Switch/switch.module.scss +82 -0
  73. package/components/Switch/switch.ts +8 -4
  74. package/components/Table/Table.astro +60 -60
  75. package/components/Table/Table.svelte +56 -54
  76. package/components/Table/Table.tsx +64 -63
  77. package/components/Table/{table.scss → table.module.scss} +60 -65
  78. package/components/Tabs/Tabs.astro +76 -76
  79. package/components/Tabs/Tabs.svelte +56 -54
  80. package/components/Tabs/Tabs.tsx +70 -69
  81. package/components/Tabs/tabs.module.scss +125 -0
  82. package/components/ThemeSwitcher/ThemeSwitcher.astro +106 -0
  83. package/components/ThemeSwitcher/ThemeSwitcher.svelte +76 -0
  84. package/components/ThemeSwitcher/ThemeSwitcher.tsx +89 -0
  85. package/components/ThemeSwitcher/themeswitcher.module.scss +76 -0
  86. package/components/ThemeSwitcher/themeswitcher.ts +13 -0
  87. package/components/Timeline/Timeline.astro +36 -34
  88. package/components/Timeline/Timeline.svelte +32 -30
  89. package/components/Timeline/Timeline.tsx +38 -37
  90. package/components/Timeline/{timeline.scss → timeline.module.scss} +76 -71
  91. package/components/TimelineItem/TimelineItem.astro +27 -26
  92. package/components/TimelineItem/TimelineItem.svelte +24 -22
  93. package/components/TimelineItem/TimelineItem.tsx +33 -32
  94. package/components/TimelineItem/timelineitem.module.scss +29 -0
  95. package/components/Toast/Toast.astro +41 -30
  96. package/components/Toast/Toast.svelte +32 -21
  97. package/components/Toast/Toast.tsx +38 -28
  98. package/components/Toast/toast.module.scss +40 -0
  99. package/components/Toast/toast.ts +8 -6
  100. package/icons/moon.svg +3 -0
  101. package/icons/sun.svg +3 -0
  102. package/icons.d.ts +11 -0
  103. package/icons.js +9 -0
  104. package/index.js +3 -0
  105. package/package.json +5 -1
  106. package/react.d.ts +4 -0
  107. package/react.js +4 -0
  108. package/scss/config/color-palette.scss +23 -0
  109. package/scss/config/css-values.scss +44 -0
  110. package/scss/config/layout.scss +41 -0
  111. package/scss/config/mixins.scss +395 -9
  112. package/scss/config/typography.scss +66 -0
  113. package/scss/config.scss +6 -1
  114. package/scss/global/elements.scss +22 -2
  115. package/scss/global/scrollbar.scss +24 -0
  116. package/scss/global/theme.scss +140 -0
  117. package/scss/global/tooltip.scss +47 -39
  118. package/scss/global/utility.scss +33 -4
  119. package/scss/global.scss +2 -1
  120. package/scss/resets.scss +64 -11
  121. package/scss/setup.scss +25 -31
  122. package/svelte.d.ts +16 -12
  123. package/svelte.js +4 -0
  124. package/utils/classNames.ts +4 -0
  125. package/utils/cookies.ts +28 -0
  126. package/utils/event.ts +17 -0
  127. package/utils/toast.ts +15 -11
  128. package/components/Accordion/accordion.scss +0 -63
  129. package/components/Alert/alert.scss +0 -53
  130. package/components/Badge/badge.scss +0 -85
  131. package/components/Button/button.scss +0 -91
  132. package/components/Card/card.scss +0 -37
  133. package/components/Checkbox/checkbox.scss +0 -85
  134. package/components/Input/input.scss +0 -83
  135. package/components/Progress/progress.scss +0 -66
  136. package/components/Radio/radio.scss +0 -92
  137. package/components/Rating/rating.scss +0 -37
  138. package/components/Switch/switch.scss +0 -84
  139. package/components/Tabs/tabs.scss +0 -134
  140. package/components/TimelineItem/timelineitem.scss +0 -31
  141. package/components/Toast/toast.scss +0 -43
@@ -1,69 +1,70 @@
1
- import React, { useState, useRef } from 'react'
2
- import type { ReactTabsProps } from './tabs'
3
-
4
- import './tabs.scss'
5
-
6
- const Tabs = ({
7
- items,
8
- theme,
9
- vertical,
10
- even,
11
- className,
12
- children
13
- }: ReactTabsProps) => {
14
- const tabContainer = useRef<HTMLDivElement>(null)
15
- const [active, setActive] = useState('')
16
-
17
- const classes = [
18
- 'w-tabs',
19
- theme && theme,
20
- vertical && 'vertical',
21
- even && 'even',
22
- className
23
- ].filter(Boolean).join(' ')
24
-
25
- const setTab = (tab: string) => {
26
- const tabs = tabContainer.current!.querySelectorAll('[data-tab]')
27
-
28
- Array.from(tabs).forEach((item: any) => {
29
- item.dataset.active = false
30
-
31
- if (item.dataset.tab === tab) {
32
- item.dataset.active = true
33
- }
34
- })
35
-
36
- setActive(tab)
37
- }
38
-
39
- const isActive = (item: ReactTabsProps['items'][0]) => {
40
- if (!active) {
41
- return item.active ? 'active' : undefined
42
- }
43
-
44
- return active === item.value ? 'active' : undefined
45
- }
46
-
47
- return (
48
- <section className={classes}>
49
- <div className="tabs-wrapper">
50
- <div className="tabs">
51
- {items.map((item, index) => (
52
- <button
53
- key={index}
54
- disabled={item.disabled}
55
- dangerouslySetInnerHTML={{ __html: item.label }}
56
- onClick={() => setTab(item.value)}
57
- className={isActive(item)}
58
- />
59
- ))}
60
- </div>
61
- </div>
62
- <div className="tab-content" ref={tabContainer}>
63
- {children}
64
- </div>
65
- </section>
66
- )
67
- }
68
-
69
- export default Tabs
1
+ import React, { useState, useRef } from 'react'
2
+ import type { ReactTabsProps } from './tabs'
3
+
4
+ import styles from './tabs.module.scss'
5
+ import { classNames } from '../../utils/classNames'
6
+
7
+ const Tabs = ({
8
+ items,
9
+ theme,
10
+ vertical,
11
+ even,
12
+ className,
13
+ children
14
+ }: ReactTabsProps) => {
15
+ const tabContainer = useRef<HTMLDivElement>(null)
16
+ const [active, setActive] = useState('')
17
+
18
+ const classes = classNames([
19
+ styles.tabs,
20
+ theme && styles[theme],
21
+ vertical && styles.vertical,
22
+ even && styles.even,
23
+ className
24
+ ])
25
+
26
+ const setTab = (tab: string) => {
27
+ const tabs = tabContainer.current!.querySelectorAll('[data-tab]')
28
+
29
+ Array.from(tabs).forEach((item: any) => {
30
+ item.dataset.active = false
31
+
32
+ if (item.dataset.tab === tab) {
33
+ item.dataset.active = true
34
+ }
35
+ })
36
+
37
+ setActive(tab)
38
+ }
39
+
40
+ const isActive = (item: ReactTabsProps['items'][0]) => {
41
+ if (!active) {
42
+ return item.active ? 'true' : undefined
43
+ }
44
+
45
+ return active === item.value ? 'true' : undefined
46
+ }
47
+
48
+ return (
49
+ <section className={classes}>
50
+ <div className={styles.wrapper}>
51
+ <div className={styles.items}>
52
+ {items.map((item, index) => (
53
+ <button
54
+ key={index}
55
+ disabled={item.disabled}
56
+ dangerouslySetInnerHTML={{ __html: item.label }}
57
+ onClick={() => setTab(item.value)}
58
+ data-active={isActive(item)}
59
+ />
60
+ ))}
61
+ </div>
62
+ </div>
63
+ <div className={styles.content} ref={tabContainer}>
64
+ {children}
65
+ </div>
66
+ </section>
67
+ )
68
+ }
69
+
70
+ export default Tabs
@@ -0,0 +1,125 @@
1
+ @use '../../scss/config.scss' as *;
2
+
3
+ .tabs {
4
+ &.boxed .items,
5
+ &.outline .items {
6
+ @include background(primary-50);
7
+ @include border-radius(md);
8
+ @include spacing(p-xs);
9
+ @include size(wmax-content);
10
+
11
+ button {
12
+ @include transition();
13
+ @include border-radius(md);
14
+ @include spacing(p-sm);
15
+
16
+ &[data-active="true"] {
17
+ @include border(0);
18
+ @include background(primary-70);
19
+ padding-bottom: 10px;
20
+ }
21
+ }
22
+ }
23
+
24
+ &.outline .items {
25
+ @include background(transparent);
26
+ @include border(primary-50);
27
+
28
+ button {
29
+ margin-bottom: 0;
30
+
31
+ &[data-active="true"] {
32
+ @include background(primary-50);
33
+ }
34
+ }
35
+ }
36
+
37
+ &.even .items button {
38
+ @include layout(h-center);
39
+ flex: 1;
40
+ }
41
+
42
+ &.vertical {
43
+ @include layout(flex, default);
44
+
45
+ &.boxed .items button,
46
+ &.outline .items button {
47
+ @include border(bottom, 0);
48
+ }
49
+
50
+ .items {
51
+ @include layout(column, xs);
52
+
53
+ button {
54
+ @include spacing(p-sm);
55
+ @include border(2px, bottom, primary-50);
56
+
57
+ &[data-active="true"] {
58
+ padding-bottom: 10px;
59
+ }
60
+ }
61
+ }
62
+
63
+ .content {
64
+ @include spacing(m0);
65
+ }
66
+ }
67
+
68
+ .wrapper {
69
+ @include visibility(auto);
70
+ }
71
+
72
+ .items {
73
+ @include border(2px, bottom, primary-50);
74
+ @include layout(flex, sm);
75
+
76
+ button {
77
+ @include transition(color);
78
+ @include background(transparent);
79
+ @include typography(md, primary-20);
80
+ @include border(0);
81
+ @include spacing(p-md);
82
+ @include layout(flex, v-center, sm);
83
+
84
+ cursor: pointer;
85
+ flex-shrink: 0;
86
+
87
+ svg {
88
+ @include size(20px);
89
+ pointer-events: none;
90
+ }
91
+
92
+ &[disabled] {
93
+ @include typography(primary-30);
94
+ cursor: no-drop;
95
+ }
96
+
97
+ &[data-active="true"] {
98
+ @include typography(primary);
99
+ @include border(2px, bottom, primary);
100
+
101
+ padding-bottom: 13px;
102
+ }
103
+ }
104
+ }
105
+
106
+ .content {
107
+ @include spacing(mt-default);
108
+ }
109
+
110
+ [data-tab] {
111
+ @include visibility(none);
112
+
113
+ &[data-active="true"] {
114
+ @include visibility(block);
115
+ }
116
+ }
117
+ }
118
+
119
+ @include media('xs') {
120
+ .tabs {
121
+ &.even .items {
122
+ @include size(wauto);
123
+ }
124
+ }
125
+ }
@@ -0,0 +1,106 @@
1
+ ---
2
+ import type { ThemeSwitcherProps } from './themeswitcher'
3
+ import styles from './themeswitcher.module.scss'
4
+
5
+ interface Props extends ThemeSwitcherProps {}
6
+
7
+ const {
8
+ themes,
9
+ toggle,
10
+ size,
11
+ className
12
+ } = Astro.props
13
+
14
+ const classes = [
15
+ styles.switcher,
16
+ toggle && styles.toggle,
17
+ className
18
+ ]
19
+
20
+ const primaryTheme = themes[Object.keys(themes)[0]]
21
+ const secondaryTheme = themes[Object.keys(themes)[1]]
22
+ const useIcons = Astro.slots.has('primaryIcon') && Astro.slots.has('secondaryIcon')
23
+
24
+ const buttonClasses = [
25
+ styles.switch,
26
+ useIcons && styles.icons
27
+ ]
28
+ ---
29
+
30
+ <div
31
+ class:list={classes}
32
+ style={size ? `--w-theme-switcher-size: ${size}px;` : null}
33
+ data-id="w-theme-switcher"
34
+ data-primary-theme={primaryTheme}
35
+ data-secondary-theme={toggle ? secondaryTheme : undefined}
36
+ >
37
+ {Object.keys(themes as {}).map((theme, index) => (
38
+ <button
39
+ style={!useIcons ? `background:${theme};` : undefined}
40
+ data-theme={themes[theme]}
41
+ class:list={buttonClasses}
42
+ >
43
+ {index === 0 && <slot name="primaryIcon" />}
44
+ {index !== 0 && <slot name="secondaryIcon" />}
45
+ </button>
46
+ ))}
47
+ </div>
48
+
49
+ <script>
50
+ import { setCookie, getCookie } from '../../utils/cookies'
51
+ import { listen, dispatch } from '../../utils/event'
52
+
53
+ const switchers = document.querySelectorAll('[data-id="w-theme-switcher"]')
54
+
55
+ let currentTheme = localStorage.getItem('w-theme')
56
+ || getCookie('w-theme')
57
+ || (switchers[0] as HTMLDivElement).dataset.primaryTheme
58
+ || ''
59
+
60
+ const setActiveButton = (buttons: HTMLButtonElement[]) => {
61
+ buttons.forEach(button => button.dataset.active = 'false')
62
+
63
+ buttons.forEach(button => {
64
+ if (button.dataset.theme === currentTheme) {
65
+ button.dataset.active = 'true'
66
+ }
67
+ })
68
+ }
69
+
70
+ Array.from(switchers).forEach(switcher => {
71
+ const buttons = Array.from(switcher.querySelectorAll('button'))
72
+
73
+ setActiveButton(buttons)
74
+
75
+ listen('theme-switched', theme => {
76
+ currentTheme = theme
77
+
78
+ setActiveButton(buttons)
79
+ })
80
+
81
+ switcher.addEventListener('click', event => {
82
+ const target = event.target as HTMLButtonElement
83
+
84
+ if (target.nodeName === 'BUTTON') {
85
+ const toggleTheme = (switcher as HTMLDivElement).dataset.secondaryTheme
86
+
87
+ const theme = toggleTheme
88
+ ? toggleTheme === target.dataset.theme
89
+ ? (target.previousElementSibling as HTMLButtonElement).dataset.theme as string
90
+ : (target.nextElementSibling as HTMLButtonElement).dataset.theme as string
91
+ : target.dataset.theme as string
92
+
93
+ document.body.classList.replace(currentTheme, theme)
94
+
95
+ currentTheme = theme
96
+
97
+ setActiveButton(buttons)
98
+ setCookie('w-theme', currentTheme, 30)
99
+ localStorage.setItem('w-theme', currentTheme)
100
+
101
+ dispatch('theme-switched', currentTheme)
102
+ }
103
+ })
104
+ })
105
+ </script>
106
+
@@ -0,0 +1,76 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte'
3
+ import type { ThemeSwitcherProps } from './themeswitcher'
4
+
5
+ import { classNames } from '../../utils/classNames'
6
+ import { listen, dispatch } from '../../utils/event'
7
+ import { setCookie, getCookie } from '../../utils/cookies'
8
+
9
+ import styles from './themeswitcher.module.scss'
10
+
11
+ export let themes: ThemeSwitcherProps['themes'] = {}
12
+ export let toggle: ThemeSwitcherProps['toggle'] = false
13
+ export let size: ThemeSwitcherProps['size'] = 20
14
+ export let className: ThemeSwitcherProps['className'] = ''
15
+
16
+ let currentTheme = ''
17
+ let toggled = false
18
+
19
+ const classes = classNames([
20
+ styles.switcher,
21
+ toggle && styles.toggle,
22
+ className
23
+ ])
24
+
25
+ const primaryTheme = themes[Object.keys(themes)[0]]
26
+ const secondaryTheme = themes[Object.keys(themes)[1]]
27
+ const useIcons = $$slots.primaryIcon && $$slots.secondaryIcon
28
+
29
+ const setTheme = (theme: string | number) => {
30
+ if (typeof theme === 'number') {
31
+ theme = toggled ? primaryTheme : secondaryTheme
32
+ }
33
+
34
+ document.body.classList.replace(currentTheme, theme)
35
+
36
+ setCookie('w-theme', theme, 30)
37
+ localStorage.setItem('w-theme', theme)
38
+
39
+ dispatch('theme-switched', theme)
40
+ }
41
+
42
+ onMount(() => {
43
+ currentTheme = localStorage.getItem('w-theme')
44
+ || getCookie('w-theme')
45
+ || themes[Object.keys(themes)[0]]
46
+
47
+ if (toggle && currentTheme === secondaryTheme) {
48
+ toggled = true
49
+ }
50
+
51
+ listen('theme-switched', theme => {
52
+ currentTheme = theme
53
+ toggled = currentTheme === secondaryTheme
54
+ })
55
+ })
56
+ </script>
57
+
58
+ <div
59
+ class={classes}
60
+ style={size ? `--w-theme-switcher-size: ${size}px;` : null}
61
+ >
62
+ {#each Object.keys(themes) as theme, index}
63
+ <button
64
+ style={!useIcons ? `background:${theme};` : undefined}
65
+ data-active={currentTheme === themes[theme]}
66
+ on:click={() => setTheme(toggle ? index : themes[theme])}
67
+ class={classNames([
68
+ styles.switch,
69
+ useIcons && styles.icons
70
+ ])}
71
+ >
72
+ {#if index === 0}<slot name="primaryIcon" />{/if}
73
+ {#if index !== 0}<slot name="secondaryIcon" />{/if}
74
+ </button>
75
+ {/each}
76
+ </div>
@@ -0,0 +1,89 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import type { ReactThemeSwitcherProps } from './themeswitcher'
3
+
4
+ import { setCookie, getCookie } from '../../utils/cookies'
5
+ import { listen, dispatch } from '../../utils/event'
6
+ import { classNames } from '../../utils/classNames'
7
+
8
+ import styles from './themeswitcher.module.scss'
9
+
10
+ const ThemeSwitcher = ({
11
+ themes,
12
+ toggle,
13
+ size,
14
+ primaryIcon,
15
+ secondaryIcon,
16
+ className
17
+ }: ReactThemeSwitcherProps) => {
18
+ const [currentTheme, setCurrentTheme] = useState('')
19
+ const [toggled, setToggled] = useState(false)
20
+
21
+ const classes = classNames([
22
+ styles.switcher,
23
+ toggle && styles.toggle,
24
+ className
25
+ ])
26
+
27
+ const sizeStyles = size
28
+ ? { '--w-theme-switcher-size': `${size}px` } as React.CSSProperties
29
+ : undefined
30
+
31
+ const primaryTheme = themes[Object.keys(themes)[0]]
32
+ const secondaryTheme = themes[Object.keys(themes)[1]]
33
+ const useIcons = primaryIcon && secondaryIcon
34
+
35
+ const setTheme = (theme: string | number) => {
36
+ if (typeof theme === 'number') {
37
+ theme = toggled ? primaryTheme : secondaryTheme
38
+ }
39
+
40
+ document.body.classList.replace(currentTheme, theme)
41
+
42
+ setCookie('w-theme', theme, 30)
43
+ localStorage.setItem('w-theme', theme)
44
+
45
+ dispatch('theme-switched', theme)
46
+ }
47
+
48
+ useEffect(() => {
49
+ setCurrentTheme(
50
+ localStorage.getItem('w-theme')
51
+ || getCookie('w-theme')
52
+ || themes[Object.keys(themes)[0]]
53
+ )
54
+
55
+ if (toggle && currentTheme === secondaryTheme) {
56
+ setToggled(true)
57
+ }
58
+
59
+ listen('theme-switched', theme => {
60
+ setCurrentTheme(theme)
61
+ setToggled(theme === secondaryTheme)
62
+ })
63
+ }, [])
64
+
65
+ return (
66
+ <div
67
+ className={classes}
68
+ style={sizeStyles}
69
+ >
70
+ {Object.keys(themes as {}).map((theme, index) => (
71
+ <button
72
+ key={index}
73
+ data-active={currentTheme === themes[theme]}
74
+ onClick={() => setTheme(toggle ? index : themes[theme])}
75
+ style={!useIcons ? { background: theme } : undefined}
76
+ className={classNames([
77
+ styles.switch,
78
+ useIcons && styles.icons
79
+ ])}
80
+ >
81
+ {index === 0 && primaryIcon}
82
+ {index !== 0 && secondaryIcon}
83
+ </button>
84
+ ))}
85
+ </div>
86
+ )
87
+ }
88
+
89
+ export default ThemeSwitcher
@@ -0,0 +1,76 @@
1
+ @use '../../scss/config.scss' as *;
2
+
3
+ body {
4
+ --w-theme-switcher-size: 20px;
5
+ }
6
+
7
+ .switcher {
8
+ @include layout(flex, sm);
9
+
10
+ &.toggle {
11
+ @include position(relative);
12
+ width: var(--w-theme-switcher-size);
13
+ height: var(--w-theme-switcher-size);
14
+
15
+ .switch {
16
+ position: absolute;
17
+
18
+ &:first-child {
19
+ @include layer(overlay);
20
+ }
21
+
22
+ &:nth-child(2) {
23
+ @include layer(fg);
24
+ }
25
+
26
+ &[data-active="true"] {
27
+ @include layer(popup);
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ .switch {
34
+ @include border(0);
35
+ @include border-radius(max);
36
+ @include position(relative);
37
+
38
+ width: var(--w-theme-switcher-size);
39
+ height: var(--w-theme-switcher-size);
40
+ cursor: pointer;
41
+
42
+ &.icons {
43
+ @include transition(opacity);
44
+ @include typography(primary);
45
+ @include background(transparent);
46
+ @include spacing(p0);
47
+ @include visibility(0);
48
+
49
+ &[data-active="true"] {
50
+ @include visibility(1);
51
+ }
52
+
53
+ svg, img {
54
+ pointer-events: none;
55
+ width: var(--w-theme-switcher-size);
56
+ height: var(--w-theme-switcher-size);
57
+ }
58
+ }
59
+
60
+ &:not(.icons)::after {
61
+ @include position(absolute, center);
62
+ @include border(primary);
63
+ @include border-radius(max);
64
+ @include layer(bg);
65
+ @include transition();
66
+ @include size(0);
67
+
68
+ content: '';
69
+ }
70
+
71
+ &[data-active="true"]::after {
72
+ @include layer(default);
73
+ width: calc(var(--w-theme-switcher-size) + 5px);
74
+ height: calc(var(--w-theme-switcher-size) + 5px);
75
+ }
76
+ }
@@ -0,0 +1,13 @@
1
+ export type ThemeSwitcherProps = {
2
+ themes: {
3
+ [key: string]: string
4
+ }
5
+ toggle?: boolean
6
+ size?: number
7
+ className?: string
8
+ }
9
+
10
+ export type ReactThemeSwitcherProps = {
11
+ primaryIcon?: React.ReactNode
12
+ secondaryIcon?: React.ReactNode
13
+ } & ThemeSwitcherProps