Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Themability: Color & Arrow #136

Open
bruskowski opened this issue Apr 1, 2020 · 16 comments
Open

Themability: Color & Arrow #136

bruskowski opened this issue Apr 1, 2020 · 16 comments
Labels
discussion feature Something new is needed help wanted Extra attention is needed

Comments

@bruskowski
Copy link

Is your feature request related to a problem? Please describe.
I'd like to be able to easily change the color scheme of the component and swap the arrow icon.

Describe the solution you'd like
Set key colors through props. Use these as CSS variables throughout the component.

Describe alternatives you've considered
I can override most colors with classes and CSS selectors, but not for every element (e.g. arrow). Some colors are defined with CSS variables, which makes theming easy, others are 'hardcoded'. Sometimes I need to do some 'digging'.

Additional context
I'll open a pull-request, where I've made some smaller tweaks to allow color theming (heavier use of CSS variables, additional props). This is not super complete, though. Also I am not a dev, so please be critical :)

Thanks for this beautiful component, I've wrapped it for Framer X so people can use it for prototyping:
https://packages.framer.com/package/richy/modern-calendar
Intend

@Kiarash-Z
Copy link
Owner

Hi Richard, thank you so much for publishing this for Framer X. It's recommended to discuss the features here and then on a pull request. The changes you want to apply like changing the arrow are really vast. I think instead of implementing dozens of props for customizing one little thing, it's better to have a nice API for theming with some default themes like light or dark.

@bruskowski
Copy link
Author

You're welcome, thank you for building this!

Regarding the API: I see, that makes sense.
Maybe instead of adding a prop for each color, …

  • having the option to override the CSS color variables directly through a custom class might be a better way, or …
  • one theme prop, that can either be a preset like dark and light or an object with all color definitions.

Anyways, my prototyping use case is probably quite atypical, so don't worry too much about it.

@Kiarash-Z
Copy link
Owner

I think the second option is way better. I need others opinion about this API 🤔 I gotta pin this issue.

@Kiarash-Z Kiarash-Z added the help wanted Extra attention is needed label Apr 5, 2020
@Kiarash-Z Kiarash-Z pinned this issue Apr 5, 2020
@alessandrojcm
Copy link

Hi there! I really need to change the arrow as well, has been any development on this? Or maybe there's a workaround in the meantime? 🤔 Like @richardbruskowski said, one can get by overriding classes, but I had no luck with the arrows 😕

@Kiarash-Z
Copy link
Owner

Hi @alessandrojcm, I need more feedbacks to make a decision about the full customizability API 🤔 Arrows are placed into the calendar using background-image. Therefore, for now, you can override the default arrows by overriding the background-image for .Calendar__monthArrow CSS class:

image

@alessandrojcm
Copy link

alessandrojcm commented May 30, 2020

Hi @Kiarash-Z, yes that was I was trying to do; but in our project we're using font awesome for the icons. Those are font icons, so I'm not sure how could I override the calendar's arrow with those. I've tried by setting the content property in the ::after pseudo-class and applying the font awesome classes with @extend, but no luck 😕

Regarding the API, I think that having an object which defines the theme would work; something among the lines of ThemeUI or TailwindCSS, where you defined all the variables in an object, then that could be applied via CSS custom properties. Now, with the arrow, I think render props could work: the calendar would pass a callback to the render prop that triggers next/previous date and then the user could just use whatever component they like; also, if you go with the theme object, the render prop could pass also the color variables. What do you think?

@Kiarash-Z
Copy link
Owner

@alessandrojcm Yeah, I think this type of config might be good:

const getConfig = (defaultValues) => {
  textColor: defaultValues.defaultColor,
  // many other properties here...
  renderArrows: (position) => <i className={position === 'left' ? 'left' : 'right'} />
}

<Calendar configure={getConfig} />

Or I might just define a separate prop for rendering arrows 🤔

@alessandrojcm
Copy link

@Kiarash-Z Yeah I agree, arrows should be a different prop. With the render props approach, I mentioned could look like this:

<Calendar>
    {({ prevMonth, prevStyles }, { nextMonth, nextStyles }) => (
        <CustomLeftArrow callback={prevMonth} className={prevStyles} />
        <CustomRightArrow callback={nextMonth} className={nextStyles} />
    )}
</Calendar>

Pros are that the user has full control of what to render, cons are that you couldn't get to fancy with the animations, you could pass the animations via the styles, but it would be up to the user to have the animations play nicely with their components. Also, there is the problem of the month/year selector: it should be rendered between the arrows render props make that difficult, you either pass the component as a prop, so the user is responsible for placing it; or you could place it yourself between the custom arrows (maybe using the classes for that, but then the user should pass the classes to the arrows.

