diff --git a/sources/lib/components/station_ui/HTML/accordion.ex b/sources/lib/components/station_ui/HTML/accordion.ex deleted file mode 100644 index 8a2f888..0000000 --- a/sources/lib/components/station_ui/HTML/accordion.ex +++ /dev/null @@ -1,139 +0,0 @@ -defmodule StationUI.HTML.Accordion do - use Phoenix.Component - - import StationUI.HTML.Icons, only: [icon: 1] - alias Phoenix.LiveView.JS - - @moduledoc """ - The accordion component renders a list of items with child content that can be expanded or collapsed. - - ## Example - - <.accordion_set> - <:header> - Title something 1 - - <:content> - Content something 1 - - - - Suggested size classes - - The Default size for accordions is "md" but the size can be change by passing in these additional classes - using `header_size_class="..."` and `content_size_class="..."` as follows - - header_size_class: - - sm: "p-1 text-base sm:text-lg gap-x-0.5" - md: "p-1 text-base sm:text-lg md:text-xl md:py-1 md:pr-1 md:pl-1.5 md:gap-x-1" - lg: "p-1 text-base sm:text-lg md:text-xl lg:text-2xl md:py-1 md:pr-1 md:pl-1.5 lg:pl-2 md:gap-x-1 lg:gap-x-1.5" - xl: "p-1 text-base sm:text-lg md:text-xl lg:text-2xl xl:text-3xl md:pt-1 md:pb-0 md:pr-1 md:pl-1.5 lg:pl-4 sm:gap-x-3 md:gap-x-4 lg:gap-x-5" - - content_size_class: - - sm: "text-base" - md: "grid transition-grid-rows text-base md:text-lg" - lg: "md:text-lg lg:text-xl" - xl: "md:text-lg lg:text-xl xl:text-2xl" - """ - - def accordion(assigns) do - ~H""" - <.accordion_set> - <:header> - Title something 1 - - <:content> - Content something 1 - - - """ - end - - slot :header, required: true do - attr :button_id, :string - end - - slot :content, required: true - attr :header_size_class, :string, default: "text-base sm:text-lg md:text-xl" - attr :content_size_class, :string, default: "text-base md:text-lg" - attr :rest, :global - - def accordion_set(assigns) do - assigns = - assigns - |> assign(:header, List.wrap(assigns.header)) - |> assign(:content, List.wrap(assigns.content)) - |> assign(:random_id, :rand.uniform(9999)) - |> assign(:items, Enum.with_index(Enum.zip(List.wrap(assigns.header), List.wrap(assigns.content)))) - - ~H""" -
-
- <% # Accordion Trigger %> - - - <% # Accordion Content %> - -
-
- """ - end -end diff --git a/sources/lib/components/station_ui/HTML/avatars.ex b/sources/lib/components/station_ui/HTML/avatars.ex deleted file mode 100644 index e2e366f..0000000 --- a/sources/lib/components/station_ui/HTML/avatars.ex +++ /dev/null @@ -1,239 +0,0 @@ -defmodule StationUI.HTML.Avatars do - use Phoenix.Component - - import StationUI.HTML.StatusBadges, only: [status_badge: 1] - - @moduledoc """ - The avatar component renders initials, an SVG, or an image thumbnail to represent a user. - Avatars can be displayed as single items or combined into a horizontal stack. - - Sets up an avatar stack. - - ## Stack Example - - <.avatar_stack overflow_link={~p"/avatars/link"} display_max={2}> - <:avatar> - <.avatar .../> - - <:avatar> - <.avatar .../> - - <:avatar> - <.avatar .../> - - <:avatar> - <.avatar .../> - - <.avatar_stack> - - """ - @stack_base_classes [ - "flex items-start [&_div]:flex [&_div]:flex-row-reverse", - "[&>a]:z-20 [&>a]:hover:z-40 [&_div_a_figure]:z-10", - "[&_div_a]:hover:z-30 [&_a:focus-visible]:z-50 [&_a]:active:z-50 [&_a:hover_figure]:ml-0 [&_a:focus-visible_figure]:ml-0" - ] - - def stack_base_classes, do: @stack_base_classes - - attr(:class, :any, default: "[&_div]:ml-1.5 [&_div_figure]:-ml-3.5") - attr(:display_max, :integer, default: 3) - attr(:total_count, :integer, default: nil) - attr(:overflow_link, :string, required: true) - - slot(:avatar) - - def avatar_stack(assigns) do - assigns = - assigns - |> assign(:total_count, assigns.total_count || length(assigns.avatar)) - - ~H""" -
- <.avatar_link :if={@total_count > @display_max} to={@overflow_link} variant="initials" class="h-[42px] w-[42px] border-[--sui-brand-primary-border]"> - <:initials count={true}>+<%= @total_count - @display_max %> - - -
- <%= for {avatar, i} <- Enum.with_index(@avatar), i < @display_max do %> - <%= render_slot(avatar) %> - <% end %> -
-
- """ - end - - @doc """ - An avatar that links somewhere. - - ## Example - - <.avatar_link to={~p"/some/link"} variant="placeholder" /> - - """ - @link_base_classes "rounded-full outline-none transition hover:ring-2 hover:ring-[--sui-brand-primary-muted] focus-visible:ring-[--sui-brand-primary-focus] focus-visible:ring-offset-4 active:ring-[--sui-brand-primary]" - - def link_base_classes, do: @link_base_classes - - attr(:status, :string, values: ~w[active inactive deactivated pending]) - attr(:variant, :string, values: ~w[image initials placeholder]) - attr(:index, :integer) - attr(:name, :string, default: nil) - attr(:image_src, :string, default: nil) - attr(:to, :string, required: true) - attr(:link_class, :any, default: "focus-visible:ring-2 active:ring-1") - attr(:class, :any, default: nil) - - # These are all passed through. - slot :initials do - attr(:count, :boolean) - end - - slot(:placeholder) - - def avatar_link(assigns) do - assigns = - case assigns do - %{class: nil} = assigns -> Map.drop(assigns, [:class]) - assigns -> assigns - end - - ~H""" - - <.avatar {Map.drop(assigns, [:link_class])} /> - - """ - end - - @doc """ - A single avatar - - ## Examples - - Avatar with initials, a border, and an active status icon: - - <.avatar variant="initials" status="active" class="h-[42px] w-[42px] border-[--sui-brand-primary]" /> - - Avatar with placeholder image with a pending status icon: - - <.avatar variant="placeholder" status="pending" /> - - Suggested classes for various sizes: - - xs -> "h-6 w-6 [&_svg]:w-3 text-xs" - - sm -> "h-8 w-8 [&_svg]:w-4 text-sm" - - md -> "h-[42px] w-[42px] [&_svg]:w-[21px]" (default) - - lg -> "h-[52px] w-[52px] [&_svg]:w-[26px] text-lg" - - xl -> "h-16 w-16 [&_svg]:w-8 text-lg" - - """ - @figure_base_classes "relative flex items-center justify-center border rounded-full bg-slate-50 transition-all duration-200 font-sans font-medium uppercase text-[--sui-brand-primary]" - - def figure_base_classes, do: @figure_base_classes - - attr(:status, :string, values: ~w[active inactive deactivated pending]) - attr(:variant, :string, values: ~w[image initials placeholder]) - attr(:index, :integer) - attr(:name, :string, default: nil) - attr(:image_src, :string, default: "") - attr(:class, :any, default: "h-[42px] w-[42px] [&_svg]:w-[21px] border-transparent") - - slot :initials do - attr(:count, :boolean) - end - - # We may have to deal with applying styles to placeholders? - slot(:placeholder) - - def avatar(%{variant: "image"} = assigns) do - ~H""" -
- {@name - <.avatar_status_badge :if={assigns[:status]} status={@status} /> -
- """ - end - - def avatar(%{variant: "initials"} = assigns) do - ~H""" -
-
- - - <%= render_slot(@initials) %> - - <%= @name %> -
- <.avatar_status_badge :if={assigns[:status]} status={@status} /> -
- """ - end - - def avatar(%{variant: "placeholder"} = assigns) do - ~H""" -
- <%= render_slot(@placeholder) || default_avatar_placeholder_icon(assigns) %> - <.avatar_status_badge :if={assigns[:status]} status={@status} /> -
- """ - end - - defp initials_from_name(name) do - String.split(name) |> Enum.map_join(&String.first/1) - end - - @doc """ - The default placeholder icon for a placeholder variant of an avatar. - """ - attr(:name, :string, default: nil) - - def default_avatar_placeholder_icon(assigns) do - ~H""" - - <%= @name %> - - - - - - """ - end - - @doc """ - An avatar-specific status icon. - """ - attr(:status, :string, required: true, values: ~w[active inactive deactivated pending]) - attr(:class, :any, default: nil, doc: "additional or overriding classes") - - def avatar_status_badge(assigns) do - ~H""" - <.status_badge - :if={@status} - status={@status} - class={[ - "absolute -right-px -bottom-px z-10 transition-opacity duration-200", - "after:absolute after:inset-0", - "after:h-full after:w-full after:rounded-full", - "w-3 [&>span]:w-0.5" - ]} - /> - """ - end -end diff --git a/sources/lib/components/station_ui/HTML/banners.ex b/sources/lib/components/station_ui/HTML/banners.ex deleted file mode 100644 index 4192d63..0000000 --- a/sources/lib/components/station_ui/HTML/banners.ex +++ /dev/null @@ -1,72 +0,0 @@ -defmodule StationUI.HTML.Banners do - use Phoenix.Component - - import StationUI.HTML.Icons, only: [icon: 1] - import StationUI.HTML.Buttons - - alias Phoenix.LiveView.JS - - @base_classes "max-w-[800px] text-[--sui-brand-primary-text] w-full rounded-lg border py-2.5 pl-3" - defp base_classes, do: @base_classes - - @doc """ - The banner component renders an enclosed title, description, and close button. - The title content goes into the main inner_block slot. - The optional secondary (lower) content goes into the secondary slot. - - ## Examples - - Default banner with left icon, title, and secondary text: - - <.banner id="icon-title-and-secondary"> - <.icon name="hero-information-circle-solid" class="text-[--sui-brand-primary] shrink-0" /> -

Default Banner with Icon and Secondary

- <:secondary> - Secondary text. - - - - Banner of default size but without border: - - <.banner id="no-border" class="border-transparent [&_span]:h-6 [&_span]:w-6 text-base"> - ... - - - Suggested classes for various text sizes and the default border styling: - - - xs -> "border-[--sui-brand-primary-border] [&_span]:h-3.5 [&_span]:w-3.5 text-xs" - - sm -> "border-[--sui-brand-primary-border] [&_span]:h-4.5 [&_span]:w-4.5 text-sm" - - md -> "border-[--sui-brand-primary-border] [&_span]:h-6 [&_span]:w-6 text-base" (the default) - - lg -> "border-[--sui-brand-primary-border] [&_span]:h-9 [&_span]:w-9 text-xl" - - xl -> "border-[--sui-brand-primary-border] [&_span]:h-12 [&_span]:w-12 text-3xl" - """ - - slot :inner_block, required: true - slot :secondary - - attr :id, :string, required: true - attr :class, :any, default: "border-[--sui-brand-primary-border] [&_span]:h-6 [&_span]:w-6 text-base" - attr :on_cancel, JS, default: %JS{} - - def banner(assigns) do - ~H""" -
-
-
- <%= render_slot(@inner_block) %> -
- <.button class="sui-secondary min-h-11 border-0 bg-white" aria-label="Dismiss" phx-click={hide_banner(@on_cancel, @id)}> - <.icon name="hero-x-mark" /> - -
-

<%= render_slot(@secondary) %>

-
- """ - end - - defp hide_banner(js, id) do - js - |> JS.hide(to: "##{id}") - |> JS.pop_focus() - end -end diff --git a/sources/lib/components/station_ui/HTML/buttons.ex b/sources/lib/components/station_ui/HTML/buttons.ex deleted file mode 100644 index 44bd6f5..0000000 --- a/sources/lib/components/station_ui/HTML/buttons.ex +++ /dev/null @@ -1,84 +0,0 @@ -defmodule StationUI.HTML.Buttons do - use Phoenix.Component - - @moduledoc """ - The button component renders a - """ - end - - defp base_classes do - ~w" - [:where(&)]:rounded-lg - [:where(&)]:text-base - - py-[7px] - bg-[--sui-bg-btn] - border-[--sui-border-btn] - text-[--sui-text-btn] - inline-flex - items-center - justify-center - gap-x-1.5 - whitespace-nowrap - border - px-4 - font-bold - - hover:bg-[--sui-bg-btn-hover] - hover:border-[--sui-border-btn-hover] - hover:text-[--sui-text-btn-hover] - - focus-visible:outline-none - focus-visible:ring-2 - focus-visible:ring-purple-500 - focus-visible:ring-offset-4 - - active:bg-[--sui-bg-btn-active] - active:border-[--sui-border-btn-active] - active:text-[--sui-text-btn-active] - - disabled:bg-[--sui-bg-btn-disabled] - disabled:border-[--sui-border-btn-disabled] - disabled:text-[--sui-text-btn-disabled] - - lg:gap-x-2 - " - end -end diff --git a/sources/lib/components/station_ui/HTML/cards.ex b/sources/lib/components/station_ui/HTML/cards.ex deleted file mode 100644 index 273b511..0000000 --- a/sources/lib/components/station_ui/HTML/cards.ex +++ /dev/null @@ -1,180 +0,0 @@ -defmodule StationUI.HTML.Cards do - use Phoenix.Component - - @moduledoc """ - The cards component renders a self-contained area of content which can contain: - - Title - - Image - - Description - - Date - - Read More link - - The card can utilize either a vertical or horizontal layout. - - ## Examples - - ### Vertical Card - - <.card> - <:header> - A whale leaps out of the water - - <:content> -
- -

- The Whales Are Here! -

-

Nov 12, 2022

-
-

- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Facilis fugiat, aliquam assumenda repellat rerum nostrum. -

- - - Read More - - - - - ### Horizontal Card - - <.card_horizontal> - <:header> - A whale leaps out of the water - - <:content> -
-

- Headline -

-

- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Facilis fugiat, aliquam assumenda repellat rerum nostrum. -

-
- -
- <.button class="w-10 h-10 rounded-full border-0 sui-secondary"> - <.icon name="hero-face-smile-solid" class="w-5 h-5 shrink-0" /> - - <.button class="w-10 h-10 rounded-full border-0 sui-secondary"> - <.icon name="hero-face-smile-solid" class="w-5 h-5 shrink-0" /> - - <.button class="w-10 h-10 rounded-full border-0 sui-secondary"> - <.icon name="hero-face-smile-solid" class="w-5 h-5 shrink-0" /> - -
- - - """ - - @base_classes "@container min-w-[200px] w-full h-full" - defp base_classes, do: @base_classes - - @base_inner_classes "overflow-hidden drop-shadow-md @[425px]:drop-shadow-lg @[625px]:drop-shadow-xl @[850px]:drop-shadow-2xl rounded-xl w-auto h-full" - defp base_inner_classes, do: @base_inner_classes - - @base_content_classes "grid gap-0.5 @[350px]:gap-1 @[425px]:gap-2 p-2 @[425px]:px-4 @[625px]:px-6 @[625px]:py-3 @[850px]:px-8 @[850px]:py-4" - defp base_content_classes, do: @base_content_classes - - attr :class, :any, default: "" - - slot :header - - slot :content, required: true do - attr :class, :string - end - - def card(assigns) do - ~H""" -
-
-
- <%= render_slot(header) %> -
- <.content_card slot={@content} /> -
-
- """ - end - - attr :slot, :any, required: true - - defp content_card(assigns) do - class = - case assigns.slot do - [%{class: class} | _] -> class - _ -> "bg-white" - end - - assigns = assign(assigns, :class, class) - - ~H""" -
- <%= render_slot(@slot) %> -
- """ - end - - @base_horizontal_classes "@container min-w-[200px] w-full h-full" - defp base_horizontal_classes, do: @base_horizontal_classes - - @base_horizontal_inner_classes "overflow-hidden drop-shadow-md @[425px]:drop-shadow-lg @[625px]:drop-shadow-xl @[850px]:drop-shadow-2xl rounded-xl w-full flex" - defp base_horizontal_inner_classes, do: @base_horizontal_inner_classes - - @base_horizontal_content_classes "flex w-full gap-1 py-2 pl-2 @[425px]:py-4 @[425px]:pl-4 @[625px]:py-6 @[625px]:pl-6 @[850px]:py-8 @[850px]:pl-8" - defp base_horizontal_content_classes, do: @base_horizontal_content_classes - - attr :class, :any, default: "" - slot :inner_block, required: true - slot :header - - slot :content do - attr :class, :string - end - - def card_horizontal(assigns) do - ~H""" -
-
-
- <%= render_slot(header) %> -
- <.content_card_horizontal slot={@content} /> -
-
- """ - end - - attr :slot, :any, required: true - - defp content_card_horizontal(assigns) do - class = - case assigns.slot do - [%{class: class} | _] -> class - _ -> "bg-white" - end - - assigns = assign(assigns, :class, class) - - ~H""" -
- <%= render_slot(@slot) %> -
- """ - end -end diff --git a/sources/lib/components/station_ui/HTML/footer.ex b/sources/lib/components/station_ui/HTML/footer.ex deleted file mode 100644 index 5d2d9e1..0000000 --- a/sources/lib/components/station_ui/HTML/footer.ex +++ /dev/null @@ -1,224 +0,0 @@ -defmodule StationUI.HTML.Footer do - use Phoenix.Component - - @moduledoc """ - The Footer component includes "simple" (default), and "columns" variant. - The default variant will list any footer_link slotted in horizontally, while - the columns variant will loop over a grouped list of links under a heading. - - ## Default Footer example - <.footer logo_src={~p"/images/my_logo.png"} logo_alt_text="[Organization name] logo"> - <:footer_link> - <.link patch={~p"/"}> - Home - - - <:footer_link> - <.link href="https://www.foo.com/blog"> - Blog - - - - - ## columns variant - <.footer variant="columns" logo_src={~p"/images/my_logo.png"}> - <:column heading="One"> - <.column_items> - <:footer_link> - <.link patch={~p"/"}> - Home - - - <:footer_link > - <.link href="https://www.foo.com/blog"> - Blog - - - - - <:column heading="Two"> - <.column_items> - <:footer_link> - <.link patch={~p"/"}> - Home - - - <:footer_link> - <.link href="https://www.foo.com/blog"> - Blog - - - - - <./footer> - - ## Both variants accept social links and icons - <.footer> - <:social_icon url="https://www.instagram.com" title="Instagram"> - - ... - - - <:social_icon url="https://www.facebook.com" title="Facebook" class="text-[#1877F2]"> - - ... - - - - """ - - slot :inner_block - - slot :footer_link do - attr :class, :string - end - - slot :column do - attr :heading, :string, required: true - end - - slot :social_icon do - attr :url, :string, required: true - attr :title, :string, required: true - attr :class, :string - end - - attr :variant, :string, default: "simple", values: ~w[simple columns] - attr :logo_src, :string, default: nil - attr :logo_alt_text, :string, default: "" - attr :legal_text, :string, default: "© #{DateTime.utc_now().year} Your Company, Inc. All rights reserved." - - def footer(%{variant: "simple"} = assigns) do - ~H""" - - """ - end - - def footer(%{variant: "columns"} = assigns) do - ~H""" - - """ - end - - slot :footer_link do - attr :class, :string - end - - def column_items(assigns) do - ~H""" - - """ - end - - defp footer_link_base_classes do - ~w" - font-bold - text-4xl - [&_a]:rounded-lg - [&_a:hover]:underline - [&_a:hover]:underline-offset-8 - [&_a:focus-visible]:outline-none - [&_a:focus-visible]:ring-4 - [&_a:focus-visible]:ring-purple-500 - [&_a:focus-visible]:ring-offset-4 - [&_a:focus-visible]:ring-offset-[--sui-brand-secondary-bg] - " - end - - defp social_icons_base_classes do - ~w" - [&_a]:block - [&_a]:rounded-lg - [&_a:focus-visible]:outline-none - [&_a:focus-visible]:ring-4 - [&_a:focus-visible]:ring-purple-500 - [&_a:focus-visible]:ring-offset-4 - [&_a:focus-visible]:ring-offset-[--sui-brand-secondary-bg] - " - end -end diff --git a/sources/lib/components/station_ui/HTML/forms.ex b/sources/lib/components/station_ui/HTML/forms.ex deleted file mode 100644 index 07e0e46..0000000 --- a/sources/lib/components/station_ui/HTML/forms.ex +++ /dev/null @@ -1,100 +0,0 @@ -defmodule StationUI.HTML.Forms do - @moduledoc """ - This module exists to provide the same API as the Phoenix Core Components so as to support - generators that target the Core Components (`mix phx.gen.live`, `mix phx.gen.auth`, etc...) - """ - use Phoenix.Component - alias StationUI.HTML.Inputs - - attr :id, :any, default: nil - attr :name, :any - attr :label, :string, default: nil - attr :value, :any - - attr :type, :string, - default: "text", - values: ~w(checkbox color date datetime-local email file hidden month number password - range radio search select tel text textarea time url week) - - attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form, for example: @form[:email]" - - attr :errors, :list, default: [] - attr :checked, :boolean, doc: "the checked flag for checkbox inputs" - attr :prompt, :string, default: nil, doc: "the prompt for select inputs" - attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2" - attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs" - - attr :rest, :global, include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength - multiple pattern placeholder readonly required rows size step) - - slot :inner_block - - def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do - assigns - |> assign(field: nil, id: assigns.id || field.id) - |> assign(:errors, Enum.map(field.errors, &translate_error(&1))) - |> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end) - |> assign_new(:value, fn -> field.value end) - |> input() - end - - def input(%{type: "checkbox"} = assigns) do - ~H""" - - <:label :if={@label}><%= @label %> - - """ - end - - def input(%{type: "select"} = assigns) do - ~H""" - - <:label :if={@label}><%= @label %> - - """ - end - - def input(%{type: "textarea"} = assigns) do - ~H""" - - <:label :if={@label}><%= @label %> - - """ - end - - def input(assigns) do - ~H""" - - <:label :if={@label}><%= @label %> - - """ - end - - @doc """ - Translates an error message using gettext. - """ - def translate_error({msg, opts}) do - # When using gettext, we typically pass the strings we want - # to translate as a static argument: - # - # # Translate the number of files with plural rules - # dngettext("errors", "1 file", "%{count} files", count) - # - # However the error messages in our forms and APIs are generated - # dynamically, so we need to translate them by calling Gettext - # with our gettext backend as first argument. Translations are - # available in the errors.po file (as we use the "errors" domain). - if count = opts[:count] do - Gettext.dngettext(StationUI.Gettext, "errors", msg, msg, count, opts) - else - Gettext.dgettext(StationUI.Gettext, "errors", msg, opts) - end - end - - @doc """ - Translates the errors for a field from a keyword list of errors. - """ - def translate_errors(errors, field) when is_list(errors) do - for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts}) - end -end diff --git a/sources/lib/components/station_ui/HTML/icons.ex b/sources/lib/components/station_ui/HTML/icons.ex deleted file mode 100644 index 4c54de5..0000000 --- a/sources/lib/components/station_ui/HTML/icons.ex +++ /dev/null @@ -1,28 +0,0 @@ -defmodule StationUI.HTML.Icons do - use Phoenix.Component - - @doc """ - Renders a [Heroicon](https://heroicons.com). - - Heroicons come in three styles – outline, solid, and mini. - By default, the outline style is used, but solid and mini may - be applied by using the `-solid` and `-mini` suffix. - - You can customize the size and colors of the icons by setting - width, height, and background color classes. - - ## Examples - - <.icon name="hero-x-mark-solid" /> - <.icon name="hero-arrow-path" class="ml-1 w-3 h-3 animate-spin" /> - """ - attr(:name, :string, required: true) - attr(:class, :any, default: nil) - attr(:rest, :global) - - def icon(%{name: "hero-" <> _} = assigns) do - ~H""" -