Skip to content

My First Open Source Contribution

Published:  at 03:35 PM
4 min read

Hello, dear readers! Today, I’m thrilled to share a very special experience: my first open source contribution! 🥳 And to make it even more exciting, this is my first blog post! 😁

I’ve always wanted to contribute to the community since most of the content I relied on to break into the tech industry came from it. Finally, I had the opportunity to give back, and I managed to contribute! (Here’s hoping for many more contributions in the future! Haha)


The Contribution

Although I consider myself a front-end developer, my first contribution was to a project using the Phoenix framework, part of the functional programming language Elixir. 👀

If you’re interested in functional programming, Elixir is an amazing language, created by a Brazilian, and definitely worth checking out! 🇧🇷

How It All Began

My journey started at ElixirDays 2024, during a talk by Zoey Pesanha about her Supabase package for Elixir, called supabase-ex. She mentioned her involvement in the open-source project PEA Pescarte, which aims to support regional fishing community organization. This immediately piqued my interest in contributing.

Shortly after, I explored the project’s issues page and found one about creating a visual calendar component. Time to roll up my sleeves! I read the project guidelines (always important) and checked out the Figma design.


The Creation Process

It was a highly enriching experience. Despite already working in front-end, this was my first time building a date picker from scratch. It came with challenges, and I relied on my friend Freitas for help (shoutout to Freitas!). However, to meet the expectations for navigating between months and years, I had to use an existing solution.

Choosing the Component

After some research, I found Air Datepicker, a framework-agnostic component built purely with JavaScript and CSS. It was customizable enough to meet the project’s needs.


Integrating with Phoenix

The integration process was straightforward. Here’s the Phoenix component code:

doc """
  A date picker component for selecting dates.
  The `name` attribute is required.
  Use the `value` attribute to set an initial value for the component.

  ## Example
      <.date_input name="birthday"/>
  """
attr :name, :string, required: true
attr :class, :string, default: ""
attr :value, :string, default: ""

def date_input(%{field: %Phoenix.HTML.FormField{}} = assigns) do
  assigns
  |> input()
  |> date_input()
end

def date_input(assigns) do
  ~H"""
  <div class={["date_input", @class]}>
    <div class="date_input__container">
      <input type="text" id="air-datepicker" class="input" placeholder="mm/dd/yyyy" value={@value} />
      <Lucideicons.calendar_days class="date_input--suffix" />
    </div>
  </div>
  """
end

Customizing the Locale

I created a custom locale for the calendar since the default one didn’t match the required design:

let customLocale = {
  days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
  daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"],
  daysMin: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"],
  months: [
    "Janeiro",
    "Fevereiro",
    "Março",
    "Abril",
    "Maio",
    "Junho",
    "Julho",
    "Agosto",
    "Setembro",
    "Outubro",
    "Novembro",
    "Dezembro",
  ],
  monthsShort: [
    "Jan",
    "Fev",
    "Mar",
    "Abr",
    "Mai",
    "Jun",
    "Jul",
    "Ago",
    "Set",
    "Out",
    "Nov",
    "Dez",
  ],
  today: "Hoje",
  clear: "Limpar",
  dateFormat: "dd/MM/yyyy",
  timeFormat: "HH:mm",
  firstDay: 0,
};

Styling with SASS

I adapted the style using SASS, which made writing the CSS much easier:

.date_input {
  max-width: 300px;

  &__container {
    position: relative;
    input {
      @apply focus:border-black-10 focus:ring-0 focus:ring-offset-0;
    }
    &:focus-within {
      #air-datepicker {
        border-bottom: none;
        border-radius: 0.25rem 0.25rem 0 0;
      }
      &:after {
        @apply bg-black-10;
        content: "";
        position: absolute;
        left: 12px;
        bottom: 0;
        width: 276px;
        height: 1.5px;
      }
    }
  }

  &--suffix {
    @apply absolute top-3 right-3 disabled:text-black-20 pointer-events-none;
  }
}

Configuration and Behavior

After several attempts, I adjusted the visual behavior using Air Datepicker properties:

new AirDatepicker("#air-datepicker", {
  locale: customLocale,
  navTitles: {
    days: "<i>MMMM</i>",
  },
  autoClose: true,
  position({ $datepicker, $target, $pointer }) {
    let coords = $target.getBoundingClientRect(),
      dpWidth = $datepicker.clientWidth;
    let top = coords.y + coords.height;
    let left = coords.x + (coords.width - 2) / 2 - dpWidth / 2;
    $datepicker.style.left = `${left}px`;
    $datepicker.style.top = `${top}px`;
    $pointer.style.display = "none";
  },
});

Complete Code

You can check out the full contribution code on GitHub

Conclusion

This experience taught me so much and left me feeling fulfilled. It’s amazing to contribute to open-source projects. If you haven’t tried it yet, I encourage you to start today! 😁