Skip to content

Commit

Permalink
Introduce a "enhanced" theme selector for user settings
Browse files Browse the repository at this point in the history
  • Loading branch information
ivarnakken committed Dec 25, 2024
1 parent 2c2b939 commit dbe5cbd
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 41 deletions.
145 changes: 145 additions & 0 deletions app/routes/users/components/UserSettings/ThemeSelector.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
.label {
font-size: var(--font-size-lg);
margin-bottom: var(--spacing-xs);
}

.themes {
margin-bottom: var(--spacing-md);
}

.optionWrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--spacing-xs);
}

.themeOption {
position: relative;
width: 100px;
height: 100px;
cursor: pointer;
border: 1.5px solid var(--border-gray);
border-radius: var(--border-radius-md);
transition: border-color var(--easing-fast);
overflow: hidden;
}

.themeOption[data-selected='true'],
.themeOption:hover:not(:disabled),
.themeOption:focus:not(:disabled) {
border-color: var(--color-gray-4);
}

.previewContent {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}

.previewBackground {
position: absolute;
inset: 0;
z-index: 0;
}

.previewCard {
position: relative;
margin: var(--spacing-sm);
flex-grow: 1;
border-radius: var(--border-radius-sm);
display: flex;
align-items: center;
justify-content: center;
}

.previewText {
font-size: var(--font-size-lg);
font-weight: 500;
}

.auto .previewBackground {
background: linear-gradient(
135deg,
var(--light-background-color) 0%,
var(--light-background-color) 50%,
var(--dark-background-color) 50%,
var(--dark-background-color) 100%
);
}

.auto .previewCard {
background: linear-gradient(
135deg,
var(--light-card-color) 0%,
var(--light-card-color) 50%,
var(--dark-card-color) 50%,
var(--dark-card-color) 100%
);
}

.auto .previewText {
background: linear-gradient(
135deg,
var(--light-font-color) 0%,
var(--light-font-color) 50%,
var(--dark-font-color) 50%,
var(--dark-font-color) 100%
);
background-clip: text;
color: transparent;
}

.light .previewBackground {
background-color: var(--light-background-color);
}

.light .previewCard {
background-color: var(--light-card-color);
}

.light .previewText {
color: var(--light-font-color);
}

.dark .previewBackground {
background-color: var(--dark-background-color);
}

.dark .previewCard {
background-color: var(--dark-card-color);
}

.dark .previewText {
color: var(--dark-font-color);
}

.checkIcon {
position: absolute;
bottom: var(--spacing-xs);
right: var(--spacing-xs);
padding: calc(var(--spacing-xs) / 2);
border-radius: 50%;
opacity: 0;
transition: opacity var(--easing-fast);
}

.light .checkIcon {
color: var(--dark-font-color);
background: var(--dark-card-color);
}

.auto .checkIcon,
.dark .checkIcon {
color: var(--light-font-color);
background: var(--light-card-color);
}

.themeOption[data-selected='true'] .checkIcon {
opacity: 1;
}

.optionLabel {
font-size: var(--font-size-sm);
}
85 changes: 85 additions & 0 deletions app/routes/users/components/UserSettings/ThemeSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Flex, Icon } from '@webkom/lego-bricks';
import cx from 'classnames';
import { Check, MoonStar, Sun, SunMoon } from 'lucide-react';
import { useEffect } from 'react';
import { Field, useForm } from 'react-final-form';
import { useTheme } from 'app/utils/themeUtils';
import styles from './ThemeSelector.module.css';
import type { ReactNode } from 'react';

type ThemeOption = {
icon: ReactNode;
label: string;
value: 'dark' | 'light' | 'auto';
};

const themeOptions: ThemeOption[] = [
{
icon: <SunMoon />,
label: 'Auto',
value: 'auto',
},
{
icon: <Sun />,
label: 'Lyst',
value: 'light',
},
{
icon: <MoonStar />,
label: 'Mørkt',
value: 'dark',
},
];

const ThemeSelector = () => {
const form = useForm();
const theme = useTheme();

useEffect(() => {
form.change('selectedTheme', theme);
}, [form, theme]);

return (
<div>
<label className={styles.label}>Fargetema</label>
<Flex wrap gap="var(--spacing-md)" className={styles.themes}>
{themeOptions.map((option) => (
<Field
name="selectedTheme"
type="radio"
value={option.value}
key={option.value}
>
{({ input }) => (
<div className={styles.optionWrapper}>
<div
className={cx(styles.themeOption, styles[option.value])}
data-selected={input.checked}
onClick={() => input.onChange(option.value)}
>
<div className={styles.previewBackground} />
<div className={styles.previewContent}>
<div className={styles.previewCard}>
<div className={styles.previewText}>Aa</div>
</div>
</div>
<Icon
iconNode={<Check />}
size={16}
className={styles.checkIcon}
/>
</div>
<Flex alignItems="center" gap="var(--spacing-xs)">
<Icon iconNode={option.icon} size={16} />
<div className={styles.optionLabel}>{option.label}</div>
</Flex>
</div>
)}
</Field>
))}
</Flex>
</div>
);
};

