Skip to content

Commit

Permalink
Merge pull request #461 from Vizzuality/feat/opacity-manager
Browse files Browse the repository at this point in the history
Front(feat):opacity manager [MARXAN-680][MARXAN-682]
  • Loading branch information
anamontiaga authored Aug 19, 2021
2 parents 95f7a77 + 1852755 commit 2ed7d71
Show file tree
Hide file tree
Showing 27 changed files with 591 additions and 126 deletions.
6 changes: 4 additions & 2 deletions app/components/forms/slider/component.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';

import { Story } from '@storybook/react/types-6-0';

import Slider, { SliderProps } from './component';
import Label from '../label';

import Slider, { SliderProps } from './component';

export default {
title: 'Components/Forms/Slider',
component: Slider,
Expand All @@ -12,7 +14,7 @@ export default {
theme: {
control: {
type: 'select',
options: ['dark', 'light'],
options: ['dark', 'light', 'light-small'],
},
},
status: {
Expand Down
18 changes: 13 additions & 5 deletions app/components/forms/slider/component.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import cx from 'classnames';
import { useSliderState } from '@react-stately/slider';
import { useSlider } from '@react-aria/slider';

import { useNumberFormatter } from '@react-aria/i18n';
import { setInteractionModality } from '@react-aria/interactions';
import { useSlider } from '@react-aria/slider';
import { useSliderState } from '@react-stately/slider';
import cx from 'classnames';

import Thumb from './thumb';

Expand All @@ -22,6 +23,13 @@ const THEME = {
filledTrack: 'absolute left-0 h-1.5 bg-gray-800 rounded',
track: 'w-full h-1.5 bg-gray-300 rounded opacity-20',
},
'dark-small': {
base: 'w-full h-12 pt-8 touch-action-none',
output:
'absolute bottom-1 transform -translate-y-full -translate-x-1/2 text-xs text-black',
filledTrack: 'absolute left-0 h-1.5 bg-black rounded',
track: 'w-full h-1.5 bg-gray-300 rounded opacity-20',
},
};

export interface SliderProps {
Expand All @@ -32,7 +40,7 @@ export interface SliderProps {
/**
* Theme of the component
*/
theme?: 'dark' | 'light';
theme?: 'dark' | 'light' | 'dark-small';
/**
* Validation status of the input. If the `disabled` prop is set to `true`, it is overwritten to
* `'disabled'`.
Expand Down Expand Up @@ -134,7 +142,7 @@ export const Slider: React.FC<SliderProps> = ({
// component's status isn't updated
// Calling `setInteractionModality` make sure the component is in the focus status
React.useEffect(() => {
const label = labelRef.current;
const label = labelRef?.current;
// Why `'keyboard'`? This is based on React Aria's on code:
// https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/slider/src/useSlider.ts#L178-L181
const handler = () => setInteractionModality('keyboard');
Expand Down
23 changes: 18 additions & 5 deletions app/components/forms/slider/thumb/component.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import cx from 'classnames';
import { SliderState } from '@react-stately/slider';
import { useSliderThumb } from '@react-aria/slider';

import { useFocusRing } from '@react-aria/focus';
import { VisuallyHidden } from '@react-aria/visually-hidden';
import { useSliderThumb } from '@react-aria/slider';
import { mergeProps } from '@react-aria/utils';
import { VisuallyHidden } from '@react-aria/visually-hidden';
import { SliderState } from '@react-stately/slider';
import cx from 'classnames';

const THEME = {
dark: {
Expand All @@ -31,10 +32,22 @@ const THEME = {
disabled: 'border-white',
},
},
'dark-small': {
thumb:
'cursor-pointer absolute top-0 w-4 h-4 transform -translate-x-1/2 rounded-full bg-gray-700 border-2',
status: {
default: 'border-white',
dragging: 'border-white opacity-80',
focused: 'border-white ring-2 ring-primary-500',
valid: 'border-green-500',
error: 'border-red-500',
disabled: 'border-white',
},
},
};

export interface ThumbProps {
theme: 'dark' | 'light';
theme: 'dark' | 'light' | 'dark-small';
status: 'none' | 'valid' | 'error' | 'disabled';
sliderState: SliderState;
trackRef: React.MutableRefObject<HTMLElement | null>;
Expand Down
71 changes: 70 additions & 1 deletion app/components/map/legend/item/component.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import React, { Children, isValidElement, ReactNode } from 'react';
import React, {
Children, isValidElement, ReactNode,
} from 'react';

import cx from 'classnames';

import Slider from 'components/forms/slider';
import Icon from 'components/icon';
import Tooltip from 'components/tooltip';

import OPACITY_SVG from 'svgs/map/opacity.svg?sprite';
import DRAG_SVG from 'svgs/ui/drag.svg?sprite';
import HIDE_SVG from 'svgs/ui/hide.svg?sprite';
import SHOW_SVG from 'svgs/ui/show.svg?sprite';

export interface LegendItemProps {
id: string;
Expand All @@ -19,6 +26,16 @@ export interface LegendItemProps {
};
listeners?: Record<string, unknown>;
attributes?: Record<string, unknown>;
settingsManager?: {
opacity: boolean,
visibility: boolean,
}
settings?: {
opacity: number,
visibility: boolean,
}
onChangeOpacity?: () => void;
onChangeVisibility?: () => void;
}

export const LegendItem: React.FC<LegendItemProps> = ({
Expand All @@ -30,11 +47,17 @@ export const LegendItem: React.FC<LegendItemProps> = ({
sortable,
listeners,
attributes,
settingsManager,
settings,
onChangeOpacity,
onChangeVisibility,
}: LegendItemProps) => {
const validChildren = Children.map(children, (Child) => {
return isValidElement(Child);
}).some((c) => !!c);

const { opacity = 1, visibility = true } = settings || {};

return (
<div
key={id}
Expand Down Expand Up @@ -71,6 +94,52 @@ export const LegendItem: React.FC<LegendItemProps> = ({
{description}
</div>

<div className="flex space-x-3">
{settingsManager?.opacity && (
<div className="mt-2.5 flex">
<Tooltip
arrow
placement="top-start"
trigger="click"
interactive
content={(
<div
className="px-6 pt-1.5 pb-4 text-gray-500 bg-white rounded w-60"
>
<Slider
labelRef={null}
theme="dark-small"
defaultValue={opacity}
formatOptions={{
style: 'percent',
}}
maxValue={1}
minValue={0}
step={0.01}
onChange={onChangeOpacity}
/>
</div>
)}
>
<button type="button">
<Icon className="w-5" icon={OPACITY_SVG} />
</button>
</Tooltip>
</div>
)}

{settingsManager?.visibility && (
<div className="mt-2.5 flex">
<button
type="button"
onClick={onChangeVisibility}
>
<Icon className="w-5" icon={visibility ? SHOW_SVG : HIDE_SVG} />
</button>
</div>
)}
</div>

{validChildren && (
<div className="mt-2.5">
{children}
Expand Down
1 change: 1 addition & 0 deletions app/components/map/legend/types/basic/component.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';

import cx from 'classnames';

export interface LegendTypeBasicProps {
Expand Down
14 changes: 7 additions & 7 deletions app/components/projects/item/component.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useCallback, useState } from 'react';

import { useMe } from 'hooks/me';
import { useProject } from 'hooks/projects';

import cx from 'classnames';
import { AnimatePresence, motion } from 'framer-motion';
import { usePlausible } from 'next-plausible';
import type { Project } from 'types/project-model';

import Avatar from 'components/avatar';
import { useMe } from 'hooks/me';
import { useProject } from 'hooks/projects';

// import Avatar from 'components/avatar';
import Button from 'components/button';
import Icon from 'components/icon';

Expand All @@ -33,7 +33,7 @@ export const Item: React.FC<ItemProps> = ({
area,
description,
lastUpdateDistance,
contributors = [],
// contributors = [],
style,
onClick,
onDownload,
Expand Down Expand Up @@ -166,7 +166,7 @@ export const Item: React.FC<ItemProps> = ({
</header>

{/* CONTRIBUTORS */}
{!!contributors.length && (
{/* {!!contributors.length && (
<div className="flex items-center mt-4 text-sm">
<p>Contributors:</p>
<ul className="flex ml-1">
Expand All @@ -184,7 +184,7 @@ export const Item: React.FC<ItemProps> = ({
})}
</ul>
</div>
)}
)} */}

<footer className="mt-7">
<div className="flex">
Expand Down
5 changes: 3 additions & 2 deletions app/components/projects/published-item/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const PublishedItem: React.FC<PublishedItemProps> = ({
name,
description,
area,
contributors = [],
// contributors = [],
timesDuplicated,
}: PublishedItemProps) => {
return (
Expand All @@ -31,7 +31,8 @@ export const PublishedItem: React.FC<PublishedItemProps> = ({
<p className="text-sm">{area}</p>
</td>
<td className="pr-6">
{!!contributors.length && contributors?.map((c) => <p key={`${c.id}`} className="text-sm">{c.name}</p>)}
{/* {!!contributors.length && contributors?.map((c) =>
<p key={`${c.id}`} className="text-sm">{c.name}</p>)} */}
</td>
<td className="">
<div className="flex flex-row justify-between pl-10">
Expand Down
44 changes: 44 additions & 0 deletions app/hooks/map/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,42 +36,70 @@ export const LEGEND_LAYERS = {
id: 'pugrid',
name: 'Planning unit grid',
icon: <Icon icon={HEXAGON_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2 fill-none" style={{ color: COLORS.primary }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),

// WDPA
'wdpa-preview': () => ({
id: 'wdpa-preview',
name: 'Protected areas preview',
icon: <Icon icon={SQUARE_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2" style={{ color: COLORS.wdpa }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),
'wdpa-percentage': () => ({
id: 'wdpa-percentage',
name: 'Protected areas',
icon: <Icon icon={HEXAGON_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2" style={{ color: COLORS.wdpa }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),

// Species
bioregional: () => ({
id: 'bioregional',
name: 'Bioregion',
icon: <Icon icon={SQUARE_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2" style={{ color: COLORS.bioregional.default }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),
species: () => ({
id: 'species',
name: 'Species',
icon: <Icon icon={SQUARE_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2" style={{ color: COLORS.species.default }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),
features: () => ({
id: 'features',
name: 'Features',
icon: <Icon icon={HEXAGON_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2" style={{ color: COLORS.features }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),

// ANALYSIS
cost: () => ({
id: 'cost',
name: 'Cost surface',
type: 'gradient',
settingsManager: {
opacity: true,
visibility: true,
},
items: [
{
color: COLORS.cost[0],
Expand All @@ -89,6 +117,10 @@ export const LEGEND_LAYERS = {
id: 'lock-in',
name: 'Included areas',
icon: <Icon icon={HEXAGON_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2 fill-none" style={{ color: COLORS.include }} />,
settingsManager: {
opacity: true,
visibility: true,
},
description: (
<div className="pl-5">
{puIncludedValue.length}
Expand All @@ -105,6 +137,10 @@ export const LEGEND_LAYERS = {
id: 'lock-out',
name: 'Excluded areas',
icon: <Icon icon={HEXAGON_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2 fill-none" style={{ color: COLORS.exclude }} />,
settingsManager: {
opacity: true,
visibility: true,
},
description: (
<div className="pl-5">
{puExcludedValue.length}
Expand All @@ -120,6 +156,10 @@ export const LEGEND_LAYERS = {
id: 'frequency',
name: 'Frequency',
type: 'gradient',
settingsManager: {
opacity: true,
visibility: true,
},
items: [
{
color: COLORS.frequency[0],
Expand All @@ -143,5 +183,9 @@ export const LEGEND_LAYERS = {
id: 'solution',
name: 'Solution selected',
icon: <Icon icon={HEXAGON_SVG} className="w-3.5 h-3.5 mt-0.5 stroke-current stroke-2" style={{ color: COLORS.primary }} />,
settingsManager: {
opacity: true,
visibility: true,
},
}),
};
Loading

0 comments on commit 2ed7d71

Please sign in to comment.