Another approach I've seen in other libraries is, like you said, exposing props for the arrows:

<Calendar rightArrow={CustomArrowComponent} leftArrow={CustomArrowComponent} />

Those custom components should receive a callback as prop and the calendar would render that and pass the callback. What do you think? 🤔

@Kiarash-Z
Copy link
Owner

@alessandrojcm This is a good approach but for rendering arrows. For the styles, I guess it's the developer's duty to provide appropriate styles when customizing arrows. For rendering arrows, I think it's kind of verbose to expose two props; one for each arrow. Therefore, I would rather pass an isLeft: boolean to renderArrows prop. It could look like this:

const renderArrows = ({ isLeftArrow, goToPreviousMonth, goToNextMonth }) => {
  if (isLeftArrow) return <CustomLeftArrow className="MyCustomLeftArrow" onClick={goToPreviousMonth} />
  return <CustomRightArrow className="className="MyCustomRightArrow" onClick={goToNextMonth} />
}

<Calendar renderArrows={renderArrows} />

I would be glad to hear your ideas 😊

@alessandrojcm
Copy link

alessandrojcm commented Jun 1, 2020

@Kiarash-Z 5 Yeah that would work but, for me at least, passing a component to render both the arrows is kinda strange. How will the calendar render the month/year selector internally?

As for the styles, yes you're right that the dev should be responsible for the styling. But passing at least the colors would be nice for the sake of consistency.

@Kiarash-Z
Copy link
Owner

@alessandrojcm It's quite easy internally:

{renderArrows({ isLeftArrow: true })}
<MonthYearSelector />
{renderArrows({ isLeftArrow: false })}

As for the colors, I think because of their default color(black), it wouldn't be needed to expose them to renderArrows function.

@alessandrojcm
Copy link

@Kiarash-Z oh, I see. Well, regarding the colors, I meant if the user passes a theme (in which the arrow color could change) I think it would be nice to pass that down to the arrows, just to be consistent 🤔

@fandy
Copy link

fandy commented Jul 14, 2020

Any updates on the renderArrows? I think it would be a great addition to the API, along with renderDay and renderHeader.

@setayeshk
Copy link

Hi Is there any possibility of changing the background color of the calendar right now?

@cking3190
Copy link

@setayeshk you can set it through this css:

.custom-calendar {
box-shadow: 0 1em 3em rgba(156, 136, 255,0.2);
background-color: #040320;
color: white;
}

@mohsenasm
Copy link

mohsenasm commented Sep 20, 2023

A temporary solution for now:

cal
<Calendar
  value={selectedDayRange}
  onChange={setSelectedDayRange}
  calendarClassName="custom-calendar"
  calendarSelectedDayClassName="custom-selected"
  calendarRangeStartClassName="custom-start"
  calendarRangeBetweenClassName="custom-between"
  calendarRangeEndClassName="custom-end"/>
.custom-calendar {
  box-shadow: unset !important;
  background-color: unset !important;
  .Calendar__day, .Calendar__monthText, .Calendar__yearText {
    color: white !important;
  }
  .custom-start, .custom-end, .custom-between {
    color: white !important;
    background-color: rgba(0, 128, 255, 0.7) !important;
  }
  .Calendar__monthArrow {
    background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cg class=%27nc-icon-wrapper%27 fill=%27%23ffffff%27%3E%3Cdefs stroke=%27none%27%3E%3C/defs%3E%3Cpath class=%27cls-1%27 d=%27M12 23.25V.75%27 fill=%27none%27 stroke=%27%23ffffff%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 stroke-width=%271.5px%27%3E%3C/path%3E%3Cpath class=%27cls-2%27 d=%27M22.5 11.25L12 .75 1.5 11.25%27 fill=%27none%27 stroke=%27%23ffffff%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 stroke-width=%271.5px%27 fill-rule=%27evenodd%27%3E%3C/path%3E%3C/g%3E%3C/svg%3E") !important;
  }
  .Calendar__monthYear.-shown>*:hover, .Calendar:not(.-noFocusOutline) .Calendar__monthYear.-shown>*:focus, .Calendar__monthYear>*.-activeBackground {
    background: #f5f5f577 !important;
  }
  .Calendar__day:not(.-blank):not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween):not(.-selected):hover {
    background: #eaeaea77 !important;
  }
  .Calendar__day.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
    background: white !important;
  }
  .Calendar__yearSelectorWrapper::after, .Calendar__yearSelectorWrapper::before {
    visibility: hidden !important;
  }
  .Calendar__yearSelectorItem.-active *, .Calendar__monthSelectorItem.-active * {
    background-color: rgba(0, 128, 255, 0.7) !important;
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion feature Something new is needed help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

7 participants