Accessibility / Markdown Parsing

DANA 325 V D U G X C L E N T A R M S B H K Q F P O W I

Objectives

  • Description, code sample, and example from your code presented in markdown. (1 Point)

  • Description, code sample, and example from your code presented in markdown. (1 Point)

  • Description, code sample, and example from your code presented in markdown. (1 Point)

  • Description, code sample, and example from your code presented in markdown. (1 Point)

  • Description, code sample, and example from your code presented in markdown. (1 Point)

  • Description, code sample, and example from your code presented in markdown. (1 Point)

  • Description, code sample, and example from your code presented in markdown. (1 Point)

Please watch the videos under Resources before class.

You objective is to create a page that demonstrates at least 7 leassons learned in regards to acessibility.

Your page should be hosted under /accessiblility.

To get you started here is an example of how this could look like:

Always use labels for form inputs

A label can be separate from a form input. In this case the label should be linked with the form input via id and for:

<label for="user_name">Name</label>
<input type="text" name="user[name]" id="user_name">

A label can also wrap a form input. In this case the id and for attributes are not needed. But everything within <label> </label> is considered part of the label.

<label>
  Name
  <input type="text" name="user[name]">
</label>

Here is an example from my code that correctly uses a label:

def input(%{type: "select"} = assigns) do
  ~H"""
  <div class={@wrapper_class}>
    <.label :if={@label} for={@id} class="block mb-2">{@label}</.label>
    <select
      id={@id}
      name={@name}
      class={[
        "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white phx-no-feedback:focus:ring-blue-500 phx-no-feedback:focus:border-blue-500 phx-no-feedback:dark:focus:ring-blue-500 phx-no-feedback:dark:focus:border-blue-500",
        @errors == [] &&
          "focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-500 dark:focus:border-blue-500",
        @errors != [] &&
          "focus:ring-red-500 focus:border-red-500 dark:focus:ring-red-500 dark:focus:border-red-500"
      ]}
      multiple={@multiple}
      {@rest}
    >
      <option :if={@prompt} value="">{@prompt}</option>
      {Phoenix.HTML.Form.options_for_select(@options, @value)}
    </select>
    <.error :for={msg <- @errors}>{msg}</.error>
  </div>
  """
end

You should be independently research 7 more accessibility "rules" and describe them with a code snippet and a paragraph as well as an example from your code base! Don't forget a heading.

To format code a little better we will be using markdown.

Getting formatted markdown to show

Have you ever wondered how i make code snippets appear formatted like on the course website? We are going to learn this now.

Lets start by adding a new dependency in mix.ex:

  {:mdex, "~> 0.2"},

After refetching our dependencies, wew also want to create a new live view (and an appropriate route to it in the router.ex):

defmodule AppWeb.AccessibilityLive do
  use AppWeb, :live_view

  @impl true
  def render(assigns) do
    ~H"""
    <article class="mt-4 format dark:format-invert max-w-full">
      {@page_content}
    </article>
    """
  end

  @impl true
  def mount(_params, _session, socket) do
    # get markdown content from file
    case File.read(Path.join([:code.priv_dir(:app), "accessibility.md"])) do
      {:ok, content} ->
        content =
          content
          |> MDEx.to_html!(render: [unsafe_: true], features: [sanitize: false])
          |> raw()

        {:ok, assign(socket, :page_content, content)}

      {:error, _} ->
        {:ok, socket
        |> put_flash(:error, "Page content could not be loaded.")
        |> assign(:page_content, nil)}
    end
  end
end

This will read the content of priv/accessibility.md, format it into markdown and ensure it is not santitized (so we can display the content as actual HTML). Finally it will assign it to page_content. In case the file doesn't exist or can't load for any other reason an error message should display.

All that is left to do is add a accessibility.md file in our /priv folder. Here is a starting template:

### Accessibility Concern 1 (TODO: rename)

TODO: Description...

```elixir
# This would display formatted elixir code
IO.inspect("Hello World")
```. TODO: change this line to simply: ```

TODO: More description...

```heex
# This would display formatted embedded elixir and html code
<span>{@content}</span>
```. TODO: change this line to simply: ```

#### Sample from my code
TODO: add a sample from my own code

### Accessibility Concern 2 (TODO: rename)

### Accessibility Concern 3 (TODO: rename)

### Accessibility Concern 4 (TODO: rename)

### Accessibility Concern 5 (TODO: rename)

### Accessibility Concern 6 (TODO: rename)

### Accessibility Concern 7 (TODO: rename)

This should display the same syntax-highlighted code and text that you observe on the course website.

Formatting HTML Content

The Flowbite Library has a section Typography. This allows us to apply a format class which automatically updates all html elements inside the container. For example:

<article class="format">
  <h1></h1>
</article>

To enable this we will need to add the flowbite library as a npm dependency. Run the following commands:

cd assets
npm install flowbite flowbite-typography
cd ..

If you don't have npm/node installed in your system yet (WSL or OS Mac) do a quick internet research on how to install it.

Afterwards make the following change to your tailwind.config.js file:

plugins: [
  require('flowbite-typography'), // <= ADD THIS
  // ...
Copyright © 2025 Alexander Fuchsberger, Bucknell University. All rights reserved.