-
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.
Merge branch 'padms/2010' into staging
- Loading branch information
Showing
19 changed files
with
527 additions
and
9 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,144 @@ | ||
/* 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, | ||
highlightTitle: 'Highlight text selected from theme below', | ||
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 (for title)', | ||
description: | ||
'When you have selected highlight in the title, choose colour combination for the title text/background. If no highlighted is selected colour will be black or white (on blue background) If no theme is selected the default is white background with black text.', | ||
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', | ||
} | ||
}, | ||
}, | ||
} |
Oops, something went wrong.