Skip to content

Commit

Permalink
Merge branch 'fix/2805-empty-modify' of github.com:tokens-studio/figm…
Browse files Browse the repository at this point in the history
…a-plugin into fix/2805-empty-modify
  • Loading branch information
macintoshhelper committed Jun 11, 2024
2 parents 6300bec + fc4f8cf commit a880422
Show file tree
Hide file tree
Showing 25 changed files with 482 additions and 184 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-buses-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tokens-studio/figma-plugin": patch
---

Using Select all in Inspect view when you were using a filtered view is now correctly only removing tokens that were selected, instead of all.
5 changes: 5 additions & 0 deletions .changeset/metal-turkeys-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tokens-studio/figma-plugin": patch
---

Fixed an issue where variable references weren't using references from the current theme but from another theme that was using the same token names. If you are creating multiple collections with the same token structure, it's recommended to create them one by one to avoid reference clashes. For the default scenario of where different theme groups don't share the same tokens (recommended), you can create all themes at once.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { DotFilledIcon } from '@radix-ui/react-icons';
import { useTranslation } from 'react-i18next';
import {
Button, DropdownMenu, Stack,
Button, DropdownMenu, Stack, Box
} from '@tokens-studio/ui';
import { Dispatch } from '../store';
import IconChevronDown from '@/icons/chevrondown.svg';
Expand Down Expand Up @@ -78,7 +78,7 @@ export default function ApplySelector() {
</DropdownMenu.Trigger>

<DropdownMenu.Portal>
<DropdownMenu.Content side="top">
<DropdownMenu.Content side="top" css={{ maxWidth: '350px' }}>
{/* TODO: Use DropdownMenu.Label - first add that to `ds` */}
<DropdownMenu.Item disabled>{t('applyTo.applyTo')}</DropdownMenu.Item>
<DropdownMenu.RadioGroup value={updateMode}>
Expand All @@ -91,12 +91,18 @@ export default function ApplySelector() {
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
{t('applyTo.selection.title')}
<Box css={{ color: '$contextMenuFgMuted', fontSize: '$xxsmall' }}>
{t('applyTo.selection.description')}
</Box>
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem data-testid="apply-to-page" value={UpdateMode.PAGE} onSelect={handleApplyPage}>
<DropdownMenu.ItemIndicator>
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
{t('applyTo.page.title')}
<Box css={{ color: '$contextMenuFgMuted', fontSize: '$xxsmall' }}>
{t('applyTo.page.description')}
</Box>
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem
data-testid="apply-to-document"
Expand All @@ -107,6 +113,9 @@ export default function ApplySelector() {
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
{t('applyTo.doc.title')}
<Box css={{ color: '$contextMenuFgMuted', fontSize: '$xxsmall' }}>
{t('applyTo.doc.description')}
</Box>
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
<DropdownMenu.Separator />
Expand All @@ -122,6 +131,9 @@ export default function ApplySelector() {
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
{t('applyTo.variablesStyles.title')}
<Box css={{ color: '$contextMenuFgMuted', fontSize: '$xxsmall' }}>
{t('applyTo.variablesStyles.description')}
</Box>
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem
data-testid="apply-raw-values"
Expand All @@ -132,6 +144,9 @@ export default function ApplySelector() {
<DotFilledIcon />
</DropdownMenu.ItemIndicator>
{t('applyTo.rawValues.title')}
<Box css={{ color: '$contextMenuFgMuted', fontSize: '$xxsmall' }}>
{t('applyTo.rawValues.description')}
</Box>
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@ import { ResolveTokenValuesResult } from '@/utils/tokenHelpers';
import DownshiftInput from './DownshiftInput';
import { getLabelForProperty } from '@/utils/getLabelForProperty';
import { styled } from '@/stitches.config';

const StyledButton = styled('button', {
display: 'block',
width: '1.5rem',
height: '1.5rem',
borderRadius: '$small',
cursor: 'pointer',
});
import { getAliasValue } from '@/utils/alias';
import { ColorPickerTrigger } from './ColorPickerTrigger';

export default function BorderTokenDownShiftInput({
name,
Expand All @@ -23,16 +17,30 @@ export default function BorderTokenDownShiftInput({
handleToggleInputHelper,
onSubmit,
}: {
name: string,
name: string;
value: string;
type: string;
resolvedTokens: ResolveTokenValuesResult[];
handleChange: (property: string, value: string) => void;
setInputValue: (newInputValue: string, property: string) => void;
handleToggleInputHelper?: () => void;
onSubmit: () => void
onSubmit: () => void;
}) {
const handleBorderDownShiftInputChange = React.useCallback((newInputValue: string) => setInputValue(newInputValue, name), [name, setInputValue]);
const [resolvedColor, setResolvedColor] = React.useState<string>(value ? String(value) : '');

React.useEffect(() => {
if (name === 'color' && value && value.startsWith('{')) {
const aliasValue = getAliasValue(value, resolvedTokens);
setResolvedColor(aliasValue ? String(aliasValue) : '');
} else {
setResolvedColor(typeof value === 'string' ? value : '');
}
}, [value, resolvedTokens, name]);

const handleBorderDownShiftInputChange = React.useCallback(
(newInputValue: string) => setInputValue(newInputValue, name),
[name, setInputValue],
);
const getIconComponent = React.useMemo(() => getLabelForProperty(name), [name]);

const { t } = useTranslation(['tokens']);
Expand All @@ -55,13 +63,7 @@ export default function BorderTokenDownShiftInput({
placeholder={mapTypeToPlaceHolder[name as keyof typeof mapTypeToPlaceHolder] as unknown as string}
prefix={
name === 'color' && (
<StyledButton
type="button"
style={{ background: value ?? '#000000', fontSize: 0 }}
onClick={handleToggleInputHelper}
>
{value}
</StyledButton>
<ColorPickerTrigger onClick={handleToggleInputHelper} background={resolvedColor} />
)
}
suffix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ export default function InspectorMultiView({ resolvedTokens, tokenToSearch }: {

const handleSelectAll = React.useCallback(() => {
dispatch.inspectState.setSelectedTokens(
inspectState.selectedTokens.length === uiState.selectionValues.length
inspectState.selectedTokens.length === filteredSelectionValues.length
? []
: uiState.selectionValues.map((v) => `${v.category}-${v.value}`),
: filteredSelectionValues.map((v) => `${v.category}-${v.value}`),
);
}, [dispatch.inspectState, inspectState.selectedTokens.length, uiState.selectionValues]);
}, [dispatch.inspectState, inspectState.selectedTokens.length, filteredSelectionValues]);

const closeOnboarding = React.useCallback(() => {
dispatch.uiState.setOnboardingExplainerInspect(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,40 @@ export default function ExportSetsTab({ selectedSets, setSelectedSets }: { selec

const store = useStore<RootState>();

const [showChangeSets, setShowChangeSets] = React.useState(false);

const allSets = useSelector(allTokenSetsSelector);

const selectedTokenSets = React.useMemo(() => (
usedTokenSetSelector(store.getState())
), [store]);

const {
control, getValues, reset,
} = useForm<FormValues>({
defaultValues: {
tokenSets: { ...selectedTokenSets },
},
});

const [showChangeSets, setShowChangeSets] = React.useState(false);
const [previousSetSelection, setPreviousSetSelection] = React.useState({});

const allSets = useSelector(allTokenSetsSelector);

const availableTokenSets = useSelector(allTokenSetsSelector);

const setsTree = React.useMemo(() => tokenSetListToTree(availableTokenSets), [availableTokenSets]);

const handleCancelChangeSets = React.useCallback(() => {
// DO NOT SAVE THE SET CHANGES
reset(previousSetSelection);
setShowChangeSets(false);
}, [previousSetSelection, reset]);

const handleSaveChangeSets = React.useCallback(() => {
setShowChangeSets(false);
}, []);

const handleShowChangeSets = React.useCallback(() => {
setShowChangeSets(true);
}, []);

const { control, getValues } = useForm<FormValues>({
defaultValues: {
tokenSets: { ...selectedTokenSets },
},
});
setPreviousSetSelection(getValues());
}, [getValues]);

const TokenSetThemeItemInput = React.useCallback((props: React.PropsWithChildren<{ item: TreeItem }>) => (
<Controller
Expand Down Expand Up @@ -134,7 +142,25 @@ export default function ExportSetsTab({ selectedSets, setSelectedSets }: { selec
<Button variant="secondary" size="small" onClick={handleShowChangeSets}>{t('actions.changeSets')}</Button>
</Stack>
</StyledCard>
<Modal size="fullscreen" full compact isOpen={showChangeSets} close={handleCancelChangeSets} backArrow title="Styles and Variables / Export Sets">
<Modal
size="fullscreen"
full
compact
isOpen={showChangeSets}
close={handleCancelChangeSets}
backArrow
title="Styles and Variables / Export Sets"
footer={(
<Stack direction="row" gap={4} justify="between">
<Button variant="secondary" onClick={handleCancelChangeSets}>
{t('actions.cancel')}
</Button>
<Button variant="primary" onClick={handleSaveChangeSets}>
{t('actions.confirm')}
</Button>
</Stack>
)}
>
<Heading>{t('exportSetsTab.changeSetsHeading')}</Heading>
<Link target="_blank" href={docsLinks.sets}>{`${t('generic.learnMore')}${t('docs.referenceOnlyMode')}`}</Link>
<Stack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import { ResolveTokenValuesResult } from '@/utils/tokenHelpers';
import DownshiftInput from './DownshiftInput';
import { ColorPickerTrigger } from './ColorPickerTrigger';
import { getAliasValue } from '@/utils/alias';

export default function SingleBoxShadowDownShiftInput({
name,
Expand All @@ -14,17 +15,31 @@ export default function SingleBoxShadowDownShiftInput({
handleToggleInputHelper,
onSubmit,
}: {
name: string,
name: string;
value: string;
type: string;
resolvedTokens: ResolveTokenValuesResult[];
handleChange: (property: string, value: string) => void;
setInputValue: (newInputValue: string, property: string) => void;
handleToggleInputHelper?: () => void;
onSubmit: () => void
onSubmit: () => void;
}) {
const { t } = useTranslation(['tokens']);
const handleBoxshadowDownShiftInputChange = React.useCallback((newInputValue: string) => setInputValue(newInputValue, name), [name, setInputValue]);
const [resolvedColor, setResolvedColor] = React.useState<string>(value ? String(value) : '');

React.useEffect(() => {
if (name === 'color' && value && value.startsWith('{')) {
const aliasValue = getAliasValue(value, resolvedTokens);
setResolvedColor(aliasValue ? String(aliasValue) : '');
} else {
setResolvedColor(typeof value === 'string' ? value : '');
}
}, [value, resolvedTokens, name]);

const handleBoxshadowDownShiftInputChange = React.useCallback(
(newInputValue: string) => setInputValue(newInputValue, name),
[name, setInputValue],
);
return (
<DownshiftInput
name={name}
Expand All @@ -37,11 +52,9 @@ export default function SingleBoxShadowDownShiftInput({
setInputValue={handleBoxshadowDownShiftInputChange}
placeholder={name === 'color' ? t('colorOrAlias') : t('valueOrAlias')}
prefix={
name === 'color' && value && (
<ColorPickerTrigger
background={value}
onClick={handleToggleInputHelper}
>
name === 'color' &&
resolvedColor && (
<ColorPickerTrigger background={resolvedColor} onClick={handleToggleInputHelper}>
{value}
</ColorPickerTrigger>
)
Expand Down
12 changes: 1 addition & 11 deletions packages/tokens-studio-for-figma/src/app/components/Tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import JSONEditor from './JSONEditor';
import Box from './Box';
import IconListing from '@/icons/listing.svg';
import useTokens from '../store/useTokens';
import parseTokenValues from '@/utils/parseTokenValues';
import parseJson from '@/utils/parseJson';
import AttentionIcon from '@/icons/attention.svg';
import { TokensContext } from '@/context';
import {
Expand Down Expand Up @@ -127,12 +125,6 @@ function Tokens({ isActive }: { isActive: boolean }) {

const handleChangeJSON = React.useCallback((val: string) => {
setError(null);
try {
const parsedTokens = parseJson(val);
parseTokenValues(parsedTokens);
} catch (e) {
setError(`Unable to read JSON: ${JSON.stringify(e)}`);
}
dispatch.tokenState.setStringTokens(val);
}, [dispatch.tokenState]);

Expand Down Expand Up @@ -311,9 +303,7 @@ function Tokens({ isActive }: { isActive: boolean }) {
</Box>
{manageThemesModalOpen && <ManageThemesModal />}
</Box>
<TokensBottomBar
hasJSONError={!!error}
/>
<TokensBottomBar handleError={setError} />
</Box>
</TokensContext.Provider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
import React, { useCallback } from 'react';
import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';

// Components
import { Button } from '@tokens-studio/ui';
import ApplySelector from './ApplySelector';
import Box from './Box';
import StylesDropdown from './StylesDropdown';
import { hasUnsavedChangesSelector } from '@/selectors';
import Stack from './Stack';
import SettingsDropdown from './SettingsDropdown';
import ToolsDropdown from './ToolsDropdown';

// State
import useTokens from '../store/useTokens';
import { hasUnsavedChangesSelector } from '@/selectors';
import { stringTokensSelector } from '@/selectors/stringTokensSelector';
import ToolsDropdown from './ToolsDropdown';

// Utils
import { track } from '@/utils/analytics';
import parseTokenValues from '@/utils/parseTokenValues';
import parseJson from '@/utils/parseJson';

type Props = {
hasJSONError: boolean;
handleError: (error: string) => void;
};

export default function TokensBottomBar({ hasJSONError }: Props) {
export default function TokensBottomBar({ handleError }: Props) {
const hasUnsavedChanges = useSelector(hasUnsavedChangesSelector);
const stringTokens = useSelector(stringTokensSelector);

const { handleJSONUpdate } = useTokens();

const handleSaveJSON = useCallback(() => {
track('Saved in JSON');
handleJSONUpdate(stringTokens);
}, [handleJSONUpdate, stringTokens]);
try {
const parsedTokens = parseJson(stringTokens);
parseTokenValues(parsedTokens);
track('Saved in JSON');
handleJSONUpdate(stringTokens);
} catch (e) {
handleError(`Unable to read JSON: ${JSON.stringify(e)}`);
}
}, [handleError, handleJSONUpdate, stringTokens]);

const { t } = useTranslation(['general']);

Expand All @@ -47,7 +61,7 @@ export default function TokensBottomBar({ hasJSONError }: Props) {
}}
>
<Box css={{ fontSize: '$xsmall' }}>{t('unsavedChanges')}</Box>
<Button variant="primary" disabled={hasJSONError} onClick={handleSaveJSON}>
<Button variant="primary" onClick={handleSaveJSON}>
{t('save')}
{' '}
JSON
Expand Down
Loading

0 comments on commit a880422

Please sign in to comment.