@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyphen/hyphen-components",
3
- "version": "2.11.4",
3
+ "version": "2.12.0",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "@hyphen"
@@ -11,9 +11,4 @@
11
11
  &.disabled {
12
12
  color: var(--color-base-grey-300);
13
13
  }
14
-
15
- .help-text {
16
- margin-top: var(--INTERNAL_form-control-help-margin);
17
- font-weight: var(--INTERNAL_form-control-help-font-weight);
18
- }
19
14
  }
@@ -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)
@@ -20,7 +20,7 @@ export const InputValidationMessage: FC<InputValidationMessageProps> = ({
20
20
  styles['input-validation-message'],
21
21
  'font-color-danger',
22
22
  `font-size-${size}`,
23
- 'm-top-xs'
23
+ 'm-top-sm'
24
24
  );
25
25
 
26
26
  return <div className={classes}>{children}</div>;
@@ -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 { useTheme, Theme } from './ThemeProvider';
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, useContext } from 'react';
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 = createContext<ThemeProviderState>(initialState);
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
- };
@@ -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);