Skip to content

Commit 7ea3303

Browse files
🎨 update tabs component #3473 (#3474)
* 🎨 update tabs component * 🎨 classlist spaces * 🎨 more adjustments to tabs component
1 parent bd5c7c5 commit 7ea3303

File tree

13 files changed

+360
-286
lines changed

13 files changed

+360
-286
lines changed

‎sanityv3/schemas/objects/commonFields/commonFields.tsx‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Card, Flex, Grid, Radio, Text } from '@sanity/ui'
22
import { useCallback } from 'react'
3-
import { type Rule, type StringInputProps, set } from 'sanity'
3+
import { defineField, type Rule, type StringInputProps, set } from 'sanity'
44
import { filterByRoute } from '../../../helpers/referenceFilters'
55
import CompactBlockEditor from '../../components/CompactBlockEditor'
66
import { configureBlockContent } from '../../editors'
@@ -64,6 +64,33 @@ export const background = {
6464
fieldset: 'design',
6565
}
6666

67+
export const backgroundPosition = (hiddenCallBack?: any, fieldset?: string) => {
68+
return {
69+
title: 'Select positioning of the image',
70+
description:
71+
'Optional - select focus origin in the image. Useful if the image gets cropped when not contained within its container. Use together with hotspot option in Sanity studio to make sure focal point is kept',
72+
name: 'backgroundPosition',
73+
type: 'string',
74+
options: {
75+
list: [
76+
{ title: 'Center Left', value: 'center_left' },
77+
{ title: 'Center Center', value: 'center_center' },
78+
{ title: 'Center Right', value: 'center_right' },
79+
{ title: 'Top Left', value: 'top_left' },
80+
{ title: 'Top Center', value: 'top_center' },
81+
{ title: 'Top Right', value: 'top_right' },
82+
{ title: 'Bottom Left', value: 'bottom_left' },
83+
{ title: 'Bottom Center', value: 'bottom_center' },
84+
{ title: 'Bottom Right', value: 'bottom_right' },
85+
],
86+
layout: 'dropdown',
87+
},
88+
initialValue: 'center_center',
89+
...(fieldset && { fieldset }),
90+
...(hiddenCallBack && { hidden: hiddenCallBack }),
91+
}
92+
}
93+
6794
export const theme = {
6895
title: 'Theme',
6996
description: 'Theme consisting of an background color and a foreground color for cards or similar',

‎sanityv3/schemas/objects/homepageBanner/index.tsx‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
/* eslint-disable react/display-name */
22
import { Flex, Stack, Text } from '@sanity/ui'
3+
import { defineField, type PortableTextBlock, type PreviewProps, type Rule } from 'sanity'
4+
import styled from 'styled-components'
35
import blocksToText from '../../../helpers/blocksToText'
46
import CompactBlockEditor from '../../components/CompactBlockEditor'
57
import {
68
CardTheme,
79
ThemePreview,
810
ThemeSelector,
9-
ThemeSelectorColor,
10-
ThemeSelectorValue,
11+
type ThemeSelectorColor,
12+
type ThemeSelectorValue,
1113
} from '../../components/ThemeSelector'
1214
import { defaultColors } from '../../defaultColors'
1315
import { configureTitleBlockContent } from '../../editors'
14-
import { defineField, PreviewProps, type PortableTextBlock, type Rule } from 'sanity'
15-
import styled from 'styled-components'
16-
import { ImageWithAlt } from '../imageWithAlt'
16+
import type { ImageWithAlt } from '../imageWithAlt'
1717

1818
const MediaContainer = styled.div`
1919
position: relative;
@@ -248,8 +248,14 @@ export default {
248248
title: 'Link or download',
249249
of: [
250250
{ type: 'linkSelector', title: 'Link' },
251-
{ type: 'downloadableImage', title: 'Call to action: Download image' },
252-
{ type: 'downloadableFile', title: 'Call to action: Download file' },
251+
{
252+
type: 'downloadableImage',
253+
title: 'Call to action: Download image',
254+
},
255+
{
256+
type: 'downloadableFile',
257+
title: 'Call to action: Download file',
258+
},
253259
],
254260
validation: (Rule: Rule) => Rule.max(1).error('Only one is permitted'),
255261
},

‎sanityv3/schemas/objects/tabs/tabs.tsx‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/* eslint-disable @typescript-eslint/ban-ts-comment */
2-
import { defineField, defineType, PreviewProps, type Rule } from 'sanity'
2+
3+
import { Flex, Stack, Text } from '@sanity/ui'
4+
import { defineField, defineType, type PreviewProps, type Rule } from 'sanity'
35
import blocksToText from '../../../helpers/blocksToText'
6+
import { capitalizeFirstLetter } from '../../../helpers/formatters'
7+
import type { ColorSelectorValue } from '../../components/ColorSelector'
48
import CompactBlockEditor from '../../components/CompactBlockEditor'
9+
import { CardTheme, type ThemeSelectorValue } from '../../components/ThemeSelector'
510
import { configureTitleBlockContent } from '../../editors'
611
import { configureBlockContent } from '../../editors/blockContentType'
7-
import type { ColorSelectorValue } from '../../components/ColorSelector'
8-
import { Flex, Stack, Text } from '@sanity/ui'
9-
import { capitalizeFirstLetter } from '../../../helpers/formatters'
10-
import { CardTheme, ThemeSelectorValue } from '../../components/ThemeSelector'
1112
import { getColorForTabTheme } from './tabsThemes'
1213

1314
type TabsPreviewProps = {
Lines changed: 86 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { defineField, PortableTextBlock, Role, Rule, set, StringInputProps, useCurrentUser } from 'sanity'
2-
import { configureBlockContent } from '../../editors'
1+
import { Card, Flex, Radio, Text } from '@sanity/ui'
2+
import { useCallback } from 'react'
3+
import { HiOutlineInformationCircle } from 'react-icons/hi2'
4+
import { type PortableTextBlock, type Role, type Rule, type StringInputProps, set, useCurrentUser } from 'sanity'
35
import CompactBlockEditor from '../../components/CompactBlockEditor'
4-
import { useCallback, useState } from 'react'
5-
import { Badge, Card, Flex, Grid, Radio, Stack, Text } from '@sanity/ui'
6+
import { configureBlockContent } from '../../editors'
7+
import { backgroundPosition } from '../commonFields/commonFields'
68

79
const titleContentType = configureBlockContent({
810
h2: false,
@@ -27,66 +29,45 @@ type ImageVariantInputProps = {
2729
export const ImageVariantInput = (props: ImageVariantInputProps) => {
2830
const { onChange, schemaType, value = '' } = props
2931

30-
const user = useCurrentUser()
31-
const [error, setError] = useState(false)
32+
//get the role of the current user
33+
//@ts-ignore CurrentUser has roles in types...
34+
const { roles } = useCurrentUser()
35+
36+
const options = schemaType?.options?.list?.filter((option: any) => {
37+
return option.value === 'backgroundImage'
38+
? roles.some((userRole: Role) => userRole.name === 'designer' || userRole.name === 'developer')
39+
: true
40+
})
3241

3342
const handleChange = useCallback(
3443
(event: any) => {
3544
const nextValue = event.currentTarget.value
36-
if (nextValue === 'backgroundImage') {
37-
const isDesigner = user && user.roles.some((userRole: Role) => userRole.name === 'designer')
38-
if (isDesigner) {
39-
onChange(set(nextValue))
40-
} else {
41-
setError(true)
42-
}
43-
} else if (nextValue === 'sideImage') {
44-
if (error) {
45-
setError(false)
46-
}
47-
onChange(set(nextValue))
48-
}
45+
onChange(set(nextValue))
4946
},
50-
[onChange, user, error],
47+
[onChange],
5148
)
5249

5350
return (
54-
<Stack space={3}>
55-
<Grid columns={schemaType?.options?.list?.length} rows={1} gap={2}>
56-
{schemaType?.options?.list?.map((option: any) => {
57-
return (
58-
<Card key={option.value} paddingY={2} paddingX={3} radius={2} shadow={1}>
59-
<Flex direction="row" align="flex-start" gap={2}>
60-
<Radio
61-
checked={value === option.value}
62-
name={option.value}
63-
id={option.value}
64-
onChange={handleChange}
65-
value={option.value}
66-
/>
67-
<Flex direction="column" align={'flex-start'} gap={2}>
68-
<Text as="label" htmlFor={option.value}>
69-
{option.title}
70-
</Text>
71-
{option?.description && (
72-
<Badge tone="primary" fontSize={1}>
73-
{option?.description}
74-
</Badge>
75-
)}
76-
</Flex>
77-
</Flex>
78-
</Card>
79-
)
80-
})}
81-
</Grid>
82-
{error && (
83-
<Card padding={[2]} radius={2} shadow={1} tone="caution">
84-
<Text align="center" size={[1]}>
85-
Cannot perform change, missing designer role!
86-
</Text>
87-
</Card>
88-
)}
89-
</Stack>
51+
<Flex gap={2}>
52+
{options?.map((option: any) => {
53+
return (
54+
<Card key={option.value} paddingY={2} paddingX={3} radius={2}>
55+
<Flex direction="row" align="center" gap={2}>
56+
<Radio
57+
checked={value === option.value}
58+
name={option.value}
59+
id={option.value}
60+
onChange={handleChange}
61+
value={option.value}
62+
/>
63+
<Text as="label" htmlFor={option.value}>
64+
{option.title}
65+
</Text>
66+
</Flex>
67+
</Card>
68+
)
69+
})}
70+
</Flex>
9071
)
9172
}
9273

@@ -95,32 +76,36 @@ export default {
9576
type: 'object',
9677
name: 'tabsInfoPanel',
9778
fields: [
98-
defineField({
99-
name: 'image',
100-
title: 'image',
101-
type: 'image',
102-
options: {
103-
hotspot: true,
104-
},
105-
}),
106-
defineField({
79+
{
10780
name: 'imageVariant',
10881
title: 'Select image variant',
109-
description: 'Use same image variant for all information panels.',
11082
type: 'string',
11183
options: {
11284
list: [
113-
{ title: 'Background image', description: 'Designer only', value: 'backgroundImage' },
85+
{
86+
title: 'Background image',
87+
value: 'backgroundImage',
88+
},
11489
{ title: 'Side image', value: 'sideImage' },
90+
{ title: 'Banner image', value: 'bannerImage' },
11591
],
11692
layout: 'radio',
11793
},
11894
initialValue: 'sideImage',
11995
components: {
12096
input: ImageVariantInput,
12197
},
122-
}),
123-
defineField({
98+
},
99+
{
100+
name: 'image',
101+
title: 'Image',
102+
type: 'image',
103+
options: {
104+
hotspot: true,
105+
},
106+
},
107+
backgroundPosition(),
108+
{
124109
name: 'title',
125110
type: 'array',
126111
components: {
@@ -129,14 +114,14 @@ export default {
129114
of: [titleContentType],
130115
validation: (Rule: Rule) =>
131116
Rule.custom((value: PortableTextBlock[]) => (!value ? 'A title is recommended' : true)).warning(),
132-
}),
133-
defineField({
117+
},
118+
{
134119
name: 'text',
135-
title: 'Text content',
120+
title: 'Content',
136121
type: 'array',
137122
of: [blockContentType],
138-
}),
139-
defineField({
123+
},
124+
{
140125
name: 'action',
141126
type: 'array',
142127
title: 'CTA',
@@ -145,8 +130,16 @@ export default {
145130
{ type: 'downloadableImage', title: 'Call to action: Download image' },
146131
{ type: 'downloadableFile', title: 'Call to action: Download file' },
147132
],
148-
}),
149-
defineField({
133+
validation: (Rule: Rule) => Rule.max(1).error('Only 1'),
134+
},
135+
{
136+
name: 'keyInfoTitle',
137+
title: 'Key figures title',
138+
description:
139+
'Used for context for screen readers.Not visible and optional, but if empty then textsnippet for Key figures will be used',
140+
type: 'string',
141+
},
142+
{
150143
type: 'array',
151144
name: 'keyInfo',
152145
description: 'Up to 4 key information bits',
@@ -164,7 +157,7 @@ export default {
164157
},
165158
{
166159
name: 'keyFigure',
167-
title: 'Key figure highlighted',
160+
title: 'Key figure',
168161
type: 'string',
169162
},
170163
{
@@ -173,9 +166,24 @@ export default {
173166
type: 'text',
174167
},
175168
],
169+
preview: {
170+
select: {
171+
title: 'title',
172+
keyFigure: 'keyFigure',
173+
explanation: 'explanation',
174+
},
175+
prepare(selection: Record<string, string | number>) {
176+
const { title, keyFigure, explanation } = selection
177+
return {
178+
title: `${title ?? ''} ${keyFigure ?? ''}`,
179+
subtitle: `${explanation ?? ''}`,
180+
media: HiOutlineInformationCircle,
181+
}
182+
},
183+
},
176184
},
177185
].filter((e) => e),
178186
validation: (Rule: Rule) => Rule.max(4),
179-
}),
187+
},
180188
],
181189
}

‎sanityv3/schemas/objects/tabs/tabsItem.tsx‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { text_field } from '@equinor/eds-icons'
2-
import { defineField, type PortableTextBlock, type Rule } from 'sanity'
3-
import { EdsIcon } from '../../../icons'
2+
import type { PortableTextBlock, Rule } from 'sanity'
43
import { capitalizeFirstLetter } from '../../../helpers/formatters'
4+
import { EdsIcon } from '../../../icons'
55
import singleItemArray from '../singleItemArray'
66

77
export type TabsItem = {
@@ -31,7 +31,11 @@ export default {
3131
description: 'Add tab panel. Select the same panel type for all tab items',
3232
title: 'Tab panel',
3333
of: [
34-
{ name: 'tabsKeyNumbers', type: 'tabsKeyNumbers', title: 'Key numbers' },
34+
{
35+
name: 'tabsKeyNumbers',
36+
type: 'tabsKeyNumbers',
37+
title: 'Key numbers',
38+
},
3539
{
3640
name: 'tabsInfoPanel',
3741
type: 'tabsInfoPanel',

‎sanityv3/schemas/textSnippets.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,11 @@ const snippets: textSnippet = {
903903
defaultValue: 'Please confirm that you are human below and the link will appear.',
904904
group: groups.downloadableFiles,
905905
},
906+
keyFigures: {
907+
title: 'Key figures',
908+
defaultValue: 'Key figures',
909+
group: groups.common,
910+
},
906911
}
907912

908913
type textSnippetGroup = { title: string; hidden?: boolean }

0 commit comments

Comments
 (0)