diff --git a/src/design-system/Intro.stories.mdx b/src/design-system/Intro.stories.mdx index ab689cd..ffc9fae 100644 --- a/src/design-system/Intro.stories.mdx +++ b/src/design-system/Intro.stories.mdx @@ -5,7 +5,7 @@ import { palette } from 'roleypoly/design-system/atoms/colors'; - + # Rapid UI diff --git a/src/design-system/atoms/branding/Branding.tsx b/src/design-system/atoms/branding/Branding.tsx index 71dfed5..267cc2a 100644 --- a/src/design-system/atoms/branding/Branding.tsx +++ b/src/design-system/atoms/branding/Branding.tsx @@ -1,94 +1,154 @@ import * as React from 'react'; import { palette } from 'roleypoly/design-system/atoms/colors'; -type LogoProps = { +export type LogoProps = { fill: string; width: number; height: number; circleFill: string; + circleOuterFill: string; typeFill: string; style: object; className: string; + 'data-for'?: string; + 'data-tip'?: string; }; export const Logotype = ({ - fill = palette.taupe500, - width, - height, - circleFill = palette.taupe200, - typeFill, - style, - className, -}: Partial = {}) => ( + typeFill = palette.taupe400, + circleFill = palette.red200, + circleOuterFill = palette.green200, + ...props +}: Partial) => ( - + - - - - + + + + + + + + + - + + + + + + + + ); export const Logomark = ({ - fill = palette.taupe500, - width, - height, - circleFill = palette.taupe200, - typeFill, - style, - className, + circleFill = palette.red200, + circleOuterFill = palette.green200, + ...props }: Partial) => ( - - - - + + - - - - + + + + + + + ); diff --git a/src/design-system/atoms/branding/BrandingOld.tsx b/src/design-system/atoms/branding/BrandingOld.tsx new file mode 100644 index 0000000..2118661 --- /dev/null +++ b/src/design-system/atoms/branding/BrandingOld.tsx @@ -0,0 +1,85 @@ +import * as React from 'react'; +import { palette } from '../colors'; +import { LogoProps } from './Branding'; + +export const LogotypeOld = ({ + fill = palette.taupe500, + width, + height, + circleFill = palette.taupe200, + typeFill, + style, + className, +}: Partial = {}) => ( + + + + + + + + + + + + +); + +export const LogomarkOld = ({ + fill = palette.taupe500, + width, + height, + circleFill = palette.taupe200, + typeFill, + style, + className, +}: Partial) => ( + + + + + + + + + + + + +); diff --git a/src/design-system/atoms/branding/DynamicBranding.stories.tsx b/src/design-system/atoms/branding/DynamicBranding.stories.tsx new file mode 100644 index 0000000..5c1ff02 --- /dev/null +++ b/src/design-system/atoms/branding/DynamicBranding.stories.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import ReactTooltip from 'react-tooltip'; +import styled from 'styled-components'; +import { AllVariants, DynamicLogomark, DynamicLogotype } from './DynamicBranding'; + +export default { + title: 'Atoms/Branding/Dynamic', + component: DynamicLogotype, +}; + +const WrapperDiv = styled.div` + background-color: black; + padding: 2em; +`; + +const Wrapper = (props: { children: React.ReactNode }) => ( + <> + {props.children} + + +); + +export const DynamicLogotype_ = (args) => { + return ( + + + + ); +}; + +export const DynamicLogomark_ = (args) => { + return ( + + + + ); +}; + +export const AllCustomizedLogotypes = () => { + return ( + + {AllVariants.map((variant, idx) => ( +
+ +
+ ))} +
+ ); +}; + +export const AllCustomizedLogomarks = () => { + return ( + + {AllVariants.map((variant, idx) => ( + + ))} + + ); +}; diff --git a/src/design-system/atoms/branding/DynamicBranding.tsx b/src/design-system/atoms/branding/DynamicBranding.tsx new file mode 100644 index 0000000..d58854a --- /dev/null +++ b/src/design-system/atoms/branding/DynamicBranding.tsx @@ -0,0 +1,654 @@ +import * as React from 'react'; +import ReactTooltip from 'react-tooltip'; +import { palette } from '../colors'; +import { SparkleOverlay } from '../sparkle'; +import { Logomark, LogoProps, Logotype } from './Branding'; + +type DynamicLogoProps = Partial & { + currentDate?: Date; +}; + +export const DynamicLogomark = (props: DynamicLogoProps) => { + const variant = React.useMemo(() => getRelevantVariant(props.currentDate), [ + props.currentDate, + ]); + + if (!variant) { + return ; + } + + let tooltipProps = {}; + if (variant.tooltip) { + tooltipProps = { + 'data-tip': variant.tooltip, + // 'data-for': 'dynamic-logomark', + }; + } + + return ( + <> + + + + ); +}; + +export const DynamicLogotype = (props: DynamicLogoProps) => { + const variant = React.useMemo(() => getRelevantVariant(props.currentDate), [ + props.currentDate, + ]); + + if (!variant) { + return ; + } + + let tooltipProps = {}; + if (variant.tooltip) { + tooltipProps = { + 'data-tip': variant.tooltip, + // 'data-for': 'dynamic-logomark', + }; + } + + return ( + <> + + + + ); +}; + +const getRelevantVariant = (currentDate?: Date) => { + for (let variant of AllVariants) { + if (variant.activeIf(currentDate)) return variant; + } + + return null; +}; + +// These should be updated for 2021. +// Please feel free to update with a PR for 2022 or any missing weeks within 2021. +// Rules: +// - common law holidays should have at least 2 extra days before and after +// - pride days should be 1 extra day before and after +// - weeks/months should have no buffer +// - 4/20 is just for 4/20. + +const matchDay = ( + start: Date, + end: Date, + currentDate: Date = new Date(), + staticDate: boolean = false +) => { + if (!staticDate) { + // pre-fill start/end years to simplify + start.setFullYear(currentDate.getFullYear()); + end.setFullYear(currentDate.getFullYear()); + } + + start.setHours(0, 0, 0, 0); + end.setHours(0, 0, 0, 0); + + if (currentDate > start && currentDate < end) { + return true; + } + + return false; +}; + +type Variant = { + activeIf: (currentDate?: Date) => boolean; + sharedProps?: Partial; + tooltip?: string; + Logomark: React.FunctionComponent; + Logotype: React.FunctionComponent; +}; + +export const Trans: Variant = { + // March 31, Nov 13-20+1 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Mar-31'), new Date('2021-Apr-1'), currentDate) || + matchDay(new Date('2021-Nov-13'), new Date('2021-Nov-22'), currentDate), + sharedProps: { + circleFill: '#F7A8B8', + circleOuterFill: '#55CDFC', + typeFill: palette.grey600, + }, + tooltip: 'Roleypoly says trans rights!', + Logomark: (props: DynamicLogoProps) => , + Logotype: (props: DynamicLogoProps) => , +}; + +export const Bi: Variant = { + // Sept 16-23 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Sep-16'), new Date('2021-Sep-24'), currentDate), + sharedProps: { + circleFill: '#D60270', + circleOuterFill: '#9B4F96', + typeFill: '#0038A8', + }, + tooltip: 'Being bi is a lot like a riding a bicycle since they can go both ways.', + Logomark: (props: DynamicLogoProps) => , + Logotype: (props: DynamicLogoProps) => , +}; + +export const Lesbian: Variant = { + // Apr 26 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Apr-25'), new Date('2021-Apt-27'), currentDate), + sharedProps: { + circleFill: '#D362A4', + circleOuterFill: '#A30262', + typeFill: '#FF9A56', + }, + tooltip: "I'm a lesbiab... lesbiam... Less Bien... Girls.", + Logomark: (props: DynamicLogoProps) => ( + + ), + Logotype: (props: DynamicLogoProps) => ( + + ), +}; + +export const Ace: Variant = { + // Oct 24-30 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Oct-24'), new Date('2021-Oct-31'), currentDate), + sharedProps: { + circleFill: '#333', + circleOuterFill: '#84067C', + typeFill: '#CCC', + }, + tooltip: "Sexualn't", + Logomark: (props: DynamicLogoProps) => , + Logotype: (props: DynamicLogoProps) => , +}; + +export const Birthday: Variant = { + // Jan 15 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Jan-15'), new Date('2021-Jan-16'), currentDate), + sharedProps: { + circleFill: 'none', + circleOuterFill: palette.taupe300, + typeFill: palette.taupe500, + }, + tooltip: '๐ŸŽ‰ HAPPY BIRTHDAY ROLEYPOLY ๐ŸŽ‰', + Logomark: (props: DynamicLogoProps) => ( + + + + + + + + + + + + + + + + + + ), + Logotype: (props: DynamicLogoProps) => ( +
+ + + +
+ ), +}; + +export const DevilsLettuce: Variant = { + // Apr 20 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Apr-20'), new Date('2021-Apr-21'), currentDate), + sharedProps: { + circleFill: palette.green400, + circleOuterFill: palette.green200, + typeFill: palette.green400, + }, + tooltip: 'Legalize it.', + Logomark: (props: DynamicLogoProps) => ( + + ), + Logotype: (props: DynamicLogoProps) => ( + + ), +}; + +export const BicycleDay: Variant = { + // Apr 19 + // TODO: hexagon is bestagon + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Apr-19'), new Date('2021-Apr-20'), currentDate), + sharedProps: { + circleFill: palette.gold400, + circleOuterFill: palette.red200, + typeFill: palette.discord400, + }, + tooltip: 'It increases brain complexity.', + Logomark: (props: DynamicLogoProps) => ( + + ), + Logotype: (props: DynamicLogoProps) => ( + + ), +}; + +export const Christmas: Variant = { + // Dec 20-27 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Dec-20'), new Date('2021-Dec-28'), currentDate), + sharedProps: { + circleFill: palette.green200, + circleOuterFill: palette.red200, + typeFill: palette.green400, + }, + tooltip: 'Have yourself a merry little Christmas~', + Logomark: (props: DynamicLogoProps) => ( + + ), + Logotype: (props: DynamicLogoProps) => ( + + ), +}; + +export const NewYear: Variant = { + // Dec 30 - Jan 2 + // TODO: sparkle + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Dec-30'), new Date('2021-Jan-3'), currentDate), + sharedProps: { + circleFill: '#222', + circleOuterFill: palette.red400, + typeFill: '#aaa', + }, + tooltip: 'Fuck 2020. ๐ŸŽ†๐ŸŽ‡๐ŸŽ†๐ŸŽ‡', + Logomark: (props: DynamicLogoProps) => ( + + ), + Logotype: (props: DynamicLogoProps) => ( +
+ + + +
+ ), +}; + +export const LunarNewYear: Variant = { + // Feb 12, 2021 + // Feb 1, 2022 + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Feb-10'), new Date('2021-Feb-13'), currentDate, true) || + matchDay(new Date('2022-Jan-30'), new Date('2022-Feb-3'), currentDate, true), + sharedProps: { + circleFill: palette.red200, + circleOuterFill: palette.gold400, + typeFill: palette.taupe300, + }, + tooltip: 'ๆญๅ–œๅ‘่ดข! ๐ŸŽŠ๐ŸŽ†๐ŸŽ‡', + Logomark: (props: DynamicLogoProps) => ( + + ), + Logotype: (props: DynamicLogoProps) => ( +
+ + + +
+ ), +}; + +export const Pride: Variant = { + // June + activeIf: (currentDate?: Date) => + matchDay(new Date('2021-Jun-1'), new Date('2021-Jul-1'), currentDate), + sharedProps: { + circleOuterFill: palette.taupe200, + typeFill: palette.grey500, + }, + tooltip: 'LOVE WINS. ๐Ÿ’–๐ŸŒˆ๐ŸŒŸ', + Logomark: (props: DynamicLogoProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), + Logotype: (props: DynamicLogoProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), +}; + +export const AllVariants: Variant[] = [ + Trans, + Pride, + Bi, + Lesbian, + Ace, + Birthday, + DevilsLettuce, + BicycleDay, + Christmas, + NewYear, + LunarNewYear, +]; diff --git a/src/design-system/atoms/branding/index.ts b/src/design-system/atoms/branding/index.ts index e983d1e..8ccce70 100644 --- a/src/design-system/atoms/branding/index.ts +++ b/src/design-system/atoms/branding/index.ts @@ -1 +1,2 @@ export * from './Branding'; +export * from './DynamicBranding'; diff --git a/src/design-system/atoms/colors/colors.tsx b/src/design-system/atoms/colors/colors.tsx index f3a9358..47c2995 100644 --- a/src/design-system/atoms/colors/colors.tsx +++ b/src/design-system/atoms/colors/colors.tsx @@ -16,8 +16,10 @@ export const palette = { discord500: '#99AAB5', green400: '#46B646', + green200: '#1D8227', red400: '#E95353', + red200: '#F14343', gold400: '#EFCF24', diff --git a/src/design-system/atoms/sparkle/Shapes.tsx b/src/design-system/atoms/sparkle/Shapes.tsx index 5cebe02..10bb19a 100644 --- a/src/design-system/atoms/sparkle/Shapes.tsx +++ b/src/design-system/atoms/sparkle/Shapes.tsx @@ -49,7 +49,7 @@ const Animation = (props: SparkleProps) => ( const SparkleCircle = (props: SparkleProps) => ( - + @@ -62,7 +62,7 @@ const SparkleStar = (props: SparkleProps) => ( ( diff --git a/src/design-system/atoms/sparkle/Sparkle.tsx b/src/design-system/atoms/sparkle/Sparkle.tsx index 5061119..6241247 100644 --- a/src/design-system/atoms/sparkle/Sparkle.tsx +++ b/src/design-system/atoms/sparkle/Sparkle.tsx @@ -9,6 +9,7 @@ type Props = { size?: number; opacity?: number; repeatCount?: number; + strokeColor?: string; }; const SparkleContainer = styled.div` @@ -33,18 +34,18 @@ const SparkleEffect = styled.div` pointer-events: none; `; -export const SparkleOverlay = (props: Props) => ( +export const SparkleOverlay = ({ strokeColor = palette.gold400, ...props }: Props) => ( {props.children} diff --git a/src/design-system/organisms/masthead/Authed.tsx b/src/design-system/organisms/masthead/Authed.tsx index fc87687..31c5412 100644 --- a/src/design-system/organisms/masthead/Authed.tsx +++ b/src/design-system/organisms/masthead/Authed.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { GoOrganization } from 'react-icons/go'; import { GuildEnumeration, RoleypolyUser } from 'roleypoly/common/types'; import { guildEnum } from 'roleypoly/common/types/storyData'; -import { Logomark } from 'roleypoly/design-system/atoms/branding'; +import { DynamicLogomark } from 'roleypoly/design-system/atoms/branding'; import { Popover } from 'roleypoly/design-system/atoms/popover'; import { GuildNav } from 'roleypoly/design-system/molecules/guild-nav'; import { NavSlug } from 'roleypoly/design-system/molecules/nav-slug'; @@ -35,7 +35,7 @@ export const Authed = (props: Props) => { - + ( @@ -17,7 +17,7 @@ export const Guest = () => ( - + diff --git a/src/design-system/organisms/masthead/Masthead.styled.tsx b/src/design-system/organisms/masthead/Masthead.styled.tsx index b0193f1..935e888 100644 --- a/src/design-system/organisms/masthead/Masthead.styled.tsx +++ b/src/design-system/organisms/masthead/Masthead.styled.tsx @@ -70,6 +70,7 @@ export const InteractionBase = styled.div` export const MastheadA = styled.a` display: flex; align-items: center; + justify-content: center; color: unset; text-decoration: unset; `;