A design system in a box. hip-ui.tngl.io/docs/introduction
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

color picker

+747 -35
+1 -2
README.md
··· 33 33 34 34 #### react-aria wrappers 35 35 36 - - [ ] Color Picker 37 - 38 36 - [ ] Calendar 39 37 - [ ] Date Picker 40 38 - [ ] Range Date Picker ··· 56 54 - [ ] Toolbar 57 55 - [ ] Toast 58 56 57 + - [x] Color Picker 59 58 - [x] Color Swatch Picker 60 59 - [x] Color Wheel 61 60 - [x] Color Slider
+283
apps/docs/src/components/color-picker/index.tsx
··· 1 + import * as stylex from "@stylexjs/stylex"; 2 + import { Pipette } from "lucide-react"; 3 + import { createContext, use } from "react"; 4 + import { 5 + ColorPicker as AriaColorPicker, 6 + Button, 7 + Color, 8 + ColorPickerStateContext, 9 + ColorSpace, 10 + Dialog, 11 + DialogTrigger, 12 + Popover, 13 + PopoverProps, 14 + type ColorPickerProps as AriaColorPickerProps, 15 + } from "react-aria-components"; 16 + 17 + import { ColorArea } from "../color-area"; 18 + import { ColorField } from "../color-field"; 19 + import { ColorSlider } from "../color-slider"; 20 + import { ColorSwatch } from "../color-swatch"; 21 + import { 22 + ColorSwatchPicker, 23 + ColorSwatchPickerItem, 24 + } from "../color-swatch-picker"; 25 + import { SizeContext } from "../context"; 26 + import { Flex, FlexProps } from "../flex"; 27 + import { IconButton } from "../icon-button"; 28 + import { Select, SelectItem } from "../select"; 29 + import { Separator } from "../separator"; 30 + import { spacing } from "../theme/spacing.stylex"; 31 + import { Size, StyleXComponentProps } from "../theme/types"; 32 + import { fontSize } from "../theme/typography.stylex"; 33 + import { usePopoverStyles } from "../theme/usePopoverStyles"; 34 + 35 + const ColorSpaceContext = createContext<ColorSpace>("hsb"); 36 + 37 + const styles = stylex.create({ 38 + button: { 39 + alignItems: "center", 40 + backgroundColor: "transparent", 41 + borderWidth: 0, 42 + display: "flex", 43 + fontSize: fontSize["sm"], 44 + gap: { 45 + default: spacing["2"], 46 + ":is([data-size=sm])": spacing["1"], 47 + }, 48 + margin: 0, 49 + padding: 0, 50 + }, 51 + root: { 52 + display: "block", 53 + }, 54 + defaultPicker: { 55 + paddingBottom: spacing["3"], 56 + paddingLeft: spacing["2"], 57 + paddingRight: spacing["2"], 58 + paddingTop: spacing["2"], 59 + }, 60 + popover: { 61 + paddingBottom: 0, 62 + paddingTop: 0, 63 + width: 328, 64 + }, 65 + separator: { 66 + marginLeft: `calc(${spacing["2"]} * -1)`, 67 + marginRight: `calc(${spacing["2"]} * -1)`, 68 + width: `calc(100% + ${spacing["2"]} * 2)`, 69 + }, 70 + grow: { 71 + flexBasis: "0%", 72 + flexGrow: 1, 73 + flexShrink: 1, 74 + minWidth: 0, 75 + }, 76 + controls: { 77 + paddingLeft: spacing["1"], 78 + paddingRight: spacing["1"], 79 + }, 80 + }); 81 + 82 + export interface ColorPickerProps 83 + extends StyleXComponentProps<Omit<AriaColorPickerProps, "children">>, 84 + Pick<PopoverProps, "placement"> { 85 + children?: React.ReactNode; 86 + size?: Size; 87 + label?: string; 88 + } 89 + 90 + function ColorSpaceProvider({ children }: { children: React.ReactNode }) { 91 + const state = use(ColorPickerStateContext); 92 + 93 + if (!state?.color) { 94 + throw new Error("Color needs to be a defined value"); 95 + } 96 + 97 + return ( 98 + <ColorSpaceContext value={state.color.getColorSpace()}> 99 + {children} 100 + </ColorSpaceContext> 101 + ); 102 + } 103 + 104 + export function ColorPicker({ 105 + style, 106 + children, 107 + label, 108 + size: sizeProp, 109 + placement, 110 + ...props 111 + }: ColorPickerProps) { 112 + const popoverStyles = usePopoverStyles(); 113 + const size = sizeProp || use(SizeContext); 114 + 115 + return ( 116 + <SizeContext value={size}> 117 + <AriaColorPicker {...props} {...stylex.props(styles.root, style)}> 118 + <ColorSpaceProvider> 119 + <DialogTrigger> 120 + <Button data-size={size} {...stylex.props(styles.button)}> 121 + <ColorSwatch /> 122 + {label && <span>{label}</span>} 123 + </Button> 124 + <Popover 125 + placement={placement} 126 + {...stylex.props( 127 + popoverStyles.wrapper, 128 + popoverStyles.animation, 129 + styles.popover, 130 + )} 131 + > 132 + <Dialog className="color-picker-dialog">{children}</Dialog> 133 + </Popover> 134 + </DialogTrigger> 135 + </ColorSpaceProvider> 136 + </AriaColorPicker> 137 + </SizeContext> 138 + ); 139 + } 140 + 141 + export interface DefaultColorEditorProps extends FlexProps { 142 + swatches?: string[]; 143 + onSwatchChange?: (color: Color) => void; 144 + hasAlpha?: boolean; 145 + } 146 + 147 + export function DefaultColorEditor({ 148 + style, 149 + swatches, 150 + onSwatchChange, 151 + hasAlpha = true, 152 + ...props 153 + }: DefaultColorEditorProps) { 154 + const colorSpace = use(ColorSpaceContext); 155 + const state = use(ColorPickerStateContext); 156 + 157 + return ( 158 + <Flex 159 + direction="column" 160 + gap="3" 161 + {...props} 162 + style={[styles.defaultPicker, style]} 163 + > 164 + {colorSpace === "hsb" ? ( 165 + <ColorArea 166 + colorSpace={colorSpace} 167 + xChannel="saturation" 168 + yChannel="brightness" 169 + /> 170 + ) : colorSpace === "hsl" ? ( 171 + <ColorArea 172 + colorSpace={colorSpace} 173 + xChannel="hue" 174 + yChannel="saturation" 175 + /> 176 + ) : ( 177 + <ColorArea colorSpace={colorSpace} xChannel="red" yChannel="green" /> 178 + )} 179 + 180 + <Separator style={styles.separator} /> 181 + 182 + <Flex gap="2" align="center"> 183 + <IconButton label="Pick color" variant="outline"> 184 + <Pipette /> 185 + </IconButton> 186 + <Select 187 + aria-label="Color format" 188 + value={colorSpace} 189 + onChange={(key) => { 190 + state?.setColor(state.color.toFormat(key as ColorSpace)); 191 + }} 192 + > 193 + <SelectItem id="hsb">HSB</SelectItem> 194 + <SelectItem id="hsl">HSL</SelectItem> 195 + <SelectItem id="rgb">RGB</SelectItem> 196 + </Select> 197 + <ColorField 198 + aria-label="HEX code" 199 + colorSpace={colorSpace} 200 + style={styles.grow} 201 + /> 202 + {hasAlpha && ( 203 + <ColorField 204 + aria-label="Alpha" 205 + colorSpace={colorSpace} 206 + channel="alpha" 207 + style={styles.grow} 208 + /> 209 + )} 210 + </Flex> 211 + 212 + <Separator style={styles.separator} /> 213 + 214 + <SizeContext value="sm"> 215 + <Flex direction="column" gap="3" style={styles.controls}> 216 + {colorSpace === "hsb" ? ( 217 + <> 218 + <ColorSlider label="Hue" channel="hue" colorSpace={colorSpace} /> 219 + <ColorSlider 220 + label="Saturation" 221 + channel="saturation" 222 + colorSpace={colorSpace} 223 + /> 224 + <ColorSlider 225 + label="Brightness" 226 + channel="brightness" 227 + colorSpace={colorSpace} 228 + /> 229 + </> 230 + ) : colorSpace === "hsl" ? ( 231 + <> 232 + <ColorSlider label="Hue" channel="hue" colorSpace={colorSpace} /> 233 + <ColorSlider 234 + label="Saturation" 235 + channel="saturation" 236 + colorSpace={colorSpace} 237 + /> 238 + <ColorSlider 239 + label="Lightness" 240 + channel="lightness" 241 + colorSpace={colorSpace} 242 + /> 243 + </> 244 + ) : ( 245 + <> 246 + <ColorSlider label="Red" channel="red" colorSpace={colorSpace} /> 247 + <ColorSlider 248 + label="Green" 249 + channel="green" 250 + colorSpace={colorSpace} 251 + /> 252 + <ColorSlider 253 + label="Blue" 254 + channel="blue" 255 + colorSpace={colorSpace} 256 + /> 257 + </> 258 + )} 259 + 260 + {hasAlpha && ( 261 + <ColorSlider 262 + label="Alpha" 263 + channel="alpha" 264 + colorSpace={colorSpace} 265 + /> 266 + )} 267 + </Flex> 268 + </SizeContext> 269 + {swatches && ( 270 + <> 271 + <Separator style={styles.separator} /> 272 + <Flex direction="column" align="center"> 273 + <ColorSwatchPicker onChange={onSwatchChange}> 274 + {swatches.map((swatch) => ( 275 + <ColorSwatchPickerItem key={swatch} color={swatch} /> 276 + ))} 277 + </ColorSwatchPicker> 278 + </Flex> 279 + </> 280 + )} 281 + </Flex> 282 + ); 283 + }
+8 -2
apps/docs/src/components/color-slider/index.tsx
··· 22 22 display: "grid", 23 23 flexDirection: "column", 24 24 gap: spacing["2"], 25 - gridTemplateAreas: "'label value-label' 'track track'", 25 + gridTemplateAreas: { 26 + default: "'track'", 27 + ":has(label,[data-slider-output])": "'label value-label' 'track track'", 28 + }, 26 29 }, 27 30 label: { 28 31 gridArea: "label", ··· 84 87 > 85 88 {label && <Label style={styles.label}>{label}</Label>} 86 89 {showValueLabel && ( 87 - <SliderOutput {...stylex.props(styles.valueLabel)} /> 90 + <SliderOutput 91 + data-slider-output 92 + {...stylex.props(styles.valueLabel)} 93 + /> 88 94 )} 89 95 <SliderTrack 90 96 {...stylex.props(styles.track)}
+4 -8
apps/docs/src/components/theme/types.ts
··· 21 21 | "warning" 22 22 | "critical"; 23 23 24 - export type StyleXComponentProps< 25 - T extends { 26 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 27 - className?: any; 28 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 29 - style?: any; 30 - }, 31 - > = Omit<T, "className" | "style"> & { 24 + export type StyleXComponentProps<T extends object> = Omit< 25 + T, 26 + "className" | "style" 27 + > & { 32 28 className?: never; 33 29 /** 34 30 * The style to apply to the component.
+1 -1
apps/docs/src/components/theme/useInputStyles.ts
··· 121 121 field: [styles.field], 122 122 wrapper: [ 123 123 styles.inputWrapper, 124 - variant === "primary" && [ui.bgUi, styles.primary], 124 + variant === "primary" && [ui.bgGhost, styles.primary], 125 125 variant === "secondary" && [ui.bgUi], 126 126 variant === "tertiary" && [ui.bgGhost], 127 127 ui.text,
+68
apps/docs/src/docs/components/color-picker.mdx
··· 1 + --- 2 + title: Color Picker 3 + description: Compose color components to create a color picker. 4 + --- 5 + 6 + import { PropDocs } from '../../lib/PropDocs' 7 + import { Example } from '../../lib/Example' 8 + import { DefaultEditor } from '../../examples/color-picker/default-editor' 9 + import { CustomChildren } from '../../examples/color-picker/custom-children' 10 + import { Swatches } from '../../examples/color-picker/swatches' 11 + import { AlphaChannel } from '../../examples/color-picker/alpha-channel' 12 + 13 + This component provides a `DefaultColorEditor` component that contains a basic color picker with support for `hsb`, `hsl` and `rgb` values. 14 + It simply composes other color components, which you can also easily do yourself to customize the picker. 15 + 16 + <Example src={DefaultEditor} /> 17 + 18 + ## Installation 19 + 20 + Run the following command to add the color picker to your project. 21 + 22 + ```bash 23 + pnpm hip install color-picker 24 + ``` 25 + 26 + ## Props 27 + 28 + This component is built using the React Aria ColorPicker. 29 + See the official guide for full behavior and API details. 30 + 31 + - Docs: [React Aria ColorPicker](https://react-spectrum.adobe.com/react-aria/ColorPicker.html#reusable-wrappers) 32 + 33 + <PropDocs components={["ColorPicker", "DefaultColorEditor"]} /> 34 + 35 + ## Examples 36 + 37 + ### Default Editor 38 + 39 + The `DefaultColorEditor` composes a `ColorArea`, `Hue` and `Alpha` sliders, a format `Select`, and a format-aware `ColorField`. 40 + 41 + <Example src={DefaultEditor} /> 42 + 43 + ### Custom Children 44 + 45 + Compose any color UI you like inside `ColorPicker`. 46 + 47 + <Example src={CustomChildren} /> 48 + 49 + ### Swatches 50 + 51 + You can add swatches to the color picker by passing an array of colors to the `swatches` prop. 52 + 53 + <Example src={Swatches} /> 54 + 55 + ### Alpha Channel 56 + 57 + You can hide the alpha channel by passing `false` to the `hasAlpha` prop. 58 + 59 + <Example src={AlphaChannel} /> 60 + 61 + ## Related Components 62 + 63 + - [ColorArea](/docs/components/color-area) 64 + - [ColorSlider](/docs/components/color-slider) 65 + - [ColorField](/docs/components/color-field) 66 + - [ColorSwatchPicker](/docs/components/color-swatch-picker) 67 + 68 +
+9
apps/docs/src/examples/color-picker/alpha-channel.tsx
··· 1 + import { ColorPicker, DefaultColorEditor } from "@/components/color-picker"; 2 + 3 + export function AlphaChannel() { 4 + return ( 5 + <ColorPicker defaultValue="#5100FF" label="Fill color"> 6 + <DefaultColorEditor hasAlpha={false} /> 7 + </ColorPicker> 8 + ); 9 + }
+15
apps/docs/src/examples/color-picker/custom-children.tsx
··· 1 + import { ColorArea } from "@/components/color-area"; 2 + import { ColorPicker } from "@/components/color-picker"; 3 + import { ColorSlider } from "@/components/color-slider"; 4 + 5 + export function CustomChildren() { 6 + return ( 7 + <ColorPicker defaultValue="#5100FF"> 8 + <ColorArea colorSpace="hsb" xChannel="saturation" yChannel="brightness" /> 9 + <div> 10 + <ColorSlider channel="hue" label="Hue" /> 11 + <ColorSlider channel="alpha" label="Alpha" /> 12 + </div> 13 + </ColorPicker> 14 + ); 15 + }
+9
apps/docs/src/examples/color-picker/default-editor.tsx
··· 1 + import { ColorPicker, DefaultColorEditor } from "@/components/color-picker"; 2 + 3 + export function DefaultEditor() { 4 + return ( 5 + <ColorPicker defaultValue="#5100FF" label="Fill color" placement="right"> 6 + <DefaultColorEditor /> 7 + </ColorPicker> 8 + ); 9 + }
+32
apps/docs/src/examples/color-picker/swatches.tsx
··· 1 + import { ColorPicker, DefaultColorEditor } from "@/components/color-picker"; 2 + 3 + const SWATCHES = [ 4 + "#FF0000", 5 + "#FF7F00", 6 + "#FFFF00", 7 + "#00FF00", 8 + "#0000FF", 9 + "#4B0082", 10 + "#8B00FF", 11 + "#5100FF", 12 + "#A00", 13 + "#f80", 14 + "#080", 15 + "#08f", 16 + "#088", 17 + "#008", 18 + "#f0f", 19 + "#0ff", 20 + "#dead", 21 + "#000000", 22 + "#808080", 23 + "#FFFFFF", 24 + ]; 25 + 26 + export function Swatches() { 27 + return ( 28 + <ColorPicker defaultValue="#5100FF" label="Fill color"> 29 + <DefaultColorEditor swatches={SWATCHES} /> 30 + </ColorPicker> 31 + ); 32 + }
+13 -11
packages/hip-ui/src/cli/install.tsx
··· 22 22 import { colorSwatchPickerConfig } from "../components/color-swatch-picker/color-swatch-picker-config.js"; 23 23 import { colorSwatchConfig } from "../components/color-swatch/link-config.js"; 24 24 import { colorWheelConfig } from "../components/color-wheel/color-wheel-config.js"; 25 + import { colorPickerConfig } from "../components/color-picker/color-picker-config.js"; 25 26 import { comboboxConfig } from "../components/combobox/combobox-config.js"; 26 27 import { commandMenuConfig } from "../components/command-menu/command-menu-config.js"; 27 28 import { contextMenuConfig } from "../components/context-menu/context-menu-config.js"; ··· 118 119 colorSliderConfig, 119 120 colorWheelConfig, 120 121 colorSwatchPickerConfig, 122 + colorPickerConfig, 121 123 ]; 122 124 123 125 function StringSetting({ ··· 288 290 289 291 console.log(`🔄 Installing ${packageName}@${version}`); 290 292 291 - await new Promise((resolve) => 292 - exec(`${config.packageManager} i ${packageName}@${version}`, (error) => { 293 - if (error) { 294 - console.error( 295 - `❌ Error installing ${packageName}@${version}:`, 296 - error, 297 - ); 298 - } 293 + // await new Promise((resolve) => 294 + // exec(`${config.packageManager} i ${packageName}@${version}`, (error) => { 295 + // if (error) { 296 + // console.error( 297 + // `❌ Error installing ${packageName}@${version}:`, 298 + // error, 299 + // ); 300 + // } 299 301 300 - resolve(true); 301 - }), 302 - ); 302 + // resolve(true); 303 + // }), 304 + // ); 303 305 } 304 306 } 305 307
+8
packages/hip-ui/src/components/color-picker/color-picker-config.ts
··· 1 + import { ComponentConfig } from "../../types"; 2 + 3 + export const colorPickerConfig: ComponentConfig = { 4 + name: "color-picker", 5 + filepath: "./index.tsx", 6 + }; 7 + 8 +
+283
packages/hip-ui/src/components/color-picker/index.tsx
··· 1 + import * as stylex from "@stylexjs/stylex"; 2 + import { Pipette } from "lucide-react"; 3 + import { createContext, use } from "react"; 4 + import { 5 + ColorPicker as AriaColorPicker, 6 + Button, 7 + Color, 8 + ColorPickerStateContext, 9 + ColorSpace, 10 + Dialog, 11 + DialogTrigger, 12 + Popover, 13 + PopoverProps, 14 + type ColorPickerProps as AriaColorPickerProps, 15 + } from "react-aria-components"; 16 + 17 + import { ColorArea } from "../color-area"; 18 + import { ColorField } from "../color-field"; 19 + import { ColorSlider } from "../color-slider"; 20 + import { ColorSwatch } from "../color-swatch"; 21 + import { 22 + ColorSwatchPicker, 23 + ColorSwatchPickerItem, 24 + } from "../color-swatch-picker"; 25 + import { SizeContext } from "../context"; 26 + import { Flex, FlexProps } from "../flex"; 27 + import { IconButton } from "../icon-button"; 28 + import { Select, SelectItem } from "../select"; 29 + import { Separator } from "../separator"; 30 + import { spacing } from "../theme/spacing.stylex"; 31 + import { Size, StyleXComponentProps } from "../theme/types"; 32 + import { fontSize } from "../theme/typography.stylex"; 33 + import { usePopoverStyles } from "../theme/usePopoverStyles"; 34 + 35 + const ColorSpaceContext = createContext<ColorSpace>("hsb"); 36 + 37 + const styles = stylex.create({ 38 + button: { 39 + alignItems: "center", 40 + backgroundColor: "transparent", 41 + borderWidth: 0, 42 + display: "flex", 43 + fontSize: fontSize["sm"], 44 + gap: { 45 + default: spacing["2"], 46 + ":is([data-size=sm])": spacing["1"], 47 + }, 48 + margin: 0, 49 + padding: 0, 50 + }, 51 + root: { 52 + display: "block", 53 + }, 54 + defaultPicker: { 55 + paddingBottom: spacing["3"], 56 + paddingLeft: spacing["2"], 57 + paddingRight: spacing["2"], 58 + paddingTop: spacing["2"], 59 + }, 60 + popover: { 61 + paddingBottom: 0, 62 + paddingTop: 0, 63 + width: 328, 64 + }, 65 + separator: { 66 + marginLeft: `calc(${spacing["2"]} * -1)`, 67 + marginRight: `calc(${spacing["2"]} * -1)`, 68 + width: `calc(100% + ${spacing["2"]} * 2)`, 69 + }, 70 + grow: { 71 + flexBasis: "0%", 72 + flexGrow: 1, 73 + flexShrink: 1, 74 + minWidth: 0, 75 + }, 76 + controls: { 77 + paddingLeft: spacing["1"], 78 + paddingRight: spacing["1"], 79 + }, 80 + }); 81 + 82 + export interface ColorPickerProps 83 + extends StyleXComponentProps<Omit<AriaColorPickerProps, "children">>, 84 + Pick<PopoverProps, "placement"> { 85 + children?: React.ReactNode; 86 + size?: Size; 87 + label?: string; 88 + } 89 + 90 + function ColorSpaceProvider({ children }: { children: React.ReactNode }) { 91 + const state = use(ColorPickerStateContext); 92 + 93 + if (!state?.color) { 94 + throw new Error("Color needs to be a defined value"); 95 + } 96 + 97 + return ( 98 + <ColorSpaceContext value={state.color.getColorSpace()}> 99 + {children} 100 + </ColorSpaceContext> 101 + ); 102 + } 103 + 104 + export function ColorPicker({ 105 + style, 106 + children, 107 + label, 108 + size: sizeProp, 109 + placement, 110 + ...props 111 + }: ColorPickerProps) { 112 + const popoverStyles = usePopoverStyles(); 113 + const size = sizeProp || use(SizeContext); 114 + 115 + return ( 116 + <SizeContext value={size}> 117 + <AriaColorPicker {...props} {...stylex.props(styles.root, style)}> 118 + <ColorSpaceProvider> 119 + <DialogTrigger> 120 + <Button data-size={size} {...stylex.props(styles.button)}> 121 + <ColorSwatch /> 122 + {label && <span>{label}</span>} 123 + </Button> 124 + <Popover 125 + placement={placement} 126 + {...stylex.props( 127 + popoverStyles.wrapper, 128 + popoverStyles.animation, 129 + styles.popover, 130 + )} 131 + > 132 + <Dialog className="color-picker-dialog">{children}</Dialog> 133 + </Popover> 134 + </DialogTrigger> 135 + </ColorSpaceProvider> 136 + </AriaColorPicker> 137 + </SizeContext> 138 + ); 139 + } 140 + 141 + export interface DefaultColorEditorProps extends FlexProps { 142 + swatches?: string[]; 143 + onSwatchChange?: (color: Color) => void; 144 + hasAlpha?: boolean; 145 + } 146 + 147 + export function DefaultColorEditor({ 148 + style, 149 + swatches, 150 + onSwatchChange, 151 + hasAlpha = true, 152 + ...props 153 + }: DefaultColorEditorProps) { 154 + const colorSpace = use(ColorSpaceContext); 155 + const state = use(ColorPickerStateContext); 156 + 157 + return ( 158 + <Flex 159 + direction="column" 160 + gap="3" 161 + {...props} 162 + style={[styles.defaultPicker, style]} 163 + > 164 + {colorSpace === "hsb" ? ( 165 + <ColorArea 166 + colorSpace={colorSpace} 167 + xChannel="saturation" 168 + yChannel="brightness" 169 + /> 170 + ) : colorSpace === "hsl" ? ( 171 + <ColorArea 172 + colorSpace={colorSpace} 173 + xChannel="hue" 174 + yChannel="saturation" 175 + /> 176 + ) : ( 177 + <ColorArea colorSpace={colorSpace} xChannel="red" yChannel="green" /> 178 + )} 179 + 180 + <Separator style={styles.separator} /> 181 + 182 + <Flex gap="2" align="center"> 183 + <IconButton label="Pick color" variant="outline"> 184 + <Pipette /> 185 + </IconButton> 186 + <Select 187 + aria-label="Color format" 188 + value={colorSpace} 189 + onChange={(key) => { 190 + state?.setColor(state.color.toFormat(key as ColorSpace)); 191 + }} 192 + > 193 + <SelectItem id="hsb">HSB</SelectItem> 194 + <SelectItem id="hsl">HSL</SelectItem> 195 + <SelectItem id="rgb">RGB</SelectItem> 196 + </Select> 197 + <ColorField 198 + aria-label="HEX code" 199 + colorSpace={colorSpace} 200 + style={styles.grow} 201 + /> 202 + {hasAlpha && ( 203 + <ColorField 204 + aria-label="Alpha" 205 + colorSpace={colorSpace} 206 + channel="alpha" 207 + style={styles.grow} 208 + /> 209 + )} 210 + </Flex> 211 + 212 + <Separator style={styles.separator} /> 213 + 214 + <SizeContext value="sm"> 215 + <Flex direction="column" gap="3" style={styles.controls}> 216 + {colorSpace === "hsb" ? ( 217 + <> 218 + <ColorSlider label="Hue" channel="hue" colorSpace={colorSpace} /> 219 + <ColorSlider 220 + label="Saturation" 221 + channel="saturation" 222 + colorSpace={colorSpace} 223 + /> 224 + <ColorSlider 225 + label="Brightness" 226 + channel="brightness" 227 + colorSpace={colorSpace} 228 + /> 229 + </> 230 + ) : colorSpace === "hsl" ? ( 231 + <> 232 + <ColorSlider label="Hue" channel="hue" colorSpace={colorSpace} /> 233 + <ColorSlider 234 + label="Saturation" 235 + channel="saturation" 236 + colorSpace={colorSpace} 237 + /> 238 + <ColorSlider 239 + label="Lightness" 240 + channel="lightness" 241 + colorSpace={colorSpace} 242 + /> 243 + </> 244 + ) : ( 245 + <> 246 + <ColorSlider label="Red" channel="red" colorSpace={colorSpace} /> 247 + <ColorSlider 248 + label="Green" 249 + channel="green" 250 + colorSpace={colorSpace} 251 + /> 252 + <ColorSlider 253 + label="Blue" 254 + channel="blue" 255 + colorSpace={colorSpace} 256 + /> 257 + </> 258 + )} 259 + 260 + {hasAlpha && ( 261 + <ColorSlider 262 + label="Alpha" 263 + channel="alpha" 264 + colorSpace={colorSpace} 265 + /> 266 + )} 267 + </Flex> 268 + </SizeContext> 269 + {swatches && ( 270 + <> 271 + <Separator style={styles.separator} /> 272 + <Flex direction="column" align="center"> 273 + <ColorSwatchPicker onChange={onSwatchChange}> 274 + {swatches.map((swatch) => ( 275 + <ColorSwatchPickerItem key={swatch} color={swatch} /> 276 + ))} 277 + </ColorSwatchPicker> 278 + </Flex> 279 + </> 280 + )} 281 + </Flex> 282 + ); 283 + }
+8 -2
packages/hip-ui/src/components/color-slider/index.tsx
··· 22 22 display: "grid", 23 23 flexDirection: "column", 24 24 gap: spacing["2"], 25 - gridTemplateAreas: "'label value-label' 'track track'", 25 + gridTemplateAreas: { 26 + default: "'track'", 27 + ":has(label,[data-slider-output])": "'label value-label' 'track track'", 28 + }, 26 29 }, 27 30 label: { 28 31 gridArea: "label", ··· 84 87 > 85 88 {label && <Label style={styles.label}>{label}</Label>} 86 89 {showValueLabel && ( 87 - <SliderOutput {...stylex.props(styles.valueLabel)} /> 90 + <SliderOutput 91 + data-slider-output 92 + {...stylex.props(styles.valueLabel)} 93 + /> 88 94 )} 89 95 <SliderTrack 90 96 {...stylex.props(styles.track)}
+4 -8
packages/hip-ui/src/components/theme/types.ts
··· 21 21 | "warning" 22 22 | "critical"; 23 23 24 - export type StyleXComponentProps< 25 - T extends { 26 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 27 - className?: any; 28 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 29 - style?: any; 30 - }, 31 - > = Omit<T, "className" | "style"> & { 24 + export type StyleXComponentProps<T extends object> = Omit< 25 + T, 26 + "className" | "style" 27 + > & { 32 28 className?: never; 33 29 /** 34 30 * The style to apply to the component.
+1 -1
packages/hip-ui/src/components/theme/useInputStyles.ts
··· 121 121 field: [styles.field], 122 122 wrapper: [ 123 123 styles.inputWrapper, 124 - variant === "primary" && [ui.bgUi, styles.primary], 124 + variant === "primary" && [ui.bgGhost, styles.primary], 125 125 variant === "secondary" && [ui.bgUi], 126 126 variant === "tertiary" && [ui.bgGhost], 127 127 ui.text,