Skip to content

Commit

Permalink
fix(website): make state local (#958)
Browse files Browse the repository at this point in the history
* chore: upgrade legend state

* fix: make preview page state local

* fix: horizontal overflow and dropdown portal

* refactor: clean up some conditionals

* fix(website): make variable family name explicit

* fix: homepage local state
  • Loading branch information
ayuhito committed Apr 13, 2024
1 parent 054cab6 commit d94c4a3
Show file tree
Hide file tree
Showing 23 changed files with 1,459 additions and 521 deletions.
1,138 changes: 990 additions & 148 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions website/app/components/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ const DropdownBase = ({
<Combobox
store={combobox}
onOptionSubmit={handleValueSelect}
withinPortal={false}
transitionProps={{ duration: 100, transition: 'fade' }}
width={w ?? rem(250)}
>
Expand Down Expand Up @@ -105,7 +104,7 @@ const DropdownBase = ({
/>
)}
<Combobox.Options>
<ScrollArea.Autosize type="scroll" mah={240}>
<ScrollArea.Autosize type="scroll" mah={240} scrollbars="y">
{options}
</ScrollArea.Autosize>
</Combobox.Options>
Expand Down
100 changes: 53 additions & 47 deletions website/app/components/preview/Buttons.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useSelector } from '@legendapp/state/react';
import { observer } from '@legendapp/state/react';
import {
Button,
ColorInput,
Expand All @@ -12,10 +12,11 @@ import {
import { IconEye, IconHorizontal, IconVertical } from '../icons';
import classes from './Buttons.module.css';
import { LanguageSelector } from './Language';
import { previewState } from './observables';
import { type FontIDState } from './observables';
import { SizeSlider } from './SizeSlider';

interface ButtonsProps {
state$: FontIDState;
subsets: string[];
defSubset: string;
hasItalic: boolean;
Expand Down Expand Up @@ -74,52 +75,57 @@ const SliderButton = ({
);
};

const NormalButtonsGroup = ({
subsets,
hasItalic,
defSubset,
}: ButtonsProps) => {
const state = useSelector(previewState);
const NormalButtonsGroup = observer(
({ state$, subsets, hasItalic, defSubset }: ButtonsProps) => {
const lineHeight = state$.preview.lineHeight.get();
const letterSpacing = state$.preview.letterSpacing.get();
const color = state$.preview.color.get();
const transparency = state$.preview.transparency.get();

return (
<>
<LanguageSelector subsets={subsets} defSubset={defSubset} />
<SizeSlider hasItalic={hasItalic} />
<Group grow>
<SliderButton
label="Line Height"
icon={<IconVertical />}
value={state.lineHeight}
setValue={previewState.lineHeight.set}
max={10}
/>
<SliderButton
label="Letter Spacing"
icon={<IconHorizontal />}
value={state.letterSpacing}
setValue={previewState.letterSpacing.set}
min={-20}
max={80}
/>
</Group>
<Group grow>
<ColorInput
className={classes['color-button']}
variant="unstyled"
value={state.color}
onChange={previewState.color.set}
withEyeDropper={false}
return (
<>
<LanguageSelector
state$={state$}
subsets={subsets}
defSubset={defSubset}
/>
<SliderButton
label="Transparency"
icon={<IconEye />}
value={state.transparency}
setValue={previewState.transparency.set}
suffix="%"
/>
</Group>
</>
);
};
<SizeSlider state$={state$} hasItalic={hasItalic} />
<Group grow>
<SliderButton
label="Line Height"
icon={<IconVertical />}
value={lineHeight}
setValue={state$.preview.lineHeight.set}
max={10}
/>
<SliderButton
label="Letter Spacing"
icon={<IconHorizontal />}
value={letterSpacing}
setValue={state$.preview.letterSpacing.set}
min={-20}
max={80}
/>
</Group>
<Group grow>
<ColorInput
className={classes['color-button']}
variant="unstyled"
value={color}
onChange={state$.preview.color.set}
withEyeDropper={false}
/>
<SliderButton
label="Transparency"
icon={<IconEye />}
value={transparency}
setValue={state$.preview.transparency.set}
suffix="%"
/>
</Group>
</>
);
},
);

export { NormalButtonsGroup, SliderButton };
1 change: 1 addition & 0 deletions website/app/components/preview/Configure.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
.scroll-wrapper {
width: rem(332px);
margin-left: auto;
overflow-x: hidden;

border-radius: 4px;

Expand Down
35 changes: 28 additions & 7 deletions website/app/components/preview/Configure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,44 @@ import type { AxisRegistryAll, Metadata, VariableData } from '@/utils/types';
import { CarbonAd } from '../CarbonAd';
import { NormalButtonsGroup } from './Buttons';
import classes from './Configure.module.css';
import { previewState, variableState } from './observables';
import { type FontIDState } from './observables';
import { VariableButtonsGroup } from './VariableButtons';

interface ConfigureProps {
state$: FontIDState;
metadata: Metadata;
variable?: VariableData;
axisRegistry?: AxisRegistryAll;
}

const resetVariation = () => {
previewState.italic.set(false);
variableState.set({});
const resetVariation = (state$: FontIDState) => {
// Reset variation to default
state$.preview.italic.set(false);
state$.variable.set({});
};

const Configure = ({ metadata, variable, axisRegistry }: ConfigureProps) => {
const Configure = ({
state$,
metadata,
variable,
axisRegistry,
}: ConfigureProps) => {
return (
<>
<ScrollArea.Autosize mah="50vh" className={classes['scroll-wrapper']}>
<ScrollArea.Autosize
mah="50vh"
className={classes['scroll-wrapper']}
style={{
overflowX: 'hidden',
}}
scrollbars="y"
>
<Flex gap="xs" className={classes.wrapper}>
<Text className={classes.title} mb={4}>
Settings
</Text>
<NormalButtonsGroup
state$={state$}
subsets={metadata.subsets}
defSubset={metadata.defSubset}
hasItalic={metadata.styles.includes('italic')}
Expand All @@ -45,11 +60,17 @@ const Configure = ({ metadata, variable, axisRegistry }: ConfigureProps) => {
<Divider mt="sm" />
<Group justify="space-between">
<Text className={classes.title}>Variable Axes</Text>
<ActionIcon className={classes.button} onClick={resetVariation}>
<ActionIcon
className={classes.button}
onClick={() => {
resetVariation(state$);
}}
>
<IconRotate />
</ActionIcon>
</Group>
<VariableButtonsGroup
state$={state$}
variable={variable}
axisRegistry={axisRegistry}
/>
Expand Down
59 changes: 32 additions & 27 deletions website/app/components/preview/Language.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
import { useSelector } from '@legendapp/state/react';
import { useEffect } from 'react';
import { observer, useMountOnce } from '@legendapp/state/react';

import { DropdownSimple } from '@/components/Dropdown';
import { subsetToLanguage } from '@/utils/language/subsets';

import { previewState } from './observables';
import { type FontIDState } from './observables';

interface LanguageSelectorProps {
state$: FontIDState;
defSubset: string;
subsets: string[];
}

const LanguageSelector = ({ defSubset, subsets }: LanguageSelectorProps) => {
const language = useSelector(previewState.language);

useEffect(() => {
if (defSubset !== 'latin') {
previewState.language.set(defSubset);
}
}, [defSubset]);

const items = subsets.map((lang) => ({
label: subsetToLanguage(lang),
value: lang,
isRefined: lang === language,
}));

return (
<DropdownSimple
label={subsetToLanguage(language)}
items={items}
refine={previewState.language.set}
w={284}
/>
);
};
const LanguageSelector = observer(
({ state$, defSubset, subsets }: LanguageSelectorProps) => {
// As we assume that defSubset is latin for ssr, we need
// to update the default preview text if defSubset is not latin
// on mount
useMountOnce(() => {
if (defSubset !== 'latin') {
state$.preview.language.set(defSubset);
}
});

const language = state$.preview.language.get();

const items = subsets.map((lang) => ({
label: subsetToLanguage(lang),
value: lang,
isRefined: lang === language,
}));

return (
<DropdownSimple
label={subsetToLanguage(language)}
items={items}
refine={state$.preview.language.set}
w={284}
/>
);
},
);

export { LanguageSelector };
32 changes: 17 additions & 15 deletions website/app/components/preview/SizeSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,47 @@
import { useSelector } from '@legendapp/state/react';
import { observer } from '@legendapp/state/react';
import { ActionIcon, Group, Slider as MantineSlider } from '@mantine/core';

import { DropdownSimple } from '@/components/Dropdown';

import { IconItalic } from '../icons/Italic';
import { previewState, variableState } from './observables';
import { type FontIDState } from './observables';
import classes from './SizeSlider.module.css';

interface SizeSliderProps {
state$: FontIDState;
hasItalic: boolean;
}

const SizeSlider = ({ hasItalic }: SizeSliderProps) => {
const state = useSelector(previewState);
const SizeSlider = observer(({ state$, hasItalic }: SizeSliderProps) => {
const sizes = [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64];

const handleItalic = () => {
previewState.italic.set(!state.italic);
if (variableState.ital.get() === 1) {
variableState.ital.set(0);
state$.preview.italic.toggle();
if (state$.variable.ital.get() === 1) {
state$.variable.ital.set(0);
} else {
variableState.ital.set(1);
state$.variable.ital.set(1);
}
};

const items = sizes.map((size) => ({
label: `${size}px`,
value: String(size),
isRefined: size === state.size,
isRefined: size === state$.preview.size.get(),
}));

const setSize = (size: string) => {
previewState.size.set(Number(size));
state$.preview.size.set(Number(size));
};

const size = state$.preview.size.get();

// className={classes.button}
return (
<Group justify="apart" gap="xs">
<Group className={classes.wrapper}>
<DropdownSimple
label={`${previewState.size.get()} px`}
label={`${size} px`}
items={items}
refine={setSize}
w={84}
Expand All @@ -51,8 +53,8 @@ const SizeSlider = ({ hasItalic }: SizeSliderProps) => {
size="sm"
// eslint-disable-next-line unicorn/no-null
label={null}
value={previewState.size.get()}
onChange={previewState.size.set}
value={size}
onChange={state$.preview.size.set}
w={116}
max={99}
/>
Expand All @@ -61,12 +63,12 @@ const SizeSlider = ({ hasItalic }: SizeSliderProps) => {
className={classes.italic}
onClick={handleItalic}
disabled={!hasItalic}
data-active={state.italic}
data-active={state$.preview.italic.get()}
>
<IconItalic />
</ActionIcon>
</Group>
);
};
});

export { SizeSlider };

0 comments on commit d94c4a3

Please sign in to comment.