export default ThemeSelector;
33 changes: 3 additions & 30 deletions app/routes/users/components/UserSettings/UserSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@ import { usePreparedEffect } from '@webkom/react-prepare';
import { Field } from 'react-final-form';
import { useNavigate, useParams } from 'react-router-dom';
import { fetchUser, updateUser } from 'app/actions/UserActions';
import {
TextInput,
MultiSelectGroup,
RadioButton,
PhoneNumberInput,
SelectInput,
} from 'app/components/Form';
import { TextInput, PhoneNumberInput, SelectInput } from 'app/components/Form';
import LegoFinalForm from 'app/components/Form/LegoFinalForm';
import SubmissionError from 'app/components/Form/SubmissionError';
import { SubmitButton } from 'app/components/Form/SubmitButton';
Expand All @@ -32,6 +26,7 @@ import {
} from 'app/utils/validation';
import AllergiesOrPreferencesField from '../AllergiesOrPreferencesField';
import ChangePassword from './ChangePassword';
import ThemeSelector from './ThemeSelector';
import UserImage from './UserImage';
import styles from './UserSettings.module.css';
import type { CurrentUser } from 'app/store/models/User';
Expand Down Expand Up @@ -198,29 +193,7 @@ const UserSettings = () => {
/>
</Flex>

<MultiSelectGroup legend="Fargetema" name="selectedTheme">
<Field
name="selectedTheme"
label="Auto"
value="auto"
type="radio"
component={RadioButton.Field}
/>
<Field
name="selectedTheme"
label="Lyst"
value="light"
type="radio"
component={RadioButton.Field}
/>
<Field
name="selectedTheme"
label="Mørkt"
value="dark"
type="radio"
component={RadioButton.Field}
/>
</MultiSelectGroup>
<ThemeSelector />

{showAbakusMembership && (
<Field
Expand Down
29 changes: 18 additions & 11 deletions app/styles/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@
:root {
color-scheme: light;

--lego-background-color: #f8f9fa;
--lego-card-color: #fff;
--light-background-color: #f8f9fa;
--dark-background-color: #0d0d0d;
--light-card-color: #fff;
--dark-card-color: #222;
--light-font-color: #0d0d0d;
--dark-font-color: #f2f2f2;

--lego-font-color: var(--color-gray-9);
--lego-background-color: var(--light-background-color);
--lego-card-color: var(--light-card-color);

--lego-font-color: var(--light-font-color);
--inverted-font-color: var(--color-gray-1);
--secondary-font-color: #606060;
--placeholder-color: var(--color-gray-5);
Expand All @@ -25,7 +32,6 @@
--lego-max-width: 1100px;

--lego-header-height: 120px;
--lego-main-nav-height: 50px;
--development-banner-height: 0px;

--color-event-red: #b11c11;
Expand All @@ -34,7 +40,7 @@
--color-absolute-white: #fff; /* White on dark mode as well */
--color-white: var(--color-absolute-white);
--color-absolute-black: #000; /* Black on dark mode as well */
--color-black: #000;
--color-black: var(--color-absolute-black);

--border-gray: var(--color-gray-2);

Expand All @@ -50,15 +56,15 @@
var(--low-alpha)
);

--color-gray-1: #f2f2f2;
--color-gray-1: var(--dark-font-color);
--color-gray-2: #e7e7e7;
--color-gray-3: #d9d9d9;
--color-gray-4: #b6b6b6;
--color-gray-5: #8c8c8c;
--color-gray-6: #757575;
--color-gray-7: #595959;
--color-gray-8: #373737;
--color-gray-9: #0d0d0d;
--color-gray-9: var(--dark-font-color);

--color-blue-1: #e6f1ff;
--color-blue-2: #cee4fe;
Expand Down Expand Up @@ -169,8 +175,9 @@
[data-theme='dark'] {
color-scheme: dark;

--lego-background-color: #0d0d0d;
--lego-card-color: #222;
--lego-background-color: var(--dark-background-color);
--lego-card-color: var(--dark-card-color);
--lego-font-color: var(--dark-font-color);

--secondary-font-color: #aaa;

Expand All @@ -187,15 +194,15 @@

--low-alpha: 10%;

--color-gray-1: #0d0d0d;
--color-gray-1: var(--light-font-color);
--color-gray-2: #373737;
--color-gray-3: #595959;
--color-gray-4: #757575;
--color-gray-5: #8c8c8c;
--color-gray-6: #b6b6b6;
--color-gray-7: #d9d9d9;
--color-gray-8: #e7e7e7;
--color-gray-9: #f2f2f2;
--color-gray-9: var(--light-font-color);

--color-blue-1: #102a47;
--color-blue-2: #0f3158;
Expand Down

0 comments on commit dbe5cbd

Please sign in to comment.