Commit 3dc0d87d authored by tom's avatar tom

tooltip navigation recipe

parent 632ae278
...@@ -5,6 +5,7 @@ import * as React from 'react'; ...@@ -5,6 +5,7 @@ import * as React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
export interface TooltipProps extends ChakraTooltip.RootProps { export interface TooltipProps extends ChakraTooltip.RootProps {
selected?: boolean;
showArrow?: boolean; showArrow?: boolean;
portalled?: boolean; portalled?: boolean;
portalRef?: React.RefObject<HTMLElement>; portalRef?: React.RefObject<HTMLElement>;
...@@ -17,6 +18,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -17,6 +18,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
function Tooltip(props, ref) { function Tooltip(props, ref) {
const { const {
showArrow = true, showArrow = true,
selected,
children, children,
disabled, disabled,
portalled, portalled,
...@@ -36,7 +38,6 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -36,7 +38,6 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
}, []); }, []);
const handleTriggerClick = React.useCallback(() => { const handleTriggerClick = React.useCallback(() => {
// FIXME on mobile tooltip will open and close simultaneously
setOpen((prev) => !prev); setOpen((prev) => !prev);
}, [ ]); }, [ ]);
...@@ -55,10 +56,10 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -55,10 +56,10 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
openDelay={ 100 } openDelay={ 100 }
closeDelay={ 100 } closeDelay={ 100 }
open={ open } open={ open }
onOpenChange={ handleOpenChange } onOpenChange={ isMobile ? undefined : handleOpenChange }
closeOnClick={ false }
{ ...rest } { ...rest }
positioning={ positioning } positioning={ positioning }
closeOnClick={ false }
> >
<ChakraTooltip.Trigger <ChakraTooltip.Trigger
ref={ triggerRef } ref={ triggerRef }
...@@ -69,7 +70,11 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -69,7 +70,11 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
</ChakraTooltip.Trigger> </ChakraTooltip.Trigger>
<Portal disabled={ !portalled } container={ portalRef }> <Portal disabled={ !portalled } container={ portalRef }>
<ChakraTooltip.Positioner> <ChakraTooltip.Positioner>
<ChakraTooltip.Content ref={ ref } p={ 2 } { ...contentProps }> <ChakraTooltip.Content
ref={ ref }
{ ...(selected ? { 'data-selected': true } : {}) }
{ ...contentProps }
>
{ showArrow && ( { showArrow && (
<ChakraTooltip.Arrow> <ChakraTooltip.Arrow>
<ChakraTooltip.ArrowTip/> <ChakraTooltip.ArrowTip/>
......
...@@ -4,7 +4,7 @@ const semanticTokens: ThemingConfig['semanticTokens'] = { ...@@ -4,7 +4,7 @@ const semanticTokens: ThemingConfig['semanticTokens'] = {
// TODO @tom2drum remove *_hover in favor of conditional selectors // TODO @tom2drum remove *_hover in favor of conditional selectors
colors: { colors: {
// NEW TOKENS // NEW TOKENS
buttons: { button: {
outline: { outline: {
fg: { fg: {
DEFAULT: { value: { base: '{colors.blue.600}', _dark: '{colors.blue.300}' } }, DEFAULT: { value: { base: '{colors.blue.600}', _dark: '{colors.blue.300}' } },
...@@ -27,7 +27,7 @@ const semanticTokens: ThemingConfig['semanticTokens'] = { ...@@ -27,7 +27,7 @@ const semanticTokens: ThemingConfig['semanticTokens'] = {
}, },
}, },
}, },
links: { link: {
primary: { primary: {
DEFAULT: { value: { base: '{colors.blue.600}', _dark: '{colors.blue.300}' } }, DEFAULT: { value: { base: '{colors.blue.600}', _dark: '{colors.blue.300}' } },
hover: { value: { base: '{colors.blue.400}' } }, hover: { value: { base: '{colors.blue.400}' } },
...@@ -40,11 +40,24 @@ const semanticTokens: ThemingConfig['semanticTokens'] = { ...@@ -40,11 +40,24 @@ const semanticTokens: ThemingConfig['semanticTokens'] = {
hover: { value: { base: '{colors.blackAlpha.800}', _dark: '{colors.gray.400}' } }, hover: { value: { base: '{colors.blackAlpha.800}', _dark: '{colors.gray.400}' } },
}, },
}, },
tooltip: {
DEFAULT: {
bg: { value: { base: '{colors.gray.700}', _dark: '{colors.gray.200}' } },
fg: { value: { base: '{colors.white}', _dark: '{colors.black}' } },
},
navigation: {
bg: { value: { base: '{colors.blue.50}', _dark: '{colors.gray.800}' } },
fg: {
DEFAULT: { value: '{colors.blue.400}' },
selected: { value: { base: '{colors.blue.700}', _dark: '{colors.gray.50}' } },
},
},
},
text: { text: {
primary: { value: { base: '{colors.blackAlpha.800}', _dark: '{colors.whiteAlpha.800}' } }, primary: { value: { base: '{colors.blackAlpha.800}', _dark: '{colors.whiteAlpha.800}' } },
secondary: { value: { base: '{colors.gray.500}', _dark: '{colors.gray.400}' } }, secondary: { value: { base: '{colors.gray.500}', _dark: '{colors.gray.400}' } },
}, },
globals: { global: {
body: { body: {
bg: { value: { base: '{colors.white}', _dark: '{colors.black}' } }, bg: { value: { base: '{colors.white}', _dark: '{colors.black}' } },
fg: { value: '{colors.text.primary}' }, fg: { value: '{colors.text.primary}' },
...@@ -64,10 +77,10 @@ const semanticTokens: ThemingConfig['semanticTokens'] = { ...@@ -64,10 +77,10 @@ const semanticTokens: ThemingConfig['semanticTokens'] = {
DEFAULT: { value: '{colors.gray.500}' }, DEFAULT: { value: '{colors.gray.500}' },
_dark: { value: '{colors.gray.400}' }, _dark: { value: '{colors.gray.400}' },
}, },
link: { // link: {
DEFAULT: { value: '{colors.blue.600}' }, // DEFAULT: { value: '{colors.blue.600}' },
_dark: { value: '{colors.blue.300}' }, // _dark: { value: '{colors.blue.300}' },
}, // },
link_hovered: { link_hovered: {
DEFAULT: { value: '{colors.blue.400}' }, DEFAULT: { value: '{colors.blue.400}' },
}, },
......
...@@ -9,13 +9,13 @@ import scrollbar from './globals/scrollbar'; ...@@ -9,13 +9,13 @@ import scrollbar from './globals/scrollbar';
const globalCss: Record<string, SystemStyleObject> = { const globalCss: Record<string, SystemStyleObject> = {
body: { body: {
bg: 'globals.body.bg', bg: 'global.body.bg',
color: 'globals.body.fg', color: 'global.body.fg',
'-webkit-tap-highlight-color': 'transparent', '-webkit-tap-highlight-color': 'transparent',
'font-variant-ligatures': 'no-contextual', 'font-variant-ligatures': 'no-contextual',
}, },
mark: { mark: {
bg: 'globals.mark.bg', bg: 'global.mark.bg',
color: 'inherit', color: 'inherit',
}, },
'svg *::selection': { 'svg *::selection': {
......
...@@ -24,42 +24,42 @@ export const recipe = defineRecipe({ ...@@ -24,42 +24,42 @@ export const recipe = defineRecipe({
borderWidth: '2px', borderWidth: '2px',
borderStyle: 'solid', borderStyle: 'solid',
bg: 'transparent', bg: 'transparent',
color: 'buttons.outline.fg', color: 'button.outline.fg',
borderColor: 'buttons.outline.fg', borderColor: 'button.outline.fg',
_hover: { _hover: {
bg: 'transparent', bg: 'transparent',
color: 'buttons.outline.hover', color: 'button.outline.hover',
borderColor: 'buttons.outline.hover', borderColor: 'button.outline.hover',
}, },
}, },
dropdown: { dropdown: {
borderWidth: '2px', borderWidth: '2px',
borderStyle: 'solid', borderStyle: 'solid',
bg: 'transparent', bg: 'transparent',
color: 'buttons.dropdown.fg', color: 'button.dropdown.fg',
borderColor: 'buttons.dropdown.border', borderColor: 'button.dropdown.border',
_hover: { _hover: {
bg: 'transparent', bg: 'transparent',
color: 'buttons.dropdown.hover', color: 'button.dropdown.hover',
borderColor: 'buttons.dropdown.hover', borderColor: 'button.dropdown.hover',
}, },
// When the dropdown is open, the button should be active // When the dropdown is open, the button should be active
_active: { _active: {
bg: 'transparent', bg: 'transparent',
color: 'buttons.dropdown.hover', color: 'button.dropdown.hover',
borderColor: 'buttons.dropdown.hover', borderColor: 'button.dropdown.hover',
}, },
// We have a special state for this button variant that serves as a popover trigger. // We have a special state for this button variant that serves as a popover trigger.
// When any items (filters) are selected in the popover, the button should change its background and text color. // When any items (filters) are selected in the popover, the button should change its background and text color.
// The last CSS selector is for redefining styles for the TabList component. // The last CSS selector is for redefining styles for the TabList component.
_selected: { _selected: {
bg: 'buttons.dropdown.border.selected', bg: 'button.dropdown.border.selected',
color: 'buttons.dropdown.fg.selected', color: 'button.dropdown.fg.selected',
borderColor: 'buttons.dropdown.border.selected', borderColor: 'button.dropdown.border.selected',
_hover: { _hover: {
bg: 'buttons.dropdown.border.selected', bg: 'button.dropdown.border.selected',
color: 'buttons.dropdown.fg.selected', color: 'button.dropdown.fg.selected',
borderColor: 'buttons.dropdown.border.selected', borderColor: 'button.dropdown.border.selected',
}, },
}, },
}, },
......
export { recipe as button } from './button.recipe'; import { recipe as button } from './button.recipe';
export { recipe as link } from './link.recipe'; import { recipe as link } from './link.recipe';
import { recipe as tooltip } from './tooltip.recipe';
export const recipes = {
button,
link,
};
export const slotRecipes = {
tooltip,
};
...@@ -4,24 +4,24 @@ export const recipe = defineRecipe({ ...@@ -4,24 +4,24 @@ export const recipe = defineRecipe({
variants: { variants: {
visual: { visual: {
primary: { primary: {
color: 'links.primary', color: 'link.primary',
_hover: { _hover: {
textDecoration: 'none', textDecoration: 'none',
color: 'links.primary.hover', color: 'link.primary.hover',
}, },
}, },
secondary: { secondary: {
color: 'links.secondary', color: 'link.secondary',
_hover: { _hover: {
textDecoration: 'none', textDecoration: 'none',
color: 'links.primary.hover', color: 'link.primary.hover',
}, },
}, },
subtle: { subtle: {
color: 'links.subtle', color: 'link.subtle',
_hover: { _hover: {
color: 'links.subtle.hover', color: 'link.subtle.hover',
textDecorationColor: 'links.subtle.hover', textDecorationColor: 'link.subtle.hover',
}, },
}, },
}, },
......
import { defineSlotRecipe } from '@chakra-ui/react';
export const recipe = defineSlotRecipe({
slots: [ 'content', 'arrow', 'arrowTip' ],
base: {
content: {
px: '2',
py: '2',
borderRadius: 'sm',
fontWeight: '500',
textStyle: 'sm',
boxShadow: 'md',
zIndex: 'tooltip',
maxW: '320px',
transformOrigin: 'var(--transform-origin)',
_open: {
animationStyle: 'scale-fade-in',
animationDuration: 'fast',
},
_closed: {
animationStyle: 'scale-fade-out',
animationDuration: 'fast',
},
},
arrow: {
'--arrow-size': 'sizes.2',
'--arrow-background': 'var(--tooltip-bg)',
},
arrowTip: {
borderTopWidth: '1px',
borderInlineStartWidth: '1px',
borderColor: 'var(--tooltip-bg)',
},
},
variants: {
visual: {
regular: {
content: {
'--tooltip-bg': 'colors.tooltip.bg',
bg: 'var(--tooltip-bg)',
color: 'tooltip.fg',
},
},
navigation: {
content: {
'--tooltip-bg': 'colors.tooltip.navigation.bg',
bg: 'var(--tooltip-bg)',
color: 'tooltip.navigation.fg',
borderWidth: '0',
borderRadius: 'base',
minW: '120px',
boxShadow: 'none',
textAlign: 'center',
padding: '15px 12px',
_selected: {
color: 'tooltip.navigation.fg.selected',
},
},
arrow: {
display: 'none',
},
arrowTip: {
display: 'none',
},
},
},
},
defaultVariants: {
visual: 'regular',
},
});
...@@ -12,13 +12,14 @@ import shadows from './foundations/shadows'; ...@@ -12,13 +12,14 @@ import shadows from './foundations/shadows';
import { fonts, textStyles } from './foundations/typography'; import { fonts, textStyles } from './foundations/typography';
import zIndex from './foundations/zIndex'; import zIndex from './foundations/zIndex';
import globalCss from './globalCss'; import globalCss from './globalCss';
import * as recipes from './recipes'; import { recipes, slotRecipes } from './recipes';
const customConfig = defineConfig({ const customConfig = defineConfig({
globalCss, globalCss,
theme: { theme: {
breakpoints, breakpoints,
recipes, recipes,
slotRecipes,
semanticTokens, semanticTokens,
textStyles, textStyles,
tokens: { tokens: {
......
...@@ -33,7 +33,7 @@ const NameDomainHistoryTable = ({ history, domain, isLoading, sort, onSortToggle ...@@ -33,7 +33,7 @@ const NameDomainHistoryTable = ({ history, domain, isLoading, sort, onSortToggle
name="arrows/east" name="arrows/east"
boxSize={ 4 } boxSize={ 4 }
transform={ sortIconTransform } transform={ sortIconTransform }
color="link" color="link.primary"
position="absolute" position="absolute"
left={ -5 } left={ -5 }
top={ 0 } top={ 0 }
......
...@@ -33,7 +33,7 @@ const NameDomainsTable = ({ data, isLoading, sort, onSortToggle }: Props) => { ...@@ -33,7 +33,7 @@ const NameDomainsTable = ({ data, isLoading, sort, onSortToggle }: Props) => {
name="arrows/east" name="arrows/east"
boxSize={ 4 } boxSize={ 4 }
transform={ sortIconTransform } transform={ sortIconTransform }
color="link" color="link.primary"
position="absolute" position="absolute"
left={ -5 } left={ -5 }
top={ 0 } top={ 0 }
......
...@@ -4,6 +4,7 @@ import React from 'react'; ...@@ -4,6 +4,7 @@ import React from 'react';
import { Button } from 'toolkit/chakra/button'; import { Button } from 'toolkit/chakra/button';
import { useColorMode } from 'toolkit/chakra/color-mode'; import { useColorMode } from 'toolkit/chakra/color-mode';
import { Switch } from 'toolkit/chakra/switch'; import { Switch } from 'toolkit/chakra/switch';
import { Tooltip } from 'toolkit/chakra/tooltip';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
const ChakraShowcases = () => { const ChakraShowcases = () => {
...@@ -19,7 +20,7 @@ const ChakraShowcases = () => { ...@@ -19,7 +20,7 @@ const ChakraShowcases = () => {
<VStack align="flex-start" gap={ 6 }> <VStack align="flex-start" gap={ 6 }>
<section> <section>
<Heading textStyle="heading.md" mb={ 2 }>Buttons</Heading> <Heading textStyle="heading.md" mb={ 2 }>Buttons</Heading>
<HStack gap={ 4 }> <HStack gap={ 4 } flexWrap="wrap">
<Button>Solid</Button> <Button>Solid</Button>
<Button visual="outline">Outline</Button> <Button visual="outline">Outline</Button>
<Button visual="dropdown">Dropdown</Button> <Button visual="dropdown">Dropdown</Button>
...@@ -35,6 +36,18 @@ const ChakraShowcases = () => { ...@@ -35,6 +36,18 @@ const ChakraShowcases = () => {
<Link visual="subtle">Subtle</Link> <Link visual="subtle">Subtle</Link>
</HStack> </HStack>
</section> </section>
<section>
<Heading textStyle="heading.md" mb={ 2 }>Tooltips</Heading>
<HStack gap={ 4 }>
<Tooltip content="Tooltip content">
<span>Default</span>
</Tooltip>
<Tooltip content="Tooltip content" visual="navigation" selected open>
<span>Navigation</span>
</Tooltip>
</HStack>
</section>
</VStack> </VStack>
</> </>
); );
......
...@@ -112,7 +112,7 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => { ...@@ -112,7 +112,7 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => {
<GridItem colSpan={{ base: 1, lg: 3 }} as="h2" textStyle="h4" mt={{ base: 3, lg: 5 }}> <GridItem colSpan={{ base: 1, lg: 3 }} as="h2" textStyle="h4" mt={{ base: 3, lg: 5 }}>
Public tags/labels Public tags/labels
<Hint label="Submit a public tag proposal for our moderation team to review" ml={ 1 } color="link"/> <Hint label="Submit a public tag proposal for our moderation team to review" ml={ 1 } color="link.primary"/>
</GridItem> </GridItem>
<PublicTagsSubmitFieldAddresses/> <PublicTagsSubmitFieldAddresses/>
<PublicTagsSubmitFieldTags tagTypes={ config?.tagTypes }/> <PublicTagsSubmitFieldTags tagTypes={ config?.tagTypes }/>
......
...@@ -53,7 +53,7 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => { ...@@ -53,7 +53,7 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
noSymbol noSymbol
noLink={ !validTokenAddress } noLink={ !validTokenAddress }
fontWeight="500" fontWeight="500"
color="link" color="link.primary"
w="fit-content" w="fit-content"
/> />
</Box> </Box>
...@@ -90,7 +90,7 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => { ...@@ -90,7 +90,7 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
jointSymbol jointSymbol
noLink={ !validTokenAddress } noLink={ !validTokenAddress }
fontWeight="500" fontWeight="500"
color="link" color="link.primary"
w="fit-content" w="fit-content"
/> />
</Box> </Box>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment