@ibis-design/css 1.0.0-alpha.3 → 1.0.0-alpha.5

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.
@@ -1,4 +1,4 @@
1
- .ibis-toaster {
1
+ .ib-toaster {
2
2
  font-family: var(--font-family-sans);
3
3
  display: flex;
4
4
  align-items: center;
@@ -12,7 +12,7 @@
12
12
  margin-bottom: var(--spacing-1);
13
13
  }
14
14
 
15
- .ibis-toaster__icon {
15
+ .ib-toaster__icon {
16
16
  display: flex;
17
17
  align-items: center;
18
18
  justify-content: center;
@@ -23,29 +23,29 @@
23
23
  color: var(--color-text-on-primary);
24
24
  }
25
25
 
26
- .ibis-toaster__icon :global(svg) {
26
+ .ib-toaster__icon :global(svg) {
27
27
  width: 100%;
28
28
  height: 100%;
29
29
  }
30
30
 
31
- .ibis-toaster__content {
31
+ .ib-toaster__content {
32
32
  flex: 1;
33
33
  display: flex;
34
34
  flex-direction: column;
35
35
  justify-content: center;
36
36
  }
37
37
 
38
- .ibis-toaster__title {
38
+ .ib-toaster__title {
39
39
  font-weight: var(--font-weight-medium);
40
40
  font-size: var(--font-size-body-sm);
41
41
  }
42
42
 
43
- .ibis-toaster__message {
43
+ .ib-toaster__message {
44
44
  font-size: var(--font-size-body-sm);
45
45
  color: var(--color-text-on-primary);
46
46
  }
47
47
 
48
- .ibis-toaster__close {
48
+ .ib-toaster__close {
49
49
  background: transparent;
50
50
  border: none;
51
51
  cursor: pointer;
@@ -55,65 +55,65 @@
55
55
  flex-shrink: 0;
56
56
  }
57
57
 
58
- .ibis-toaster--success {
58
+ .ib-toaster--success {
59
59
  border-color: var(--color-status-success);
60
60
  background-color: var(--color-status-success);
61
61
  }
62
62
 
63
- .ibis-toaster--success .ibis-toaster__title {
63
+ .ib-toaster--success .ib-toaster__title {
64
64
  color: var(--color-text-on-primary);
65
65
  }
66
66
 
67
- .ibis-toaster--error {
67
+ .ib-toaster--error {
68
68
  border-color: var(--color-status-error);
69
69
  background-color: var(--color-status-error);
70
70
  }
71
71
 
72
- .ibis-toaster--error .ibis-toaster__title {
72
+ .ib-toaster--error .ib-toaster__title {
73
73
  color: var(--color-text-on-primary);
74
74
  }
75
75
 
76
- .ibis-toaster--accent {
76
+ .ib-toaster--accent {
77
77
  border-color: var(--color-toaster-accent);
78
78
  background-color: var(--color-toaster-accent);
79
79
  }
80
80
 
81
- .ibis-toaster--accent .ibis-toaster__title {
81
+ .ib-toaster--accent .ib-toaster__title {
82
82
  color: var(--color-text-on-primary);
83
83
  }
84
84
 
85
- .ibis-toaster--default {
85
+ .ib-toaster--default {
86
86
  border-color: var(--color-surface-muted);
87
87
  background-color: var(--color-surface-muted);
88
88
  }
89
89
 
90
- .ibis-toaster--default .ibis-toaster__title {
90
+ .ib-toaster--default .ib-toaster__title {
91
91
  color: var(--color-text-on-muted);
92
92
  }
93
93
 
94
- .ibis-toaster--default .ibis-toaster__message {
94
+ .ib-toaster--default .ib-toaster__message {
95
95
  color: var(--color-text-on-muted);
96
96
  }
97
97
 
98
- .ibis-toaster--default .ibis-toaster__icon {
98
+ .ib-toaster--default .ib-toaster__icon {
99
99
  color: var(--color-text-on-muted);
100
100
  }
101
101
 
102
- .ibis-toaster--default .ibis-toaster__close {
102
+ .ib-toaster--default .ib-toaster__close {
103
103
  color: var(--color-text-on-muted);
104
104
  border-color: var(--color-surface-default);
105
105
  }
106
106
 
107
- .ibis-toaster__loader {
107
+ .ib-toaster__loader {
108
108
  width: 1em;
109
109
  height: 1em;
110
110
  border: var(--border-width-default) solid var(--border-color-focus);
111
111
  border-top-color: var(--color-interactive-primary-indicator);
112
112
  border-radius: 50%;
113
- animation: ibis-toaster-spin 0.8s linear infinite;
113
+ animation: ib-toaster-spin 0.8s linear infinite;
114
114
  }
115
115
 
116
- @keyframes ibis-toaster-spin {
116
+ @keyframes ib-toaster-spin {
117
117
  from {
118
118
  transform: rotate(0deg);
119
119
  }
@@ -8,8 +8,8 @@
8
8
  flex-direction: row;
9
9
  align-items: center;
10
10
  justify-content: space-between;
11
- background-color: var(--color-surface-default);
12
- border-bottom: var(--border-width-thin) solid var(--border-color-subtle);
11
+ background-color: transparent;
12
+ border-bottom: none;
13
13
  box-sizing: border-box;
14
14
  padding: 0 var(--spacing-6);
15
15
  gap: var(--spacing-4);
@@ -44,7 +44,7 @@
44
44
  width: 200px;
45
45
  }
46
46
 
47
- .ib-top-bar__search .ibis-input {
47
+ .ib-top-bar__search .ib-input {
48
48
  max-width: 100%;
49
49
  width: 100%;
50
50
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibis-design/css",
3
- "version": "1.0.0-alpha.3",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "Design tokens, CSS variables, and Tailwind preset for the IBIS design system.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -30,8 +30,5 @@
30
30
  "sd-tailwindcss-transformer": "^2.2.1",
31
31
  "style-dictionary": "^5.4.4",
32
32
  "tsx": "^4.22.4"
33
- },
34
- "dependencies": {
35
- "@ibis-design/css": "^1.0.0-alpha.3"
36
33
  }
37
34
  }
@@ -25,11 +25,21 @@ export type ThemeOptions = {
25
25
  syncBootstrapTheme?: boolean;
26
26
  };
27
27
 
28
+ export type ThemeState = {
29
+ brand: BrandId;
30
+ colorMode: ColorModeId;
31
+ themeId: ThemeId;
32
+ };
33
+
28
34
  const isBrandId = (value: string): value is BrandId => value === "ib" || value === "alc";
29
35
 
30
36
  const isColorModeId = (value: string): value is ColorModeId =>
31
37
  value === "light" || value === "dark";
32
38
 
39
+ /** `<html>` when `document` exists (SSR-safe). */
40
+ const getHtmlRoot = (): HTMLElement | undefined =>
41
+ typeof document === "undefined" ? undefined : document.documentElement;
42
+
33
43
  /**
34
44
  * Applies brand and color mode to `document.documentElement` for CSS token switching.
35
45
  *
@@ -41,8 +51,8 @@ export const setTheme = (options: ThemeOptions = {}): ThemeId => {
41
51
  const brand = options.brand ?? DEFAULT_BRAND;
42
52
  const colorMode = options.colorMode ?? DEFAULT_COLOR_MODE;
43
53
 
44
- if (typeof document !== "undefined") {
45
- const root = document.documentElement;
54
+ const root = getHtmlRoot();
55
+ if (root) {
46
56
  root.dataset.brand = brand;
47
57
  root.dataset.colorMode = colorMode;
48
58
  delete root.dataset.theme;
@@ -60,8 +70,9 @@ export const setTheme = (options: ThemeOptions = {}): ThemeId => {
60
70
  *
61
71
  * @returns Current brand and color mode, or defaults when not in a browser
62
72
  */
63
- export const getTheme = (): { brand: BrandId; colorMode: ColorModeId; themeId: ThemeId } => {
64
- if (typeof document === "undefined") {
73
+ export const getTheme = (): ThemeState => {
74
+ const root = getHtmlRoot();
75
+ if (!root) {
65
76
  return {
66
77
  brand: DEFAULT_BRAND,
67
78
  colorMode: DEFAULT_COLOR_MODE,
@@ -69,11 +80,29 @@ export const getTheme = (): { brand: BrandId; colorMode: ColorModeId; themeId: T
69
80
  };
70
81
  }
71
82
 
72
- const brandRaw = document.documentElement.dataset.brand;
73
- const modeRaw = document.documentElement.dataset.colorMode;
83
+ const brandRaw = root.dataset.brand;
84
+ const modeRaw = root.dataset.colorMode;
74
85
 
75
86
  const brand = brandRaw && isBrandId(brandRaw) ? brandRaw : DEFAULT_BRAND;
76
87
  const colorMode = modeRaw && isColorModeId(modeRaw) ? modeRaw : DEFAULT_COLOR_MODE;
77
88
 
78
89
  return { brand, colorMode, themeId: toThemeId(brand, colorMode) };
79
90
  };
91
+
92
+ /**
93
+ * Toggles `data-color-mode` between light and dark while preserving the active brand.
94
+ * When `data-bs-theme` is already present on `<html>`, it is updated to match.
95
+ *
96
+ * @returns Active brand, color mode, and composite theme id after the toggle
97
+ * @example
98
+ * const { colorMode } = toggleDark();
99
+ */
100
+ export const toggleDark = (): ThemeState => {
101
+ const { brand, colorMode } = getTheme();
102
+ const nextColorMode: ColorModeId = colorMode === "dark" ? "light" : "dark";
103
+ const syncBootstrapTheme = getHtmlRoot()?.hasAttribute("data-bs-theme") ?? false;
104
+
105
+ setTheme({ brand, colorMode: nextColorMode, syncBootstrapTheme });
106
+
107
+ return { brand, colorMode: nextColorMode, themeId: toThemeId(brand, nextColorMode) };
108
+ };