-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
502 additions
and
4 deletions.
There are no files selected for viewing
103 changes: 103 additions & 0 deletions
103
sanityv3/schemas/components/ThemeSelector/ThemeSelector.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,103 @@ | ||
import { Box, Card, Flex, Stack, Tooltip, Text } from '@sanity/ui' | ||
import { useCallback } from 'react' | ||
import { set } from 'sanity' | ||
import type { ObjectInputProps } from 'sanity' | ||
import styled from 'styled-components' | ||
import { defaultColors, getColorForTheme } from './defaultColors' | ||
import { EdsIcon } from '../../../icons' | ||
import { text_field } from '@equinor/eds-icons' | ||
|
||
const Circle = styled.div<{ active: boolean }>` | ||
display: inline-block; | ||
border: solid 2px ${({ active }) => (active ? 'var(--card-focus-ring-color)' : 'transparent')}; | ||
border-radius: 50%; | ||
padding: 4px; | ||
cursor: pointer; | ||
` | ||
|
||
const InnerCircle = styled.div<{ color: string; fillColor: string }>` | ||
display: flex; | ||
background-color: ${({ color }) => color}; | ||
border: 1px solid var(--card-hairline-soft-color); | ||
padding: 15px; | ||
border-radius: 50%; | ||
color: ${({ fillColor }) => fillColor}; | ||
` | ||
|
||
export type ThemeSelectorValue = { | ||
title: string | ||
value: number | ||
} | ||
|
||
type ColorCircleProps = { | ||
color: ThemeSelectorValue | ||
active: boolean | ||
onClickHandler: (val: ThemeSelectorValue) => void | ||
} | ||
|
||
const ColorCircle = ({ color, active, onClickHandler }: ColorCircleProps) => { | ||
const { background, highlight } = getColorForTheme(color.value) | ||
return ( | ||
<Card paddingY={1}> | ||
<Tooltip | ||
content={ | ||
<Box padding={2}> | ||
<Text muted size={1}> | ||
{color.title} | ||
</Text> | ||
</Box> | ||
} | ||
fallbackPlacements={['right', 'left']} | ||
placement="top" | ||
portal | ||
> | ||
<Circle active={active} onClick={() => onClickHandler(color)}> | ||
<InnerCircle color={background} fillColor={highlight}> | ||
<EdsIcon {...text_field} /> | ||
</InnerCircle> | ||
</Circle> | ||
</Tooltip> | ||
</Card> | ||
) | ||
} | ||
|
||
type ThemeSelectorProps = ObjectInputProps | ||
|
||
export const ThemeSelector = ({ value, onChange, schemaType }: ThemeSelectorProps) => { | ||
const { options } = schemaType | ||
const colors = (options?.colors as ThemeSelectorValue[]) || defaultColors | ||
|
||
const handleSelect = useCallback( | ||
(selected: ThemeSelectorValue) => { | ||
if (selected === value) return | ||
|
||
onChange(set(selected.title, ['title'])) | ||
onChange(set(selected.value, ['value'])) | ||
}, | ||
[onChange, value], | ||
) | ||
|
||
return ( | ||
<Stack space={3}> | ||
{colors && ( | ||
<Card> | ||
<Flex direction={'row'} wrap={'wrap'}> | ||
{colors.map((colorItem: ThemeSelectorValue) => { | ||
const { background } = getColorForTheme(colorItem.value) | ||
return ( | ||
<ColorCircle | ||
key={background} | ||
color={colorItem} | ||
active={colorItem.value === value?.value} | ||
onClickHandler={handleSelect} | ||
/> | ||
) | ||
})} | ||
</Flex> | ||
</Card> | ||
)} | ||
</Stack> | ||
) | ||
} | ||
|
||
export default ThemeSelector |
36 changes: 36 additions & 0 deletions
36
sanityv3/schemas/components/ThemeSelector/defaultColors.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,36 @@ | ||
export const defaultColors = [ | ||
{ title: 'White', value: 0 }, | ||
{ title: 'Moss Green Light', value: 1 }, | ||
{ title: 'Spruce Wood', value: 2 }, | ||
{ title: 'Mist Blue', value: 3 }, | ||
{ title: 'Mid Yellow', value: 4 }, | ||
{ title: 'Mid Orange', value: 5 }, | ||
{ title: 'Mid Blue 1', value: 6 }, | ||
{ title: 'Mid Blue 2', value: 7 }, | ||
{ title: 'Mid Green', value: 8 }, | ||
] | ||
|
||
export const getColorForTheme = (pattern: number) => { | ||
switch (pattern) { | ||
case 1: | ||
return { background: 'hsl(184, 30%, 96%)', highlight: 'hsl(348, 100%, 54%)' } | ||
case 2: | ||
return { background: 'hsl(25, 100%, 94%)', highlight: 'hsl(348, 100%, 54%)' } | ||
case 3: | ||
return { background: 'hsl(199, 58%, 90%)', highlight: 'hsl(348, 100%, 54%)' } | ||
case 4: | ||
return { background: '#FFF5B8', highlight: 'hsl(348, 100%, 54%)' } | ||
case 5: | ||
return { background: '#F8D1AF', highlight: 'hsl(348, 100%, 54%)' } | ||
case 6: | ||
return { background: '#49709C', highlight: '#F8D1AF' } | ||
case 7: | ||
return { background: '#49709C', highlight: '#FFF5B8' } | ||
case 8: | ||
return { background: '#C3E4CE', highlight: 'hsl(348, 100%, 54%)' } | ||
|
||
case 0: | ||
default: | ||
return { background: 'hsl(0, 0%, 100%)', highlight: 'hsl(348, 100%, 54%)' } | ||
} | ||
} |
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,2 @@ | ||
export * from './ThemeSelector' | ||
export * from './defaultColors' |
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,4 +1,4 @@ | ||
import {ReactNode} from 'react' | ||
import { ReactNode } from 'react' | ||
|
||
type Props = { | ||
children: ReactNode | ||
|
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,142 @@ | ||
/* eslint-disable react/display-name */ | ||
import blocksToText from '../../helpers/blocksToText' | ||
import { LeftAlignedImage, RightAlignedImage } from '../../icons' | ||
import { RadioIconSelector } from '../components' | ||
import CompactBlockEditor from '../components/CompactBlockEditor' | ||
import { configureBlockContent, configureTitleBlockContent } from '../editors' | ||
import { validateCharCounterEditor } from '../validations/validateCharCounterEditor' | ||
|
||
import type { PortableTextBlock, Rule } from 'sanity' | ||
import type { DownloadableImage } from './downloadableImage' | ||
import type { DownloadableFile } from './files' | ||
import type { LinkSelector } from './linkSelector' | ||
import { ThemeSelectorValue } from '../components/ThemeSelector' | ||
|
||
const titleContentType = configureTitleBlockContent({ | ||
highlight: true, | ||
styles: [ | ||
{ | ||
title: 'Normal', | ||
value: 'normal', | ||
}, | ||
], | ||
}) | ||
|
||
const titleAlignmentOptions = [ | ||
{ value: 'left', icon: LeftAlignedImage }, | ||
{ value: 'right', icon: RightAlignedImage }, | ||
] | ||
|
||
const blockConfig = { | ||
h1: false, | ||
h2: false, | ||
h3: false, | ||
h4: false, | ||
internalLink: false, | ||
externalLink: false, | ||
attachment: false, | ||
lists: true, | ||
} | ||
|
||
const blockContentType = configureBlockContent({ ...blockConfig }) | ||
|
||
export type TextTeaser = { | ||
_type: 'textTeaser' | ||
title?: PortableTextBlock[] | ||
text?: PortableTextBlock[] | ||
action?: (LinkSelector | DownloadableFile | DownloadableImage)[] | ||
titlePosition?: string | ||
theme?: ThemeSelectorValue | ||
} | ||
|
||
export default { | ||
name: 'textTeaser', | ||
title: 'Text Teaser', | ||
type: 'object', | ||
localize: true, | ||
fieldsets: [ | ||
{ | ||
name: 'link', | ||
title: 'Link', | ||
description: 'Select either an internal link or external URL.', | ||
}, | ||
{ | ||
name: 'design', | ||
title: 'Design options', | ||
}, | ||
], | ||
fields: [ | ||
{ | ||
name: 'title', | ||
type: 'array', | ||
components: { | ||
input: CompactBlockEditor, | ||
}, | ||
of: [titleContentType], | ||
validation: (Rule: Rule) => Rule.required(), | ||
}, | ||
{ | ||
name: 'text', | ||
title: 'Text content', | ||
type: 'array', | ||
of: [blockContentType], | ||
validation: (Rule: Rule) => | ||
Rule.custom((value: PortableTextBlock[]) => { | ||
return validateCharCounterEditor(value, 600) | ||
}).warning(), | ||
}, | ||
|
||
{ | ||
name: 'action', | ||
title: 'Link/action', | ||
description: 'Select the link or downloadable file for the teaser', | ||
type: 'array', | ||
of: [ | ||
{ type: 'linkSelector', title: 'Link' }, | ||
{ type: 'downloadableImage', title: 'Downloadable image' }, | ||
{ type: 'downloadableFile', title: 'Downloadable file' }, | ||
], | ||
validation: (Rule: Rule) => Rule.max(1).error('Only one action is permitted'), | ||
}, | ||
{ | ||
name: 'titlePosition', | ||
title: 'Title position', | ||
description: 'Select which side of the teaser the title should be displayed at on larger screens.', | ||
type: 'string', | ||
fieldset: 'design', | ||
components: { | ||
input: function ({ onChange, value }: { onChange: any; value: string }) { | ||
return ( | ||
<RadioIconSelector | ||
name="imageAlignmentSelector" | ||
options={titleAlignmentOptions} | ||
defaultValue="left" | ||
currentValue={value} | ||
onChange={onChange} | ||
/> | ||
) | ||
}, | ||
}, | ||
}, | ||
{ | ||
title: 'Theme', | ||
description: 'Pick a colour combination for the background and title highlight. Default is white.', | ||
name: 'theme', | ||
type: 'themeList', | ||
fieldset: 'design', | ||
}, | ||
], | ||
preview: { | ||
select: { | ||
title: 'title', | ||
text: 'text', | ||
}, | ||
prepare({ title, text }: { title: PortableTextBlock[]; text: PortableTextBlock[] }) { | ||
const plainTitle = blocksToText(title) | ||
return { | ||
title: plainTitle || 'Missing teaser title', | ||
subtitle: blocksToText(text) || 'Mising teaser text', | ||
} | ||
}, | ||
}, | ||
} |
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,27 @@ | ||
import { ThemeSelector, defaultColors } from '../components/ThemeSelector' | ||
import { defineType, defineField } from 'sanity' | ||
|
||
export default defineType({ | ||
name: 'themeList', | ||
title: 'Theme', | ||
type: 'object', | ||
fields: [ | ||
defineField({ | ||
name: 'title', | ||
type: 'string', | ||
}), | ||
defineField({ | ||
name: 'value', | ||
type: 'number', | ||
}), | ||
], | ||
initialValue: { | ||
title: defaultColors[0].title, | ||
value: defaultColors[0].value, | ||
}, | ||
components: { | ||
input: (props) => { | ||
return <ThemeSelector {...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
Oops, something went wrong.