- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #258 from riccardoperra/90-gradient-as-theme-frame…
…-background-color feat: add theme gradients
- v1.9.0
- v1.8.5
- v1.8.4
- v1.8.3
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.2
- v1.7.1
- v1.7.0
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.1
- v1.5.0
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.1
- v1.3.0
- v1.2.0
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.10
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.2
- v1.0.0
- v0.21.4
- v0.21.3
- v0.21.2
- v0.21.1
- v0.21.0
- v0.20.0
- v0.19.2
- v0.19.1
- v0.19.0
- v0.18.0
Showing
42 changed files
with
998 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
'@codeimage/app': minor | ||
'@codeimage/config': minor | ||
'@codeimage/theme': minor | ||
'@codeimage/ui': minor | ||
--- | ||
|
||
feat: add support for gradient colors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
apps/codeimage/src/components/PropertyEditor/SidebarPopoverHost.css.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import {themeVars} from '@codeimage/ui'; | ||
import {style} from '@vanilla-extract/css'; | ||
import {scaffoldVars} from '../Scaffold/Scaffold.css'; | ||
|
||
export const wrapper = style({ | ||
marginLeft: `calc(${scaffoldVars.panelWidth} + 10px)`, | ||
position: 'absolute', | ||
maxWidth: scaffoldVars.panelWidth, | ||
height: '100%', | ||
width: '100%', | ||
zIndex: themeVars.zIndex['50'], | ||
}); |
7 changes: 7 additions & 0 deletions
7
apps/codeimage/src/components/PropertyEditor/SidebarPopoverHost.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import * as styles from './SidebarPopoverHost.css'; | ||
|
||
export const SIDEBAR_POPOVER_HOST_ID = 'sidebar-popover-host'; | ||
|
||
export function SidebarPopoverHost() { | ||
return <div class={styles.wrapper} id={SIDEBAR_POPOVER_HOST_ID} />; | ||
} |
24 changes: 24 additions & 0 deletions
24
apps/codeimage/src/components/PropertyEditor/controls/CustomColorPicker.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {AVAILABLE_COLORS, AVAILABLE_GRADIENTS} from '@codeimage/config'; | ||
import {ColorPicker} from '@codeimage/ui'; | ||
import {Middleware} from '@floating-ui/dom'; | ||
import {SIDEBAR_POPOVER_HOST_ID} from '../SidebarPopoverHost'; | ||
|
||
export type CustomColorPickerProps = Parameters<typeof ColorPicker>[0]; | ||
|
||
export function CustomColorPicker(props: CustomColorPickerProps) { | ||
const resetFloatingHorizontalSpace: Middleware = { | ||
name: 'reset-h-space', | ||
fn: () => ({x: 0}), | ||
}; | ||
|
||
return ( | ||
<ColorPicker | ||
colors={AVAILABLE_COLORS} | ||
gradients={AVAILABLE_GRADIENTS} | ||
popoverRoot={SIDEBAR_POPOVER_HOST_ID} | ||
popoverPlacement={'right-start'} | ||
popoverMiddlewares={[resetFloatingHorizontalSpace]} | ||
{...props} | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export const uiLocale = { | ||
it: { | ||
colorPicker: { | ||
color: 'Colore', | ||
gradient: 'Gradiente', | ||
}, | ||
}, | ||
en: { | ||
colorPicker: { | ||
color: 'Color', | ||
gradient: 'Gradient', | ||
}, | ||
}, | ||
de: { | ||
colorPicker: { | ||
color: 'Color', | ||
gradient: 'Gradient', | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
export const AVAILABLE_COLORS = [ | ||
'#000000', | ||
'#1a1a1a', | ||
'#1e222f', | ||
'#213043', | ||
'#383c4a', | ||
'#999999', | ||
'#A2B1D2', | ||
'#FFFFFF', | ||
'#da4d4d', | ||
'#e97171', | ||
'#FF88AA', | ||
'#fdad5d', | ||
'#e3db2a', | ||
'#FFEE66', | ||
'#ffcc99', | ||
'#7e3bdf', | ||
'#8663ed', | ||
'#BD93F9', | ||
'#d4b8ff', | ||
'#79a1ff', | ||
'#4455BB', | ||
'#1e88df', | ||
'#1b55d9', | ||
'#1a3f95', | ||
'#1c933f', | ||
'#64e7a3', | ||
'#21d5b8', | ||
'#06535d', | ||
]; | ||
|
||
export const AVAILABLE_GRADIENTS = [ | ||
// Purple | ||
'linear-gradient(-45deg, #402662 0%, #8000FF 100%)', | ||
'linear-gradient(135deg, #6a3cc0 0%, #240573 100%)', | ||
'linear-gradient(to right top, #7f469d, #8242aa, #833db7, #8338c4, #8233d2, #8a35da, #9336e2, #9b38ea, #af41ee, #c24af2, #d554f7, #e65ffb)', | ||
'linear-gradient(135deg, rgba(171,73,222,1) 0%,rgba(73,84,222,1) 100%)', | ||
// Blue | ||
'linear-gradient(to right top, #3547be, #285acd, #186ddb, #047ee7, #0090f2, #0091f3, #0091f4, #0092f5, #0082ec, #0071e2, #0060d7, #174ecb)', | ||
'linear-gradient(135deg, rgba(73,84,222,1) 0%,rgba(73,221,216,1) 100%)', | ||
'linear-gradient(135deg, #54D2EF 0%, #2AA6DA 100%)', | ||
'linear-gradient(135deg, #2AA6DA 0%, #1B7B77 100%)', | ||
// Green | ||
'linear-gradient(to right bottom, #1e737e, #186b76, #13636d, #0d5b65, #06535d)', | ||
'linear-gradient(to right bottom, #00ffc7, #00c6a5, #148f7e, #205b55, #1e2c2b)', | ||
'linear-gradient(to right bottom, #2be7b5, #1edea2, #16d58f, #13cb7c, #16c268, #0db866, #04ae64, #00a462, #00976c, #008971, #007b72, #006d6d)', | ||
'linear-gradient(135deg, #33CC99 0%, #FFCC33 100%)', | ||
'linear-gradient(135deg, rgba(73,221,216,1) 0%,rgba(25,226,115,1) 100%)', | ||
// Red | ||
'linear-gradient(135deg, #FFE174 0%, #FFBF40 100%)', | ||
'linear-gradient(to right bottom, #ffcc99, #f6bd83, #edad6e, #e49e59, #da8f44)', | ||
'linear-gradient(to right bottom, #f66283, #e45475, #d34768, #c2395b, #b12a4e, #a92246, #a1183e, #990d36, #970931, #95052b, #930226, #900020)', | ||
'linear-gradient(135deg, #E233FF 0%, #FF6B00 100%)', | ||
// Mix | ||
'linear-gradient(135deg, #FF0076 0%, #590FB7 100%)', | ||
'linear-gradient(to right bottom, #d44be1, #c945d7, #be3fcd, #b43ac3, #a934b9, #b330af, #bb2ca6, #c12a9c, #d6308f, #e73c83, #f34d77, #fb5f6d)', | ||
'linear-gradient(-45deg, #402662 0%, #F59ABE 100%)', | ||
// Light | ||
'linear-gradient(62deg, #8EC5FC 0%, #E0C3FC 100%)', | ||
'linear-gradient(to right bottom, #82aaff, #6c88cb, #566899, #3f4969, #292d3e)', | ||
'linear-gradient(to right bottom, #e5e5e5, #d0cfd5, #bbbac5, #a5a6b6, #9092a7, #83869d, #777a93, #6a6f89, #646881, #5d6279, #575b71, #515569)', | ||
'linear-gradient(135deg, #CECED8 0%, #FFFFFF 100%)', | ||
'linear-gradient(to right bottom, #393939, #343435, #2f3030, #2b2b2c, #262727)', | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { | ||
createSignal, | ||
mergeProps, | ||
onMount, | ||
PropsWithChildren, | ||
Show, | ||
} from 'solid-js'; | ||
import {Portal} from 'solid-js/web'; | ||
|
||
const DEFAULT_ID = 'floating-ui-root'; | ||
|
||
export interface CreateFloatingPortalNodeProps { | ||
id?: string; | ||
} | ||
|
||
export const createFloatingPortalNode = ( | ||
props: CreateFloatingPortalNodeProps, | ||
) => { | ||
const [portal, setPortal] = createSignal<HTMLElement | null>(null); | ||
const propsWithDefault = mergeProps({id: DEFAULT_ID}, props); | ||
|
||
onMount(() => { | ||
const rootNode = document.getElementById(propsWithDefault.id); | ||
if (rootNode) { | ||
setPortal(rootNode); | ||
} else { | ||
const element = document.createElement('div'); | ||
element.id = propsWithDefault.id; | ||
setPortal(element); | ||
} | ||
}); | ||
return portal; | ||
}; | ||
|
||
export interface FloatingPortalProps { | ||
id?: string; | ||
root?: HTMLElement | null; | ||
} | ||
|
||
export const FloatingPortal = ( | ||
props: PropsWithChildren<FloatingPortalProps>, | ||
) => { | ||
const portalNode = createFloatingPortalNode({id: props.id}); | ||
|
||
return ( | ||
<Show when={portalNode()}> | ||
{node => <Portal mount={node}>{props.children}</Portal>} | ||
</Show> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 41 additions & 12 deletions
53
packages/ui/src/lib/primitives/ColorPicker/ColorPicker.css.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,50 @@ | ||
import {style} from '@vanilla-extract/css'; | ||
import {baseField} from '../TextField/TextField.css'; | ||
import {themeVars} from '../../theme'; | ||
import {recipe, RecipeVariants} from '@vanilla-extract/recipes'; | ||
import {backgroundColorVar, themeVars} from '../../theme'; | ||
import * as textFieldStyles from '../TextField/TextField.css'; | ||
|
||
export const colorPicker = style([ | ||
baseField, | ||
export const wrapper = style({ | ||
display: 'flex', | ||
width: '100%', | ||
}); | ||
|
||
export const input = style([ | ||
textFieldStyles.baseField, | ||
{ | ||
padding: themeVars.spacing['1'], | ||
flex: 1, | ||
}, | ||
{ | ||
appearance: 'none', | ||
]); | ||
|
||
export const inputColor = style({ | ||
borderRadius: themeVars.borderRadius.md, | ||
width: themeVars.width.full, | ||
height: '100%', | ||
background: backgroundColorVar, | ||
}); | ||
|
||
selectors: { | ||
'&::-webkit-color-swatch-wrapper': {}, | ||
'&::-webkit-color-swatch': { | ||
border: 0, | ||
borderRadius: themeVars.borderRadius.md, | ||
export const colorGrid = style({ | ||
display: 'grid', | ||
gap: themeVars.spacing['3'], | ||
gridTemplateColumns: 'repeat(6, 1fr)', | ||
}); | ||
|
||
export const colorItem = recipe({ | ||
base: { | ||
borderRadius: themeVars.borderRadius.full, | ||
cursor: 'pointer', | ||
width: '28px', | ||
height: '28px', | ||
background: backgroundColorVar, | ||
boxShadow: themeVars.boxShadow.md, | ||
}, | ||
variants: { | ||
active: { | ||
true: { | ||
boxShadow: themeVars.boxShadow.outline, | ||
}, | ||
}, | ||
}, | ||
]); | ||
}); | ||
|
||
export type ColorPickerColorItemProps = RecipeVariants<typeof colorItem>; |
147 changes: 119 additions & 28 deletions
147
packages/ui/src/lib/primitives/ColorPicker/ColorPicker.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,126 @@ | ||
import { | ||
DynamicProps, | ||
WithRef, | ||
} from 'solid-headless/dist/types/utils/dynamic-prop'; | ||
import {Component} from 'solid-js'; | ||
import {omitProps} from 'solid-use'; | ||
import {styled} from '../../utils'; | ||
import {autoPlacement, Middleware, Placement} from '@floating-ui/dom'; | ||
import {createButton} from '@solid-aria/button'; | ||
import {createOverlayTrigger, OverlayContainer} from '@solid-aria/overlays'; | ||
import {assignInlineVars} from '@vanilla-extract/dynamic'; | ||
import {PropsWithChildren, Show} from 'solid-js'; | ||
import {useFloating} from '../../hooks'; | ||
import {backgroundColorVar} from '../../theme'; | ||
import {Box} from '../Box'; | ||
import {Popover} from '../Popover'; | ||
import {createPopoverPortal} from '../Popover/create-popover-portal'; | ||
import * as styles from './ColorPicker.css'; | ||
import {ColorPickerColorItemProps} from './ColorPicker.css'; | ||
import {ColorPickerPopover} from './ColorPickerPopover'; | ||
|
||
type ColorPickerProps = { | ||
value?: string; | ||
onChange?: (value: string) => void; | ||
} & WithRef<'input'> & | ||
Omit<DynamicProps<'input'>, 'as' | 'ref' | 'onInput' | 'onChange' | 'value'>; | ||
export interface ColorPickerProps { | ||
value: string | undefined; | ||
onChange: (value: string) => void; | ||
title?: string; | ||
colors?: string[]; | ||
gradients?: string[]; | ||
popoverPlacement?: Placement; | ||
popoverRoot?: string; | ||
popoverMiddlewares?: Middleware[]; | ||
} | ||
|
||
export const ColorPicker: Component<ColorPickerProps> = props => { | ||
function onChange(e: Event): void { | ||
if (props.onChange) { | ||
const target = e.target as HTMLInputElement; | ||
props.onChange(target.value); | ||
} | ||
} | ||
export function ColorPicker(props: PropsWithChildren<ColorPickerProps>) { | ||
let triggerRef: HTMLButtonElement | undefined; | ||
|
||
const {triggerProps, overlayProps, state} = createOverlayTrigger({ | ||
type: 'dialog', | ||
}); | ||
|
||
const {buttonProps} = createButton( | ||
{ | ||
onPress: () => state.open(), | ||
}, | ||
() => triggerRef, | ||
); | ||
|
||
const portal = createPopoverPortal({id: props.popoverRoot}); | ||
|
||
const floating = useFloating({ | ||
strategy: 'absolute', | ||
placement: 'right-start', | ||
middleware: [ | ||
autoPlacement({ | ||
allowedPlacements: [ | ||
'right-start', | ||
'top-start', | ||
'bottom-start', | ||
'left-start', | ||
], | ||
}), | ||
...(props?.popoverMiddlewares ?? []), | ||
], | ||
}); | ||
|
||
return ( | ||
<> | ||
<button | ||
{...buttonProps()} | ||
{...triggerProps()} | ||
class={styles.input} | ||
ref={ref => { | ||
triggerRef = ref; | ||
floating.setReference(ref); | ||
}} | ||
> | ||
<div | ||
class={styles.inputColor} | ||
style={assignInlineVars({ | ||
[backgroundColorVar]: props.value ?? '#000000', | ||
})} | ||
/> | ||
</button> | ||
|
||
<Show when={state.isOpen()}> | ||
<OverlayContainer portalContainer={portal()!}> | ||
<Popover | ||
{...overlayProps()} | ||
ref={floating.setFloating} | ||
title={props.title} | ||
style={{ | ||
top: `${floating.y}px`, | ||
left: `${floating.x}px`, | ||
position: floating.strategy, | ||
}} | ||
isOpen={state.isOpen()} | ||
onClose={state.close} | ||
> | ||
<ColorPickerPopover | ||
value={props.value} | ||
onChange={props.onChange} | ||
colors={props.colors} | ||
gradientColors={props.gradients} | ||
/> | ||
</Popover> | ||
</OverlayContainer> | ||
</Show> | ||
</> | ||
); | ||
} | ||
|
||
type ColorPickerPresetItemProps = { | ||
title: string; | ||
color: string; | ||
onClick: (color: string) => void; | ||
active: boolean; | ||
} & ColorPickerColorItemProps; | ||
|
||
export function ColorPickerPresetItem( | ||
props: PropsWithChildren<ColorPickerPresetItemProps>, | ||
) { | ||
return ( | ||
<styled.input | ||
component={'input'} | ||
class={styles.colorPicker} | ||
value={props.value} | ||
onInput={onChange} | ||
onChange={onChange} | ||
type={'color'} | ||
{...omitProps(props, ['class', 'type', 'value', 'onChange'])} | ||
<Box | ||
class={styles.colorItem({ | ||
active: props.active, | ||
})} | ||
title={props.title} | ||
style={assignInlineVars({ | ||
[backgroundColorVar]: props.color, | ||
})} | ||
onClick={() => props.onClick(props.color)} | ||
/> | ||
); | ||
}; | ||
} |
109 changes: 109 additions & 0 deletions
109
packages/ui/src/lib/primitives/ColorPicker/ColorPickerPopover.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { | ||
Accessor, | ||
createEffect, | ||
createMemo, | ||
createSignal, | ||
For, | ||
on, | ||
onMount, | ||
Show, | ||
} from 'solid-js'; | ||
import {VStack} from '../Box'; | ||
import {FlexField} from '../Field'; | ||
import {SegmentedField, SegmentedFieldItem} from '../SegmentedField'; | ||
import {TextField} from '../TextField'; | ||
import {ColorPickerPresetItem} from './ColorPicker'; | ||
import * as styles from './ColorPicker.css'; | ||
import {useI18n} from '@codeimage/locale'; | ||
|
||
enum ColorPickerSelectionMode { | ||
gradient = 'gradient', | ||
color = 'color', | ||
} | ||
|
||
export interface ColorPickerPopoverProps { | ||
value?: string | null; | ||
onChange: (value: string) => void; | ||
gradientColors?: string[]; | ||
colors?: string[]; | ||
} | ||
|
||
export function ColorPickerPopover(props: ColorPickerPopoverProps) { | ||
const [internalColor, setInternalColor] = createSignal<string>(); | ||
const [mode, setMode] = createSignal(ColorPickerSelectionMode.gradient); | ||
const [, {tUnsafe}] = useI18n(); | ||
createEffect(on(() => props.value, setInternalColor)); | ||
|
||
const modalities: Accessor<SegmentedFieldItem<ColorPickerSelectionMode>[]> = | ||
createMemo(() => [ | ||
{ | ||
label: tUnsafe('colorPicker.gradient'), | ||
value: ColorPickerSelectionMode.gradient, | ||
}, | ||
{ | ||
label: tUnsafe('colorPicker.color'), | ||
value: ColorPickerSelectionMode.color, | ||
}, | ||
]); | ||
|
||
onMount(() => { | ||
if (props.colors?.includes(props.value ?? '')) { | ||
setMode(ColorPickerSelectionMode.color); | ||
} else { | ||
setMode(ColorPickerSelectionMode.gradient); | ||
} | ||
}); | ||
|
||
return ( | ||
<VStack spacing={'4'}> | ||
<FlexField size={'md'}> | ||
<SegmentedField | ||
value={mode()} | ||
onChange={setMode} | ||
items={modalities()} | ||
/> | ||
</FlexField> | ||
|
||
<FlexField size={'xs'}> | ||
<TextField | ||
size={'xs'} | ||
type={'text'} | ||
value={internalColor()} | ||
onChange={value => props.onChange(value)} | ||
tabIndex={-1} | ||
/> | ||
</FlexField> | ||
|
||
<Show when={mode() === ColorPickerSelectionMode.color}> | ||
<div class={styles.colorGrid}> | ||
<For each={props.colors}> | ||
{item => ( | ||
<ColorPickerPresetItem | ||
color={item} | ||
title={item} | ||
active={props.value === item} | ||
onClick={() => { | ||
props.onChange(item); | ||
}} | ||
/> | ||
)} | ||
</For> | ||
</div> | ||
</Show> | ||
<Show when={mode() === ColorPickerSelectionMode.gradient}> | ||
<div class={styles.colorGrid}> | ||
<For each={props.gradientColors}> | ||
{item => ( | ||
<ColorPickerPresetItem | ||
color={item} | ||
title={item} | ||
active={props.value === item} | ||
onClick={() => props.onChange(item)} | ||
/> | ||
)} | ||
</For> | ||
</div> | ||
</Show> | ||
</VStack> | ||
); | ||
} |
21 changes: 21 additions & 0 deletions
21
packages/ui/src/lib/primitives/ColorPicker/NativeColorPicker.css.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import {style} from '@vanilla-extract/css'; | ||
import {baseField} from '../TextField/TextField.css'; | ||
import {themeVars} from '../../theme'; | ||
|
||
export const colorPicker = style([ | ||
baseField, | ||
{ | ||
flex: 1, | ||
}, | ||
{ | ||
appearance: 'none', | ||
|
||
selectors: { | ||
'&::-webkit-color-swatch-wrapper': {}, | ||
'&::-webkit-color-swatch': { | ||
border: 0, | ||
borderRadius: themeVars.borderRadius.md, | ||
}, | ||
}, | ||
}, | ||
]); |
35 changes: 35 additions & 0 deletions
35
packages/ui/src/lib/primitives/ColorPicker/NativeColorPicker.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { | ||
DynamicProps, | ||
WithRef, | ||
} from 'solid-headless/dist/types/utils/dynamic-prop'; | ||
import {Component} from 'solid-js'; | ||
import {omitProps} from 'solid-use'; | ||
import {styled} from '../../utils'; | ||
import * as styles from './NativeColorPicker.css'; | ||
|
||
type ColorPickerProps = { | ||
value?: string; | ||
onChange?: (value: string) => void; | ||
} & WithRef<'input'> & | ||
Omit<DynamicProps<'input'>, 'as' | 'ref' | 'onInput' | 'onChange' | 'value'>; | ||
|
||
export const NativeColorPicker: Component<ColorPickerProps> = props => { | ||
function onChange(e: Event): void { | ||
if (props.onChange) { | ||
const target = e.target as HTMLInputElement; | ||
props.onChange(target.value); | ||
} | ||
} | ||
|
||
return ( | ||
<styled.input | ||
component={'input'} | ||
class={styles.colorPicker} | ||
value={props.value} | ||
onInput={onChange} | ||
onChange={onChange} | ||
type={'color'} | ||
{...omitProps(props, ['class', 'type', 'value', 'onChange'])} | ||
/> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './NativeColorPicker'; | ||
export * from './ColorPicker'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import {style} from '@vanilla-extract/css'; | ||
import {themeVars} from '../../theme'; | ||
import {fontSize, fontWeight} from '../Text/Text.css'; | ||
|
||
export const container = style({ | ||
overflow: 'hidden', | ||
borderRadius: themeVars.borderRadius.lg, | ||
backgroundColor: themeVars.dynamicColors.panel.background, | ||
color: themeVars.dynamicColors.panel.textColor, | ||
display: 'flex', | ||
flexDirection: 'column', | ||
width: '260px', | ||
boxShadow: themeVars.dynamicColors.dialog.panelShadow, | ||
maxWidth: '300px', | ||
|
||
':focus-visible': { | ||
outline: 'none', | ||
boxShadow: themeVars.boxShadow.outline, | ||
}, | ||
}); | ||
|
||
export const title = style([ | ||
fontSize.sm, | ||
fontWeight.semibold, | ||
{ | ||
padding: themeVars.spacing['4'], | ||
marginTop: 0, | ||
paddingBottom: 0, | ||
}, | ||
]); | ||
|
||
export const content = style({ | ||
padding: themeVars.spacing['4'], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import {createDialog} from '@solid-aria/dialog'; | ||
import {FocusScope} from '@solid-aria/focus'; | ||
import { | ||
AriaOverlayProps, | ||
createModal, | ||
createOverlay, | ||
DismissButton, | ||
} from '@solid-aria/overlays'; | ||
import {combineProps} from '@solid-primitives/props'; | ||
import {mergeRefs} from '@solid-primitives/refs'; | ||
import {access} from '@solid-primitives/utils'; | ||
import {createMemo, JSX, Show, splitProps} from 'solid-js'; | ||
import * as styles from './Popover.css'; | ||
|
||
interface PopoverProps extends AriaOverlayProps { | ||
ref: HTMLDivElement | ((ref: HTMLDivElement) => void) | undefined; | ||
style?: JSX.CSSProperties | string; | ||
class?: string; | ||
title?: JSX.Element; | ||
children?: JSX.Element; | ||
} | ||
|
||
export function Popover(props: PopoverProps) { | ||
let ref: HTMLDivElement | undefined; | ||
|
||
const [local, others] = splitProps(props, [ | ||
'ref', | ||
'class', | ||
'title', | ||
'children', | ||
'isOpen', | ||
'onClose', | ||
]); | ||
|
||
// Handle interacting outside the dialog and pressing | ||
// the Escape key to close the modal. | ||
const {overlayProps} = createOverlay( | ||
{ | ||
onClose: local.onClose, | ||
isOpen: () => access(local.isOpen), | ||
isDismissable: true, | ||
}, | ||
() => ref, | ||
); | ||
|
||
// Hide content outside the modal from screen readers. | ||
const {modalProps} = createModal(); | ||
|
||
// Get props for the dialog and its title | ||
const {dialogProps, titleProps} = createDialog({}, () => ref); | ||
|
||
const rootProps = createMemo(() => { | ||
return combineProps(overlayProps(), dialogProps(), modalProps(), others); | ||
}); | ||
|
||
return ( | ||
<FocusScope restoreFocus> | ||
<div | ||
{...rootProps()} | ||
ref={mergeRefs(el => (ref = el), local.ref)} | ||
class={styles.container} | ||
> | ||
<Show when={!!props.title}> | ||
<h3 {...titleProps} class={styles.title}> | ||
{props.title} | ||
</h3> | ||
<div class={styles.content}>{props.children}</div> | ||
</Show> | ||
<DismissButton onDismiss={local.onClose} /> | ||
</div> | ||
</FocusScope> | ||
); | ||
} |
18 changes: 18 additions & 0 deletions
18
packages/ui/src/lib/primitives/Popover/create-popover-portal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import {mergeProps} from 'solid-js'; | ||
import { | ||
createFloatingPortalNode, | ||
CreateFloatingPortalNodeProps, | ||
} from '../../floating/floating-portal'; | ||
|
||
export const DEFAULT_PORTAL_POPOVER_ID = 'floating-portal-popover'; | ||
|
||
export function createPopoverPortal(props?: CreateFloatingPortalNodeProps) { | ||
const propsWithDefault = mergeProps( | ||
{ | ||
id: DEFAULT_PORTAL_POPOVER_ID, | ||
}, | ||
props, | ||
); | ||
|
||
return createFloatingPortalNode(propsWithDefault); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {Popover} from './Popover'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.