@hyphen/hyphen-components 2.11.4 → 2.12.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.
- package/dist/components/ThemeProvider/ThemeProvider.d.ts +2 -1
- package/dist/css/index.css +2 -2
- package/dist/css/variables.css +0 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/useTheme/useTheme.d.ts +5 -0
- package/dist/hooks/useTheme/useTheme.stories.d.ts +6 -0
- package/dist/hyphen-components.cjs.development.js +60 -62
- package/dist/hyphen-components.cjs.development.js.map +1 -1
- package/dist/hyphen-components.cjs.production.min.js +1 -1
- package/dist/hyphen-components.cjs.production.min.js.map +1 -1
- package/dist/hyphen-components.esm.js +61 -64
- package/dist/hyphen-components.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/FormLabel/FormLabel.module.scss +0 -5
- package/src/components/FormLabel/FormLabel.tsx +2 -11
- package/src/components/HelpText/HelpText.module.scss +1 -4
- package/src/components/InputValidationMessage/InputValidationMessage.tsx +1 -1
- package/src/components/ThemeProvider/ThemeProvider.stories.tsx +6 -3
- package/src/components/ThemeProvider/ThemeProvider.tsx +10 -13
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useTheme/useTheme.stories.tsx +63 -0
- package/src/hooks/useTheme/useTheme.ts +11 -0
- package/src/styles/variables/forms.scss +0 -1
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import React, { FC, ReactNode } from 'react';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { Box, BoxProps } from '../Box/Box';
|
|
4
4
|
import styles from './FormLabel.module.scss';
|
|
5
|
+
import { HelpText } from '../HelpText/HelpText';
|
|
5
6
|
|
|
6
7
|
export interface FormLabelProps extends BoxProps {
|
|
7
8
|
/**
|
|
@@ -80,17 +81,7 @@ export const FormLabel: FC<FormLabelProps> = ({
|
|
|
80
81
|
>
|
|
81
82
|
{children}
|
|
82
83
|
{isFieldRequired && requiredIndicator && <span>{requiredIndicator}</span>}
|
|
83
|
-
{helpText &&
|
|
84
|
-
<Box
|
|
85
|
-
as="p"
|
|
86
|
-
display="block"
|
|
87
|
-
fontSize="sm"
|
|
88
|
-
color="secondary"
|
|
89
|
-
className={styles['help-text']}
|
|
90
|
-
>
|
|
91
|
-
{helpText}
|
|
92
|
-
</Box>
|
|
93
|
-
)}
|
|
84
|
+
{helpText && <HelpText>{helpText}</HelpText>}
|
|
94
85
|
</Box>
|
|
95
86
|
);
|
|
96
87
|
};
|
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
--form-control-font-family,
|
|
4
4
|
var(--INTERNAL_form-control-font-family)
|
|
5
5
|
);
|
|
6
|
-
margin-top: var(
|
|
7
|
-
--form-control-help-margin,
|
|
8
|
-
var(--INTERNAL_form-control-help-margin)
|
|
9
|
-
);
|
|
6
|
+
margin-top: var(--size-spacing-xs);
|
|
10
7
|
font-weight: var(
|
|
11
8
|
--form-control-help-text-font-weight,
|
|
12
9
|
var(--INTERNAL_form-control-help-text-font-weight)
|
|
@@ -3,7 +3,8 @@ import { ThemeProvider } from './ThemeProvider';
|
|
|
3
3
|
import type { Meta } from '@storybook/react';
|
|
4
4
|
import { Box } from '../Box/Box';
|
|
5
5
|
import { RadioGroup } from '../RadioGroup/RadioGroup';
|
|
6
|
-
import {
|
|
6
|
+
import { Theme } from './ThemeProvider';
|
|
7
|
+
import { useTheme } from '../../hooks/useTheme/useTheme';
|
|
7
8
|
|
|
8
9
|
const meta: Meta<typeof ThemeProvider> = {
|
|
9
10
|
title: 'Providers/ThemeProvider',
|
|
@@ -15,7 +16,7 @@ export default meta;
|
|
|
15
16
|
export const BasicUsage = () =>
|
|
16
17
|
(() => {
|
|
17
18
|
const App = () => {
|
|
18
|
-
const { theme, setTheme } = useTheme();
|
|
19
|
+
const { theme, setTheme, isDarkMode } = useTheme();
|
|
19
20
|
|
|
20
21
|
const options = [
|
|
21
22
|
{
|
|
@@ -38,7 +39,9 @@ export const BasicUsage = () =>
|
|
|
38
39
|
return (
|
|
39
40
|
<Box gap="md" background="secondary" padding="xl" color="base">
|
|
40
41
|
<p>Theme: {theme}</p>
|
|
41
|
-
|
|
42
|
+
<p>
|
|
43
|
+
<code>isDarkMode</code>: {`${isDarkMode}`}
|
|
44
|
+
</p>
|
|
42
45
|
<RadioGroup
|
|
43
46
|
name="SelectTheme"
|
|
44
47
|
value={theme}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useState, useEffect
|
|
1
|
+
import React, { createContext, useState, useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
export type Theme = 'dark' | 'light' | 'system';
|
|
4
4
|
|
|
@@ -11,6 +11,7 @@ type ThemeProviderProps = {
|
|
|
11
11
|
type ThemeProviderState = {
|
|
12
12
|
theme: Theme;
|
|
13
13
|
setTheme: (theme: Theme) => void;
|
|
14
|
+
isDarkMode?: boolean;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
const initialState: ThemeProviderState = {
|
|
@@ -18,7 +19,8 @@ const initialState: ThemeProviderState = {
|
|
|
18
19
|
setTheme: () => null,
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
const ThemeProviderContext =
|
|
22
|
+
export const ThemeProviderContext =
|
|
23
|
+
createContext<ThemeProviderState>(initialState);
|
|
22
24
|
|
|
23
25
|
export function ThemeProvider({
|
|
24
26
|
children,
|
|
@@ -48,12 +50,18 @@ export function ThemeProvider({
|
|
|
48
50
|
root.classList.add(theme);
|
|
49
51
|
}, [theme]);
|
|
50
52
|
|
|
53
|
+
const isDarkMode =
|
|
54
|
+
theme === 'dark' ||
|
|
55
|
+
(theme === 'system' &&
|
|
56
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
|
57
|
+
|
|
51
58
|
const value = {
|
|
52
59
|
theme,
|
|
53
60
|
setTheme: (theme: Theme) => {
|
|
54
61
|
localStorage.setItem(storageKey, theme);
|
|
55
62
|
setTheme(theme);
|
|
56
63
|
},
|
|
64
|
+
isDarkMode,
|
|
57
65
|
};
|
|
58
66
|
|
|
59
67
|
return (
|
|
@@ -62,14 +70,3 @@ export function ThemeProvider({
|
|
|
62
70
|
</ThemeProviderContext.Provider>
|
|
63
71
|
);
|
|
64
72
|
}
|
|
65
|
-
|
|
66
|
-
export const useTheme = () => {
|
|
67
|
-
const context = useContext(ThemeProviderContext);
|
|
68
|
-
|
|
69
|
-
if (context === undefined)
|
|
70
|
-
throw new Error(
|
|
71
|
-
'useTheme must be used within a ThemeProvider. Be sure your App is wrapped in ThemeProvider.'
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
return context;
|
|
75
|
-
};
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './useBreakpoint/useBreakpoint';
|
|
2
|
+
export * from './useIsomorphicLayoutEffect/useIsomorphicLayouEffect';
|
|
2
3
|
export * from './useOpenClose/useOpenClose';
|
|
4
|
+
export * from './useTheme/useTheme';
|
|
3
5
|
export * from './useWindowSize/useWindowSize';
|
|
4
|
-
export * from './useIsomorphicLayoutEffect/useIsomorphicLayouEffect';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Theme,
|
|
4
|
+
ThemeProvider,
|
|
5
|
+
} from '../../components/ThemeProvider/ThemeProvider';
|
|
6
|
+
import type { Meta } from '@storybook/react';
|
|
7
|
+
import { Box } from '../../components/Box/Box';
|
|
8
|
+
import { RadioGroup } from '../../components/RadioGroup/RadioGroup';
|
|
9
|
+
import { useTheme } from '../../hooks/useTheme/useTheme';
|
|
10
|
+
|
|
11
|
+
const meta: Meta<typeof ThemeProvider> = {
|
|
12
|
+
title: 'Hooks/useTheme',
|
|
13
|
+
parameters: {
|
|
14
|
+
controls: { hideNoControlsWarning: true },
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
|
|
20
|
+
export const BasicUsage = () =>
|
|
21
|
+
(() => {
|
|
22
|
+
const App = () => {
|
|
23
|
+
const { theme, setTheme, isDarkMode } = useTheme();
|
|
24
|
+
|
|
25
|
+
const options = [
|
|
26
|
+
{
|
|
27
|
+
id: 'light',
|
|
28
|
+
value: 'light',
|
|
29
|
+
label: 'Light',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'dark',
|
|
33
|
+
value: 'dark',
|
|
34
|
+
label: 'Dark',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'system',
|
|
38
|
+
value: 'system',
|
|
39
|
+
label: 'System',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Box gap="md" background="secondary" padding="xl" color="base">
|
|
45
|
+
<p>Theme: {theme}</p>
|
|
46
|
+
<p>
|
|
47
|
+
<code>isDarkMode</code>: {`${isDarkMode}`}
|
|
48
|
+
</p>
|
|
49
|
+
<RadioGroup
|
|
50
|
+
name="SelectTheme"
|
|
51
|
+
value={theme}
|
|
52
|
+
onChange={(event) => setTheme(event.target.value as Theme)}
|
|
53
|
+
options={options}
|
|
54
|
+
/>
|
|
55
|
+
</Box>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
return (
|
|
59
|
+
<ThemeProvider defaultTheme="light" storageKey="hyphen-ui-theme">
|
|
60
|
+
<App />
|
|
61
|
+
</ThemeProvider>
|
|
62
|
+
);
|
|
63
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ThemeProviderContext } from '../../components/ThemeProvider/ThemeProvider';
|
|
3
|
+
|
|
4
|
+
export const useTheme = () => {
|
|
5
|
+
const context = React.useContext(ThemeProviderContext);
|
|
6
|
+
if (context === undefined)
|
|
7
|
+
throw new Error(
|
|
8
|
+
'useTheme must be used within a ThemeProvider. Be sure your App is wrapped in ThemeProvider.'
|
|
9
|
+
);
|
|
10
|
+
return context;
|
|
11
|
+
};
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// ----GLOBALS----
|
|
3
3
|
--INTERNAL_form-control-box-shadow-focus: 0 0 0 3px var(--color-border-subtle);
|
|
4
4
|
--INTERNAL_form-control-label-margin: var(--size-spacing-xs);
|
|
5
|
-
--INTERNAL_form-control-help-margin: var(--size-spacing-2xs);
|
|
6
5
|
--INTERNAL_form-control-line-height: var(--size-line-height-input);
|
|
7
6
|
--INTERNAL_form-control-label-font-weight: var(--size-font-weight-medium);
|
|
8
7
|
--INTERNAL_form-control-legend-font-weight: var(--size-font-weight-medium);
|